Path-following

by roman01la

HTML

<script src="http://static.tumblr.com/m2xstox/Qavmutvbs/gl-matrix-min.js"></script>
<canvas class="viewport" width=480 height=320></canvas>

CSS

body {
    margin: 0;
    padding: 0;
    overflow: hidden;
}
canvas {
    background: #eee;
}

JavaScript

var Path = function() {
  this.points = [];
  this.radius = 0;

  this.addPoint = function (x, y) {
    var point = vec2.fromValues(x, y);

    this.points.push(point);
  };
  this.display = function() {
    ctx.lineJoin = 'round';
    ctx.lineCap = 'round';
    ctx.strokeStyle = '#e7e7e7';
    ctx.lineWidth = this.radius * 2;

    ctx.beginPath();

    for (var i = 0; i < this.points.length; i++) {
      ctx.lineTo(this.points[i][0], this.points[i][1]);
    }
    ctx.closePath();

    ctx.stroke();
  };
};

var Vehicle = function (location, mass) {
  this.location = location;
  this.initMass = mass;
  this.mass = mass;
  this.maxspeed = 4 * 1 / this.mass;
  this.maxforce = 1 / (this.mass * this.maxspeed);
  this.radius = this.mass * 2;
  this.acceleration = vec2.create();
  this.velocity = vec2.fromValues(this.maxspeed, 0);
  this.bouncesNum = 0;

  this.applyBehaviors = function (vehicles, path) {
    var f = this.follow(path);
    var s = this.separate(vehicles);

    if (this.bouncesNum >= 300 && this.bouncesNum % 100 === 0) {
      if (this.maxspeed < 3) {
        this.maxspeed += 0.1;
        this.maxforce += 0.1;
      }
    }

    vec2.scale(f, f, 2);
    vec2.scale(s, s, 4);

    var forces = vec2.add(vec2.create(), f, s);

    vec2.scale(forces, forces, 1/this.mass);

    this.applyForce(forces);
  };
  this.applyForce = function (force) {
    vec2.add(this.acceleration, this.acceleration, force);
  };
  this.run = function() {
    this.update();
    this.borders();
    this.render();
  };
  this.follow = function (path) {
    var predict = vec2.clone(this.velocity);

    vec2.normalize(predict, predict);
    vec2.scale(predict, predict, 25);

    var predictLoc = vec2.create();

    vec2.add(predictLoc, predictLoc, this.location);
    vec2.add(predictLoc, predictLoc, predict);

    var normal = null;
    var target = null;
    var worldRecord = 1000000;

    for (var i = 0; i < path.points.length; i++) {
      var a = vec2.clone(path.points[i]);
     ...