If you are attempting to write any type of game it is more than likely that you will want to show some images/sprites/animation. I've previously posted about "sprite sheets", but it is worth getting to grip with loading the necessary images in the first place.
What can possibly go wrong?
At first glance loading an image is easy; for example:
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<h1>testing ...</h1>
<div id="demo_div">
</div>
<script type="text/javascript">
var my_image;
my_image=new Image();
my_image.src='bigcup.jpg';
var ele = document.getElementById('demo_div');
ele.appendChild(my_image);
</script>
</body></html>
The above will appear to work, but most likely the javascript has completed before the image is loaded, and although the image does appear to load - you are sure when it is ready.
Check it out:
http://www.advantsys.co.uk/demos/demos2
Obviously for a game this really isn't good; you can't start the game knowing half the graphics might not be loaded!
Using the "onload" callback
Fortunately there is a solution, but firstly you must understand the concept of asynchronous code execution and callbacks. For example say we want to make the image smaller once it has loaded, then you might attempt:
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<h1>testing ...</h1>
<div id="demo_div">
</div>
<script type="text/javascript">
var my_image;
my_image=new Image();
my_image.src='bigcup.jpg';
var ele = document.getElementById('demo_div');
ele.appendChild(my_image);
my_image.height=200;
my_image.width=200;
</script>
</body></html>
If you clear the browser cache (to ensure the image is reloaded), then try using the following link:
http://www.advantsys.co.uk/demos/demos3/
You should see the shrunken image is being loaded, rather than the large image loading and then shrinking! This is because certain features in JavaScript are asynchronous, in this instance:
my_image.src='bigcup.jpg';
This simply sets the name of the image and continues the script. Separately the browser will start loading the image, but the code continues to execute. Fortunately JavaScript can be made to indicate when the image has been loaded using the "onload" callback facility. For example:
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<h1>testing ...</h1>
<div id="demo_div">
</div>
<script type="text/javascript">
var my_image;
my_image=new Image();
my_image.onload=function() { my_image.height=200; my_image.width=200; };
my_image.src='bigcup.jpg';
var ele = document.getElementById('demo_div');
ele.appendChild(my_image);
</script>
</body></html>
Clear your browser cache and try the following link:
http://www.advantsys.co.uk/demos/demos4/
Now the image should load at the original size and only once loaded will it shrink to the smaller size. This happens because once the image has loaded JavaScript will see the property "onload" is set, and execute that code.
Part 2 will describe how to use the "onload" property of images to load all images for the game being developed and only continue once all images are loaded.
Showing posts with label HTML5. Show all posts
Showing posts with label HTML5. Show all posts
Saturday, March 10, 2012
Wednesday, March 7, 2012
HTML 5 Canvas Sprite Sheets 101
What the heck is a sprite sheet?
Probably obvious to lots of people but to me (who last wrote a computer game 20+ years ago) unfortunately not. I'll keep this short and to the point.
Sprite sheets are used for animation of an object - and can be used easily by the HTML 5 Canvas element.
Consider the following four frames of animation for my Pacman-style game:
Now you might simply load these 4 png images as separate files - indeed there is no harm in doing so. However it is more efficient instead to create a Sprite-sheet - joining all the files together:
Now we only need to load one image not four - that is all a sprite-sheet is - a collection of images joined together at known offsets to allow easy extraction of each sub-image.
How to create a sprite sheet?
Since I use Linux for my desk top this was easy; I created the 4 individual images shown above and called them:
pac_right1.png
pac_right2.png
pac_right3.png
pac_right4.png
Then the "montage" command from the "ImageMagick" collection of programs was used to join them together:
montage -background "transparent" -geometry 24x24 -tile 4x1 \
pac_right[1234].png pac_right.png
The result was a file called "pac_right.png" which contained all 4 images at the original resolution of 24x24 as shown in the second example.
How to use a sprite sheet on a Canvas?
This is a matter of loading an image initially, for example (overly simplistic):
var im=new Image();
im.src='images/pac_right.png';
This is overly simplistic because it does not take into account that images are loaded asynchronously - the image might not be available for a short while above the above code has been run - more on that next time!
Once the image is available it is a matter of using the "drawImage" method made available by the canvas element. This takes the following arguments:
canvas.drawImage(
image, // The image to draw (our sprite sheet)
x_offset, // The X offset in image of partial image to draw
y_offset, // The Y offset in image of partial image to draw
width, // Width in pixels of part of image to draw
height, // Height in pixels of part of image to draw
canvas_x_offset, // Offset in pixels from left of canvas
canvas_y_offset, // Offset in pixels from top of canvas
target_width, // Width of image to draw on canvas
target_height // Height of image to draw on canvas
);
Given that the sprite sheet in the example of a tile of 4 images across then the "y_offset" I will use will always be 0. The "x_offset values will be 0,24,48,72 for the for partial images.
So the first five parameters determine the image and the portion of it you wish to display on the canvas. The next two - canvas_x_offset and canvas_y_offset determine where on the canvas to put the image. The final two indicate the size of the image to display. Some points of interest:
The following takes the concepts above and creates a canvas, loads a sprite sheet and displays the 4 sub-images on the canvas with scaling:
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript">
var pac_left;
pac_left=new Image();
pac_left.onload=function() { draw_it(); };
pac_left.src='pac_left.png';
function draw_it() {
var canvas = document.getElementById('sprites');
console.log("canvas=",canvas);
var ctx=canvas.getContext('2d');
ctx.drawImage(pac_left,0,0,24,24,0,0,24,24);
ctx.drawImage(pac_left,24,0,24,24,50,0,32,32);
ctx.drawImage(pac_left,48,0,24,24,100,0,40,40);
ctx.drawImage(pac_left,72,0,24,24,200,0,48,48);
}
</script>
</head>
<body>
<h1>testing ...</h1>
<div id="maze" style="position:relative; width:720; height:480">
<canvas id="sprites" style="z-index: 1; position:absolute; left:0px; top:0px" width="720" height="480"></canvas>
</div>
</body></html>
HTML Canvas Demo 1
Probably obvious to lots of people but to me (who last wrote a computer game 20+ years ago) unfortunately not. I'll keep this short and to the point.
Sprite sheets are used for animation of an object - and can be used easily by the HTML 5 Canvas element.
Consider the following four frames of animation for my Pacman-style game:
Now you might simply load these 4 png images as separate files - indeed there is no harm in doing so. However it is more efficient instead to create a Sprite-sheet - joining all the files together:
Now we only need to load one image not four - that is all a sprite-sheet is - a collection of images joined together at known offsets to allow easy extraction of each sub-image.
How to create a sprite sheet?
Since I use Linux for my desk top this was easy; I created the 4 individual images shown above and called them:
pac_right1.png
pac_right2.png
pac_right3.png
pac_right4.png
Then the "montage" command from the "ImageMagick" collection of programs was used to join them together:
montage -background "transparent" -geometry 24x24 -tile 4x1 \
pac_right[1234].png pac_right.png
The result was a file called "pac_right.png" which contained all 4 images at the original resolution of 24x24 as shown in the second example.
How to use a sprite sheet on a Canvas?
This is a matter of loading an image initially, for example (overly simplistic):
var im=new Image();
im.src='images/pac_right.png';
This is overly simplistic because it does not take into account that images are loaded asynchronously - the image might not be available for a short while above the above code has been run - more on that next time!
Once the image is available it is a matter of using the "drawImage" method made available by the canvas element. This takes the following arguments:
canvas.drawImage(
image, // The image to draw (our sprite sheet)
x_offset, // The X offset in image of partial image to draw
y_offset, // The Y offset in image of partial image to draw
width, // Width in pixels of part of image to draw
height, // Height in pixels of part of image to draw
canvas_x_offset, // Offset in pixels from left of canvas
canvas_y_offset, // Offset in pixels from top of canvas
target_width, // Width of image to draw on canvas
target_height // Height of image to draw on canvas
);
Given that the sprite sheet in the example of a tile of 4 images across then the "y_offset" I will use will always be 0. The "x_offset values will be 0,24,48,72 for the for partial images.
So the first five parameters determine the image and the portion of it you wish to display on the canvas. The next two - canvas_x_offset and canvas_y_offset determine where on the canvas to put the image. The final two indicate the size of the image to display. Some points of interest:
- The offset values on the canvas are typically real numbers, but including fractions may slow down rendering the image size the canvas implementation might attempt to dither the image in an attempt to mimic the fractional positioning - so typically make sure whole values are passed.
- If the target_width and target_height parameters are different than the width and height parameters then the image will be scaled to this new size.
The following takes the concepts above and creates a canvas, loads a sprite sheet and displays the 4 sub-images on the canvas with scaling:
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript">
var pac_left;
pac_left=new Image();
pac_left.onload=function() { draw_it(); };
pac_left.src='pac_left.png';
function draw_it() {
var canvas = document.getElementById('sprites');
console.log("canvas=",canvas);
var ctx=canvas.getContext('2d');
ctx.drawImage(pac_left,0,0,24,24,0,0,24,24);
ctx.drawImage(pac_left,24,0,24,24,50,0,32,32);
ctx.drawImage(pac_left,48,0,24,24,100,0,40,40);
ctx.drawImage(pac_left,72,0,24,24,200,0,48,48);
}
</script>
</head>
<body>
<h1>testing ...</h1>
<div id="maze" style="position:relative; width:720; height:480">
<canvas id="sprites" style="z-index: 1; position:absolute; left:0px; top:0px" width="720" height="480"></canvas>
</div>
</body></html>
HTML Canvas Demo 1
Tuesday, March 6, 2012
Games programming - choosing a first language
Introduction
Recently my son has taken an interest in programming (well a bit...) and I thought that was a good excuse for a diverting my attention occasionally and helping him learn in an entertaining manner.
The first hurdle was choosing a language. We originally had a bit of fun with "scratch" and although it helped with the basics doing anything of note quickly became rather painful. However with the concept of logic and variables understood it was a useful exercise.
Next I tried to encourage him with Python; I often use this at work; and thought it clear and precise with a large platform base and mature libraries. No luck however - he simply didn't get interested.
I could go on and laugh at showing him the perversities of Perl (love it) and the obtuse nature of Basic variants. Suffice to say nothing really gelled.
Of course the flash of Flash was a strong contender in his eyes; but the closed-source nature and the limited number of supported platforms put me off.
So in the end the obvious choice was JavaScript.
Why JavaScript?
Personally I was dragged screaming and kicking to JavaScript. This was not out of any kind of stubbornness and an unwillingness to learn something new; it was just that I couldn't see the point. I knew Perl, Python, PHP, C, Tcl and so on - so what did Javascript offer me - or my son?
However the answer is of course obvious; it is pervasive across browsers and available across different operating systems. More recently with HTML 5 features - particularly the canvas - dynamic graphics are relatively easy.
Performance was always an issue but newer browsers and platforms offer more than enough processing power to pull off most things a 10 year old might want to program.
So JavaScript it is!
Recently my son has taken an interest in programming (well a bit...) and I thought that was a good excuse for a diverting my attention occasionally and helping him learn in an entertaining manner.
The first hurdle was choosing a language. We originally had a bit of fun with "scratch" and although it helped with the basics doing anything of note quickly became rather painful. However with the concept of logic and variables understood it was a useful exercise.
Next I tried to encourage him with Python; I often use this at work; and thought it clear and precise with a large platform base and mature libraries. No luck however - he simply didn't get interested.
I could go on and laugh at showing him the perversities of Perl (love it) and the obtuse nature of Basic variants. Suffice to say nothing really gelled.
Of course the flash of Flash was a strong contender in his eyes; but the closed-source nature and the limited number of supported platforms put me off.
So in the end the obvious choice was JavaScript.
Why JavaScript?
Personally I was dragged screaming and kicking to JavaScript. This was not out of any kind of stubbornness and an unwillingness to learn something new; it was just that I couldn't see the point. I knew Perl, Python, PHP, C, Tcl and so on - so what did Javascript offer me - or my son?
However the answer is of course obvious; it is pervasive across browsers and available across different operating systems. More recently with HTML 5 features - particularly the canvas - dynamic graphics are relatively easy.
Performance was always an issue but newer browsers and platforms offer more than enough processing power to pull off most things a 10 year old might want to program.
So JavaScript it is!
Subscribe to:
Posts (Atom)