Skip to content

Instantly share code, notes, and snippets.

@milcktoast
Created March 22, 2013 16:39
Show Gist options
  • Select an option

  • Save milcktoast/5222800 to your computer and use it in GitHub Desktop.

Select an option

Save milcktoast/5222800 to your computer and use it in GitHub Desktop.
Car along a quadratic curve.
<div id="canvas"></div>
<div id="info">
<div id="angle"></div>
</div>
<script type="text/javascript" src="https://raw.github.com/toji/gl-matrix/master/dist/gl-matrix.js"></script>
<script type="text/javascript" src="https://raw.github.com/dannygarcia/fil/master/fil.min.js"></script>
var cvs = new fil.Canvas();
var pen = new fil.Pen();
var frame = new fil.Frame();
var infoAngle = document.getElementById("angle");
var el = document.getElementById("canvas");
cvs.init({
container : el,
ratio : false
});
var ctx = cvs.context();
var WIDTH = cvs.width;
var WIDTH_HALF = WIDTH / 2;
var HEIGHT = cvs.height;
var cursor = vec2.create();
var needsUpdate = true;
var QuadraticCurve = function (x, y, width) {
var halfWidth = width / 2;
this.a = vec2.fromValues(x, y);
this.b = vec2.fromValues(x + width, y + halfWidth);
this.c = vec2.fromValues(x, y + width);
};
QuadraticCurve.prototype = {
baseVal : function (t, index) {
var mt = 1 - t;
var a = this.a[index];
var b = this.b[index];
var c = this.c[index];
return mt * mt * a + 2 * mt * t * b + t * t * c;
},
derivativeVal : function (t, index) {
var a = this.a[index];
var b = this.b[index];
var c = this.c[index];
return a * (2 * t - 2) + b * (2 - 4 * t) + 2 * c * t;
},
derivativeRoot : function (index) {
var t = -1;
var a = this.a[index];
var b = this.b[index];
var c = this.c[index];
var denominator = a -2 * b + c;
if(denominator !== 0) {
t = (a - b) / denominator;
}
return t;
},
pointAt : function (v, t) {
v[0] = this.baseVal(t, 0);
v[1] = this.baseVal(t, 1);
},
angleAt : (function () {
var slope = vec2.create();
return function (t) {
slope[0] = this.derivativeVal(t, 0);
slope[1] = this.derivativeVal(t, 1);
vec2.normalize(slope, slope);
var angle = Math.atan2(slope[1], slope[0]);
return angle * 180 / Math.PI;
};
}()),
render : function () {
var a = this.a, b = this.b, c = this.c;
pen.line(a, b, "array");
pen.line(b, c, "array");
ctx.beginPath();
ctx.moveTo(a[0], a[1]);
ctx.quadraticCurveTo(b[0], b[1], c[0], c[1]);
ctx.stroke();
}
};
// Pen does not require initialization, but it does require a canvas context.
pen.context(ctx);
pen.fill("white");
window.onmousemove = function (e) {
cursor[0] = e.pageX;
cursor[1] = e.pageY;
needsUpdate = true;
};
var Car = function (opts) {
this.sprite = new Image();
this.sprite.src = opts.sprite;
this.track = opts.track;
this.spriteLen = opts.spriteLen;
this.angleStep = opts.angleStep;
this.size = opts.size;
this.frame = vec2.create();
this.pos = vec2.create();
this.lastPos = vec2.create();
this.dir = vec2.create();
};
Car.prototype = {
setFrame : function (angle) {
var frame = -Math.round(angle / this.angleStep) + 14;
this.frame[0] = frame;
infoAngle.textContent = frame + " - " + angle;
},
update : function (f) {
var t = cursor[1] / HEIGHT;
// Calc point on track, set pos
this.track.pointAt(this.pos, t);
// Calc angle, set frame
var angle = this.track.angleAt(t);
this.setFrame(angle);
},
render : function (f) {
var s = this.size;
var hs = s / 2;
var f = this.frame;
var p = this.pos;
this.track.render();
ctx.drawImage(this.sprite, s * f[0], s * f[1], s, s, p[0] - hs, p[1] - hs, s, s);
}
};
var car = new Car({
sprite: "http://i.imgur.com/VDRs9eY.png",
spriteLen : 16,
angleStep : 22.5,
size : 64,
track: new QuadraticCurve(WIDTH / 4, 100, 128)
});
frame.start();
frame.step = function (f) {
if (needsUpdate) {
ctx.fillRect(0, 0, WIDTH, HEIGHT);
car.update(f);
car.render(f);
needsUpdate = false;
}
};
* {
margin: 0;
padding: 0;
height: 100%;
width: 100%;
}
body {
font-family: monospace;
font-size: 10px;
}
#canvas {
width: 100%;
height: 100%;
}
#info {
position: absolute;
top: 0;
left: 0;
padding: 4px;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment