2
\$\begingroup\$

This is just a simple script for testing sprite sheet animations. I'm trying to improve my code style, so I'm curious about suggestions anyone might have about best practices or readability.

<html> <head> <script> //just a shim to provide requestAnimationFrame support in different browsers if (!window.requestAnimationFrame) { window.requestAnimationFrame = (window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.msRequestAnimationFrame || window.oRequestAnimationFrame || function (callback) { return window.setTimeout(callback, 17 /*~ 1000/60*/); }); } if (!window.cancelAnimationFrame) { window.cancelAnimationFrame = (window.cancelRequestAnimationFrame || window.webkitCancelAnimationFrame || window.webkitCancelRequestAnimationFrame || window.mozCancelAnimationFrame || window.mozCancelRequestAnimationFrame || window.msCancelAnimationFrame || window.msCancelRequestAnimationFrame || window.oCancelAnimationFrame || window.oCancelRequestAnimationFrame || window.clearTimeout); } //loads when the body element has loaded. var init = function() { //the actual event loop. Runs inside of the init() closure. var animate = function() { (function animloop(){ //clear the canvas canvas.width = canvas.width; //increment the tick variable. tick++; //if it's greater than five, reset to zero and go to the next tile if (tick > 5) { tick = 0; //check to see if currently viewing the last tile in the sequence. If so, reset to the first, otherwise go the the net one. if (currentTile > tiles - 2) { currentTile = 0; } else { currentTile++ } } //pull the current tile out of the sprite sheet and draw it to the canvas. ctx.drawImage(img, currentTile * tileWidth, 0, tileWidth, tileHeight, 0, 0, tileWidth, tileHeight); //let the browser decide when to call the event loop again window.requestAnimationFrame(animloop); })(); }; //get a reference to the canvas element var canvas = document.getElementById('canvas'); //same for the canvas context var ctx = canvas.getContext('2d'); //and index that refers to the tile currently selected var currentTile = 0; //used in the event loop to slow down the animation var tick = 0; //************************************* //change this next value depending on the number of tiles in the animation var tiles = 5; //used to select the tile currently being drawn from sprite sheet var tileWidth = null; //same var tileHeight = null; //new image object img = new Image(); //called when the image loads img.onload = function() { //the sprite sheet should be composed of tiles of equal length and the animation should be centered on each tile. tileWidth = img.width / tiles; //the script only handles sprite sheets that are one dimensional. //ie, the animation should only run along the x axis, so the animation will always be the same height as the image itself. tileHeight = img.height; //call the event loop animate(); }; //********************************* //this is the name of the file you want to test. Make sure it's in the //the same directory as the script //load the specified sprite sheet img.src = 'zombieChase3.png'; }; </script> </head> //run init when body is loaded <body onload="init()"> //just a canvas element <canvas id="canvas" width="500" height="500"> You need a browser that supports the canvas element. </canvas> </body> </html> 

Thanks guys!

\$\endgroup\$

1 Answer 1

1
\$\begingroup\$
//I suggest you use this polyfill for the rAF and cAF //https://gist.github.com/paulirish/1579671 //Enclosing the module in a closure to avoid pollution of the global scope (function (exports) { //Let's make each sprite an object, so that we have a reusable constructor function Sprite(config) { //A typical convention to not lose the context is to store it in another variable var self = this; //Setting a few configs for this object this.canvas = document.getElementById(config.canvas); this.context = this.canvas.getContext('2d'); this.path = config.path; this.tiles = config.tiles; //We can add properties to the Sprite instance, like states and counters this.paused = false; this.tick = 0; //Let's load up the image when creating an instance var image = this.image = new Image(); image.onload = function () { //When loaded, get the info self.width = image.width; self.height = image.height; //Start the animation via the instance's start method self.animate(); } image.src = this.path; } //Let's extend the constructor to have methods //Unpauses the instance and runs animate Sprite.prototype.play = function () { this.paused = false; this.animate(); } //Our animation loop function Sprite.prototype.animate = function () { //If say the state is paused, don't request the next frame //Otherwise, schedule the next frame if(this.paused) return; requestAnimationFrame(animate); //clear and draw this.canvas.width = this.canvas.width; this.context.drawImage(this.image, this.tick * this.width, 0, this.width, this.height, 0, 0, this.width, this.height); //reset it tiles reached if(++this.tick > this.tiles) this.tiles = 0; } //This one stops the animation Sprite.prototype.stop() { this.paused = true; } exports.load = function (config) { return new Sprite(config) } }(this.Sprite = this.Sprite || {})); //Extensibility. Don't limit yourself to a fixed set of configurations. //Make your code reusable. var sprite = Sprite.load({ canvasId: 'canvas', path: 'zombieChase3.png', tiles: '5' }); //you can control the sprite sprite.play(); sprite.stop(); //Additionally, you can add something like play, pause, unload etc. which I just did //Also, sprite sheets are usually big sheets containing more than one sequence per image //you should consider that. If you Google "sprite sheets", you'll see. 
\$\endgroup\$
1
  • \$\begingroup\$ +1 but only because the review is in the comments. I would be an even better post if you elaborated a little bit in plain text. \$\endgroup\$ Commented Nov 21, 2013 at 3:10

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.