3D CSS Tutorial

3D Css transformations to make a lightning -fast ipad game with creative Javascript

It's possible to create even smoother animated graphics with CSS manipulated in Javascript,

Using transformations, move HTML elements in 3D space caniuse.com

automatically rendered by the GPU,which massively improves performance.

Our game has three main visual components:

the puffer fish , the background layers, and the particles that occur when the fish explode

Every graphical object is a DOM element-in fact, they're all just divs with image backgrounds and i'm animating them by adjusting their CSS properties with Javascript.

Game variables

We need to know half the width and height for working out the centerof the screen

Fish objects are stored in the fishes array and spareFishes is used to store the fishes we are not currently using

The container's 3D properties

container.style.webkitPerspective which specifies how extreme the 3D perspective is

The webkitPerspectiveOrigin should be the middle of your game screen,otherwise things will disappear into the top left as they move into the distance

Events and game loop timer

function init() {

  initMouseListeners();

  setInterval(gameLoop,1000/60);

}

We use setInterval to call gameLoop 60 times a second. Because setInterval requires time in milliseconds, we want to know the number of mils there are per frame.

convert fps into mils per frame ,simply divide 1000 by the frame rate.

requestAnimationFrame

fires on a browser screen redraw.

this has the benefit of syncing smoothly with the refresh cycle on your graphics card,

which avoids screen tearing.

But beause you never know how frequently requestAnimationFrame will fire,ensuring that your game runs at the same speed across differnet computers and browsers is complicated.

The other benefit to requestAnimationFrame is that it stops firing when your browser tab is hidden,saving CPU and batttery life Chrome has implemented a throttle on setInterval so that it only fires once per second if the page isn't visible .

Game loop overview

adding more fish , updating the parallax layers iteraing through all the fish , and updating them all. then finally calling emitter.update.

Making new fish

Fish object handles the postion update, and appearance of our fish. The constructor

parameters specify its 3D position , the image URL, the image size.create an HTML div elment and setting its css properties so it has a fixed size, absolute position ,and a background image.

div or img?

It'd be easier with divs. adjusting the div's background offset

this.update = function() {

  this.velY = this.gravity;

  this.posX += this.velX;

  this.posY += this.velY;

  this.posZ += this.velZ;

  counter ++;

  this.rotate(2);

}

velocity is how much it moves in each direction evry frame.

Fish render

This is a pretty scary-looking function. to move, scale and rotate the fish

this.render = function() {

  var dom = this.domElemnt,

  styleStr,

  sx = Math.sin(counter*0.4)*0.04 + this.size,

  xy = Math.sin(Math.PI + counter* 0.4) * 0.04 + this.size;

  dom.style.webkitTransform ="translate3d(" + this.posX+"px, " + this.posY +

"px," + this.posZ + "px) scale(" + sx+"+sy+") rotate(" + Math.sin(counter* 0.05)*20 + "deg)";

}

adjusting translate3d,which is the 3D transformation.

scalled in both x and y axis rotate in 2d using antoer sine value that causes the fish's left and right oscillating rotation

Setting the fish properties

plus a random x and z offset between -250 and 250

a slightly random velocity and give it a gravity of -0.05 which is the negative

fish.posX = HALF_WIDTH + randomRange(-250,250);

fish.posY = SCREEN_HEIGHT + 100;

fish.posZ = randomRange(-250,250);

fish.velX = randomRange(-1,1);

fish.velY = randomRange(-1,-2);

fish.velZ = randomRange(-1,1);

fish.size = 1;

fish.gravity = -0.05;

Recycling the fish

take it out of the arry and forget about it ,but this is bad for memory management.

even a fish is cleared out of memory with the gabage collector, it still takes CPU to constantly create new DOM elements and Javascript objects

function removeFish(fish) {

  fish.enabled = false;

  fish.domElment.style.visibility = "hidden";

  spareFishes.push(fish);

}

a simple pooling system,

Exploding the fish

touchstart event has an array of touch objects; it may well be that you touched down with multiple fingers at once