Sampled by © JavaScriptBank.com
Play in new window
By way of brain dump, and so that I've got a record of the stuff I need to remember somewhere ,
here's just list of bits that I picked up throughout the day. Obviously
there was tons more, but when you're coding, listening, learning and
wrapping your head around trig (something that I'm quite useless at) -
less notes are taken
Canvas
When using colours: HSL's where it's at! Here's some help: http://mothereffinghsl.com
Remember subpixels drawing, by default you draw between pixels, Mark
Pilgrim explains: http://diveintohtml5.org/canvas.html#pixel-madness
When using beginPath
, unless you do moveTo
the first use of lineTo
will actually move, and not draw a line, i.e. if you do a lineTo without a start, it only moves (in fact because there's no starting point).
Rotating a canvas rotates around the origin, which by default is top, left. To move the origin of the canvas, use translate
.
save
/restore
state the drawing style and affects coordinate system - this useful for rotating the canvas drawing, and then resetting the rotation.
For an animation the (pseudo) code looks like this:
var mouseX = 0 , mouseY = 0 , mouseDown = false , keys = {}; setup(); // initalisation setInterval( loop , 1000 / 60 ); // 60 fps function loop () { // 1. handle key or mouse states // 2. update position of animated objects: particles, etc object . update (); // 3. draw each object object . draw (); } // capture events, but don't do anything with them document. addEventListener ( 'mousemove' , function ( e ) { mouseX = e . pageX ; mouseY = e . pageY ; }, false );
Vectors
Pythagoras can be used to determine whether a point (like a click) is inside an circle drawn on a canvas. However, it requires Math . sqrt
which is costly, so instead of using Pythagoras to workout hit testing (for length of vector) - compare the distanced squared:
Instead of:
var distance = Math . sqrt (( this . diff . x * this . diff . x ) + ( this . diff . y * this . diff . y )); return ( distance < this . radius );
Use:
var distanceSq = ( this . diff . x * this . diff . x ) + ( this . diff . y * this . diff . y ); return ( distanceSq < this . radius * this . radius )
3D
Collision detection in 3D:
var distanceSq3D = ( this . diff . x * this . diff . x ) + ( this . diff . y * this . diff . y ) + ( this . diff . z * this . diff . z ) return ( distanceSq3D < this . radius * this . radius )
To calculate the new x and y in a 3D space, you need to multiply
them by a scale which is worked out from: f/(f+z) = newscale (note that f
the field of view - like the zoom on a camera)
To scale the 3D system properly, the origin must be in the centre of
the canvas, this is key to getting the perspective correct: ctx . translate ( ctx . canvas . width / 2 , ctx . canvas . height / 2 )
To rotate the y (the yaw ), you rotate the y and z axis,
which is exactly the same as the distribution code (below in the
optimisation tricks), using sin and cos
To get the z-order correct (painters algorithm), you need to sort by the z axis, where points is an array of objects with xyz:
points = points . sort ( function ( a , b ) { return a . z >= b . z ? - 1 : 1 ; });
If the z is less than -fov (f, i.e. if f=250, and z=-250) it means the z position is behind you - so it should be removed
Optimisation tricks
When removing an item (or deleted) - like bullets or asteroids,
recycle the item: disable it when it's finished with, and add it to an
array. Then when you want a new object, try to get it from the pool of
spares first, otherwise create a new item.
Instead of having the keyboard interactivity interrupt the code and
update values, track the key presses and check these in the render cycle
process.
( Math . random () * 0xff ) << 16
generates a random blue colour (0xff
== 0x0000ff
== blue), then shift 16 bits and we've now got a random red colour. We could equally get a random green using << 8
.
When placing objects at a random position, if you use x = Math . random () * width
(and similarly with y axis) the distribution creates a square shape, which looks odd. This is easy to fix, you create a circular distribution.
To get a circular distribution, rotate around a circle using:
x = Math . sin ( angle ) * speed ; // sin for X y = Math . cos ( angle ) * speed ; // cos for Y