So far what we have is not exactly exciting. It is just a blank canvas.
Lets do something about that.

There are plenty of tutorials about how to draw shapes and graphics onto a canvas. For what we want to achieve we are going to have to go to a lower level and control the canvas directly.

So first off lets write some throwaway code to see how to do just that.

Our current code has a global variable which is set to the context of the canvas. From the context there are methods available which we can use. So lets add some code to top of our our main function.

// Test drawing directly to the canvas
var imageData = ctx.getImageData(0,0,CANVAS_WIDTH, CANVAS_HEIGHT);
var pixel = Math.floor(Math.random()*CANVAS_WIDTH*CANVAS_HEIGHT)*4;
imageData.data[pixel] = Math.floor(Math.random()*255);
imageData.data[pixel+1] = Math.floor(Math.random()*255);
imageData.data[pixel+2] = Math.floor(Math.random()*255);
imageData.data[pixel+3] = 255;
ctx.putImageData(imageData,0,0);

So what is this code doing.

The first line calls the getImageData method on the canvas context. The parameters specify we want to get the canvas data from the top left pixel 0,0 to the bottom right and store it in imageData. What this will do is return an array of numbers. Starting from the top line from left to right and then down each pixel is stored as 4 numbers. The numbers are bytes ( values 0 – 255 ). The first number is the red value, the second green, third blue and the fourth is the opacity. The opacity allows semi transparent pixels. We wont be needing this so we will always set this to 255 to indicate solid.

The next part of the code is to pick a pixel. Thats what the second line is doing. Javascript has many inbuilt objects and the Math object is one we will be using a lot. Math.floor will take a number and round it down to an integer. Math.random will generate a random fraction from 0-1. So the pixel variable will pick a random pixel on the canvas ( CANVAS_WIDTH*CANVAS_HEIGHT). We multiply be four because each pixel is made up of four numbers.

The next lines will put a random number between 0-255 for each element of the pixel ( red, green,blue,opacity).

Finally the last line calls putImageData will take our array of pixel values and apply them onto the canvas. The 0,0 says where on the canvas we want to start from.

Run this and you will see multi coloured pixels appearing on the canvas. If you go back to the global variables and set the refreshRate to some big number for example 250 and run it again you will see ( unless you have a very powerful machine ) that the actual FPS is quite low. On my laptop it is less around 54FPS. This is not very good but if we think a bit we can make a quick improvement fairly easily.

The top of the main function calls GetImageData. We will be taking full control of what is on the canvas so we dont have to do this every time. We can just do this once in the init function. So make the following change. Add the imageData variable declaration in the global variables section.

var imageData;

Now add the line that sets the imageData into the init function just before we setInterval.

imageData = ctx.getImageData(0,0,CANVAS_WIDTH, CANVAS_HEIGHT);

And remove the line that sets the imageData variable in the main function.

Now when you run the code you should find that the refresh rate is significantly faster. On my machine it has gone up to around 135. Yeah… much better.

One final test. Lets see how fast we can write to ALL the pixels on the canvas per frame. Replace the test drawing code with the following

// Test drawing directly to the canvas
 for (var pixel = 0; pixel <= CANVAS_WIDTH*CANVAS_HEIGHT*4; pixel+= 4)
 {
 imageData.data[pixel] = Math.floor(Math.random()*255);
 imageData.data[pixel+1] = Math.floor(Math.random()*255);
 imageData.data[pixel+2] = Math.floor(Math.random()*255);
 imageData.data[pixel+3] = 255;
 }
 ctx.putImageData(imageData,0,0);

This will loop through every single pixel in the canvas and give it a random colour. Run this and we see something not unlike static on a tv display ( this is pre digital ). As you can see the speed has dropped a fair bit, for me the FPS dropped to 72, but this is worst case scenario where every single pixel has changed. We need to bear this in mind later on to try and optimise this.

So there we are. We have a way to be in total control of the canvas. In the next part we will create a DisplayEngine object which will handle the drawing to the canvas.

Below is a link to the final code

8BitGameTutorial2

Leave a reply

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong> 

required