Showing posts with label Example. Show all posts
Showing posts with label Example. Show all posts

Saturday, 1 December 2012

HTML5 Game Development Tutorial

If you want to make a HTML5 game and just want a nice reference page you can go back to, or if you are a complete beginner and need to learn as much as possible step-by-step, then you're at the right place.
I also have a guide split into multiple pages here, if you prefer that: HTML5 Game Development Guide.
There's also a video tutorial for the basics of HTML5 game development: Video Intro to HTML5 Game Dev

If you don't know much about JavaScript, then have a look at the Introduction to JavaScript.

If you want to know how to make money from your games, have a look at this article:
How to Make Money From Your Games


If I post any little snippets here, feel free to use them in any way.
Although if you use a lot of it, it would be appreciated if you place something like this in your JavaScript:
/* Some code taken from www.slashgame.net */

Contents

What is the HTML5 Canvas?
How to Draw an Image to the Canvas
How to Draw Text to the Canvas
Set up a Game Loop
Keyboard Input
Mouse Input
Add Simple Game Physics
How to Rotate an Image on Canvas
Use HTML5 Audio
Conclusion of Tutorial



What is the HTML5 Canvas? (back to top)

The <canvas> HTML element, which came to us in HTML5 was the first step towards HTML5 games becoming big.

The canvas allows so many things that you wouldn't have been able to do otherwise, and does it rather efficiently.

Canvas renders 2D graphics onto a given area in the browser window. It does this dynamically via scripting (i.e. JavaScript). The shapes and images which are rendered on the canvas can be manipulated in several ways. The most obvious and useful ways are scaling and rotating the image; which you would not have been able to do without the canvas, unless you did some rather inefficient and complicated php scripting to alter an image at the pixel-level to make it appear to do a similar thing.

JavaScript has a 2D graphics API which accesses the HTML5 canvas drawing area, which is how games can be written. But just because it only has a 2D API, don't let that make you think 3D isn't possible.

For a start, you could simply write your own JavaScript 3D engine, which uses normal 2D functions to generate a 3D object and render the 2D projection on the canvas. Doing so just requires a bit of mathematics. But making it a huge and playable game is where it gets difficult.

You could create a whole 3D engine if you wanted, but there is a 3D graphics API available. It's called WebGL, and it does what I just described, but it simplifies it by allowing you to just call the functions, rather than having to think up all that complicated stuff yourself. It also means that the 3D engine already has optimized code, meaning it will run faster.



How to Draw an Image to the Canvas (back to top)

This is just about the simplest example of the use of HTML5 canvas you can get. This is just to show how to set up a canvas and draw in it.

Firstly, you would have something like this in the HTML of the page:
<canvas height="400" id="canvas" width="400">
Browser not compatible with HTML5 canvas
</canvas>

The id of the canvas element can be anything, but here it has been set to "canvas". This is used so the JavaScript can identify the correct canvas element to manipulate.

I've set the width and height of the canvas to 400px. It normally wouldn't be a perfect square for a game, but this is just an example.

And if an incompatible browser is used, it will display the text "Browser not compatible with HTML5 canvas".


The JavaScript goes in the section of the page.
You could have all the code in script tags (<script>CODE HERE</script>) or have it in a seperate .js file and call it from src attribute of script tags (<script src"javascriptfile.js"></script>).

Here is an example of the kind of JavaScript you could use to draw an image:
var canvas = document.getElementById('canvas');
var context2D = canvas.getContext('2d');

var img = new Image();
img.src = "http://www.blogger.com/img/logo40.png";
context2D.drawImage(img, 100, 50);

So first it gets the canvas element by using the id we gave it. It then creates the 2D context with that canvas element.

It then loads a new Image object and then tells it to use the image from the location we give it by assigning it to the src variable of the Image object.

Then it uses the 2D graphics API by calling the drawImg() function.

The first parameter of the function is looking for an image object to draw, the second is the x-position and the third is the y-position. The positions are always relative to the top left corner by default.



How to Draw Text to the Canvas (back to top)

context2D.fillStyle = "white";
context2D.font = 'bold 30px sans-serif';
context2D.fillText("POINTS: "+numOfPoints, canvas.width-200, 30);

That right there is an example of drawing text to the canvas. It writes it on the top right of the canvas. That particular example is what would serve as part of the HUD in a game.
Here is a little function that draws text to the canvas with a specified position, color and font. This also shows you the different things you can do with text.
However, you may want to use this function just as a means to being able to not worry about remembering the different parts to it.
function drawCanvasText(txt, pX, pY, clr, fnt) {
 context2D.fillStyle = clr; // color
 context2D.font = fnt; // font
 context2D.fillText(txt, pX, pY); // text at position X, Y
}
Example Usage:
drawCanvasText("drawing text yas", 50, 50, "black", "bold 30px sans-serif");


Set up a Game Loop (back to top)

A game loop is the normal structure a game would be build in. This is something you would find in any kind of game, not just HTML5 games.
First it would initiate the loop (what I tend to do is trigger the initiation function when the window is loaded), then the loop would involve checking for user input, then doing what needs to be done to all the objects, then rendering/drawing the scene, and start again from checking user input.
This is an example of doing this in javascript:
const FPS = 30;

var playerPosX = 0;
var playerPosY = 0;

var playerImg = new Image();
playerImg.src = "http://filevaults.com/media/Slash/553481-smiley.png";

var canvas = null;
var context2D = null;
var keys = new Array();

window.onload = init;

window.addEventListener('keydown',keyDown,true);
window.addEventListener('keyup',keyUp,true);
function keyDown(evt){
 keys[evt.keyCode] = true;
}
function keyUp(evt){
 keys[evt.keyCode] = false;
}

function init()
{
 canvas = document.getElementById('canvas');
 context2D = canvas.getContext('2d');
 setInterval(draw, 1000 / FPS);
}

function draw()
{
 if ((37 in keys &amp;&amp; keys[37]) || (65 in keys &amp;&amp; keys[65])){ //left
  playerPosX -= 2;
 }
 if ((39 in keys &amp;&amp; keys[39]) || (68 in keys &amp;&amp; keys[68])){ //right
  playerPosX += 2;
 }
 
 context2D.clearRect(0, 0, canvas.width, canvas.height);
 context2D.drawImage(playerImg, playerPosX, playerPosY);
}

The code initiates the loop in the init() function, which is called as soon as the window is loaded up. This function uses the setInterval() function to call the draw() function 30 times per second (it uses the FPS variable to determine that frame rate).

It then adds an "event listener" for key being pressed, and for key being released. This means that when a key is pressed, it calls the function which adds the key's code to an array. When the key is released, another function is called which sets the value of that array element to false. This means that every time the loop comes to the point where it checks for user input, all it has to do is look in the array and see if it's there and that it is set to true.

Once it knows if the key is pressed, it then decides what to do with the playerPos variables. This is the stage where it changes the "virtual world".

Then the last stage of the loop is rendering/drawing the scene based on the "virtual world's" variables.
To do so, it clears the canvas fully then draws the image in the correct spot.

Here's the result of the example I just gave (use arrow keys or A and D to move left and right): http://slashgame.net/html5gamedevexample2.php


From the knowledge you have learned so far, you can make a simple game, if you have the ability to figure things out. However, I will continue and explain things in further detail and bring up new points of interest.



Keyboard Input (back to top)

As explained in the Game Loop section of this post (just above this section); it goes through the loop, and each time, it checks if the key is pressed by checking an array to see if it is set to true or false.
An event listener calls a function when a key is pressed down, and sets the array element of the ASCII code of the key, and sets it to true. And another event listener checks for keys being released, and sets the element value to false.

Looking up ASCII values all the time can sometimes be a pain in the ass, so what I've done is made a little snippet of code you can paste into your code which allows you to simply call the function with the key you want to check as a parameter. This is simple enough to use.

Examples of use:
If you wanted to check if the A key is pressed down:
if (isKeyPressed('a')==true) { /* do whatever */ }
If you wanted to check for the left arrow key being pressed:
isKeyPressed('left')
For escape key:
isKeyPressed('esc')


The Code:
window.addEventListener('keydown',keyPressDown,true);
window.addEventListener('keyup',keyPressUp,true);

function keyPressDown(evt){
 keys[evt.keyCode] = true;
}
function keyPressUp(evt){
 keys[evt.keyCode] = false;
}


function isKeyPressed(checkKey) {
 
 // alphabet
 if ((checkKey == 'a' || checkKey == 'A') &amp;&amp; (65 in keys &amp;&amp; keys[65])){
  return true;
 }
 else if ((checkKey == 'b' || checkKey == 'B') &amp;&amp; (66 in keys &amp;&amp; keys[66])){
  return true;
 }
 else if ((checkKey == 'c' || checkKey == 'C') &amp;&amp; (67 in keys &amp;&amp; keys[67])){
  return true;
 }
 else if ((checkKey == 'd' || checkKey == 'D') &amp;&amp; (68 in keys &amp;&amp; keys[68])){
  return true;
 }
 else if ((checkKey == 'e' || checkKey == 'E') &amp;&amp; (69 in keys &amp;&amp; keys[69])){
  return true;
 }
 else if ((checkKey == 'f' || checkKey == 'F') &amp;&amp; (70 in keys &amp;&amp; keys[70])){
  return true;
 }
 else if ((checkKey == 'g' || checkKey == 'G') &amp;&amp; (71 in keys &amp;&amp; keys[71])){
  return true;
 }
 else if ((checkKey == 'h' || checkKey == 'H') &amp;&amp; (72 in keys &amp;&amp; keys[72])){
  return true;
 }
 else if ((checkKey == 'i' || checkKey == 'I') &amp;&amp; (73 in keys &amp;&amp; keys[73])){
  return true;
 }
 else if ((checkKey == 'j' || checkKey == 'J') &amp;&amp; (74 in keys &amp;&amp; keys[74])){
  return true;
 }
 else if ((checkKey == 'k' || checkKey == 'K') &amp;&amp; (75 in keys &amp;&amp; keys[75])){
  return true;
 }
 else if ((checkKey == 'l' || checkKey == 'L') &amp;&amp; (76 in keys &amp;&amp; keys[76])){
  return true;
 }
 else if ((checkKey == 'm' || checkKey == 'M') &amp;&amp; (77 in keys &amp;&amp; keys[77])){
  return true;
 }
 else if ((checkKey == 'n' || checkKey == 'N') &amp;&amp; (78 in keys &amp;&amp; keys[78])){
  return true;
 }
 else if ((checkKey == 'o' || checkKey == 'O') &amp;&amp; (79 in keys &amp;&amp; keys[79])){
  return true;
 }
 else if ((checkKey == 'p' || checkKey == 'P') &amp;&amp; (80 in keys &amp;&amp; keys[80])){
  return true;
 }
 else if ((checkKey == 'q' || checkKey == 'Q') &amp;&amp; (81 in keys &amp;&amp; keys[81])){
  return true;
 }
 else if ((checkKey == 'r' || checkKey == 'R') &amp;&amp; (82 in keys &amp;&amp; keys[82])){
  return true;
 }
 else if ((checkKey == 's' || checkKey == 'S') &amp;&amp; (83 in keys &amp;&amp; keys[83])){
  return true;
 }
 else if ((checkKey == 't' || checkKey == 'T') &amp;&amp; (84 in keys &amp;&amp; keys[84])){
  return true;
 }
 else if ((checkKey == 'u' || checkKey == 'U') &amp;&amp; (85 in keys &amp;&amp; keys[85])){
  return true;
 }
 else if ((checkKey == 'v' || checkKey == 'V') &amp;&amp; (86 in keys &amp;&amp; keys[86])){
  return true;
 }
 else if ((checkKey == 'w' || checkKey == 'W') &amp;&amp; (87 in keys &amp;&amp; keys[87])){
  return true;
 }
 else if ((checkKey == 'x' || checkKey == 'X') &amp;&amp; (88 in keys &amp;&amp; keys[88])){
  return true;
 }
 else if ((checkKey == 'y' || checkKey == 'Y') &amp;&amp; (89 in keys &amp;&amp; keys[89])){
  return true;
 }
 else if ((checkKey == 'z' || checkKey == 'Z') &amp;&amp; (90 in keys &amp;&amp; keys[90])){
  return true;
 }
 
 
 //numbers
 else if ((checkKey == '0') &amp;&amp; (48 in keys &amp;&amp; keys[48])){
  return true;
 }
 else if ((checkKey == '1') &amp;&amp; (49 in keys &amp;&amp; keys[49])){
  return true;
 }
 else if ((checkKey == '2') &amp;&amp; (50 in keys &amp;&amp; keys[50])){
  return true;
 }
 else if ((checkKey == '3') &amp;&amp; (51 in keys &amp;&amp; keys[51])){
  return true;
 }
 else if ((checkKey == '4') &amp;&amp; (52 in keys &amp;&amp; keys[52])){
  return true;
 }
 else if ((checkKey == '5') &amp;&amp; (53 in keys &amp;&amp; keys[53])){
  return true;
 }
 else if ((checkKey == '6') &amp;&amp; (54 in keys &amp;&amp; keys[54])){
  return true;
 }
 else if ((checkKey == '7') &amp;&amp; (55 in keys &amp;&amp; keys[55])){
  return true;
 }
 else if ((checkKey == '8') &amp;&amp; (56 in keys &amp;&amp; keys[56])){
  return true;
 }
 else if ((checkKey == '9') &amp;&amp; (57 in keys &amp;&amp; keys[57])){
  return true;
 }
 
 
 // special keys
 else if ((checkKey == 'left' || checkKey == 'LEFT') &amp;&amp; (37 in keys &amp;&amp; keys[37])){
  return true;
 }
 else if ((checkKey == 'right' || checkKey == 'RIGHT') &amp;&amp; (39 in keys &amp;&amp; keys[39])){
  return true;
 }
 else if ((checkKey == 'up' || checkKey == 'UP') &amp;&amp; (38 in keys &amp;&amp; keys[38])){
  return true;
 }
 else if ((checkKey == 'down' || checkKey == 'DOWN') &amp;&amp; (40 in keys &amp;&amp; keys[40])){
  return true;
 }
 else if ((checkKey == 'esc' || checkKey == 'ESC' || checkKey == 'escape' || checkKey == 'ESCAPE' ) &amp;&amp; (27 in keys &amp;&amp; keys[27])){
  return true;
 }
 
}


Mouse Input (back to top)

It's fairly simple to add mouse input to your game; just use an eventListener for the event "mousemove" and use a function that takes the event as a parameter (in my example below, I used mouseMoved(e)), and use the e.pageX and e.pageY for the mouse's X and Y position.

And for mouse clicks, just use eventListener for the "click" event, and use a function that does whatever. In the example I give, it sets the position of an image to the position of the mouse at the point it is clicked. In this case, a bullethole in the position the cursor was pointing at.

Here is the code:
<html>
<head>
<script type="text/javascript">
const FPS = 60;

var canvas = null;
var context2D = null;

var cursorImg = new Image();
cursorImg.src = "images/cursorexample.png";

var bulletHoleImg = new Image();
bulletHoleImg.src = "images/bullethole.png";
var bulletHolesX = new Array();
var bulletHolesY = new Array();
for (var i=0; i<50; i++) {
 bulletHolesX[i] = -500;
 bulletHolesY[i] = -500;
}
bulletNum = 0;

window.addEventListener('mousemove', mouseMoved, true);
window.addEventListener('click', clicked, true);
var mouseX = 0;
var mouseY = 0;

window.onload = init;
function init() {
 canvas = document.getElementById('canvas1');
 context2D = canvas.getContext('2d');
 
 setInterval(draw, 1000/FPS);
}

function draw() {
 context2D.clearRect(0, 0, canvas.width, canvas.height);
 for (var i=0; i<50; i++) {
  context2D.drawImage(bulletHoleImg, bulletHolesX[i]-(bulletHoleImg.width/2), bulletHolesY[i]-(bulletHoleImg.height/2));
 }
 context2D.drawImage(cursorImg, mouseX-(cursorImg.width/2), mouseY-(cursorImg.width/2));
}

function mouseMoved(e) {
 
 mouseX = e.pageX;
 mouseY = e.pageY;
 
}

function clicked(e) {
 
 bulletHolesX[bulletNum] = mouseX;
 bulletHolesY[bulletNum] = mouseY;
 bulletNum++;
 if (bulletNum > 50) {
  bulletNum = 0;
 }
 
}
</script>
</head>
<body style="padding: 0px; margin: 0px;">
 <canvas id="canvas1" width="600" height="480" style="background-color: #A9A9A9;">
 Browser not compatible with HTML5 canvas
 </canvas>
</body>
</html>



Add Simple Game Physics (back to top)

Even the simplest physics can make a game look and feel so much better. Instead of just suddenly moving full speed to the right when you press right key, it can be that the character builds speed until they reach normal speed. It could be a case of only taking 1-2 seconds to build the speed, or it could take more like 10 seconds. It all depends on your game.
And there's gravity. There needs to be a fairly realistic rate of falling towards the ground. I don't mean close to earth's gravity, I just mean it can't just fall at a constant speed towards the ground. It needs to accelerate. (Although, this does depend on the game. There may be certain instances where a constant velocity is fine)



So let's start with a canvas of width 500x500. So that there will be room to move, to appreciate the physics a bit more.
<canvas height="500" id="canvas" style="background-color: darkgrey;" width="500">
Browser not compatible with HTML5 canvas
</canvas>


Now here's the javascript:
const FPS = 30;

var playerPosX = 0;
var playerPosY = 0;
var playerVelX = 0;
var playerVelY = 0;

var onGround = 0;

var playerImg = new Image();
playerImg.src = "http://filevaults.com/media/Slash/553481-smiley.png";

var canvas = null;
var context2D = null;
var keys = new Array();

window.onload = init;

window.addEventListener('keydown',keyDown,true);
window.addEventListener('keyup',keyUp,true);
function keyDown(evt){
 keys[evt.keyCode] = true;
}
function keyUp(evt){
 keys[evt.keyCode] = false;
}

function init()
{
 canvas = document.getElementById('canvas');
 context2D = canvas.getContext('2d');
 setInterval(draw, 1000 / FPS);
}

function draw()
{
 // detect user input
 if ((37 in keys &amp;&amp; keys[37]) || (65 in keys &amp;&amp; keys[65])){ //left
  playerVelX -= 3;
 }
 if ((39 in keys &amp;&amp; keys[39]) || (68 in keys &amp;&amp; keys[68])){ //right
  playerVelX += 3;
 }
 if ((38 in keys &amp;&amp; keys[38]) || (87 in keys &amp;&amp; keys[87])){ //up
  jump();
 }
 
 addPhysics();
 
 context2D.clearRect(0, 0, canvas.width, canvas.height);
 context2D.drawImage(playerImg, playerPosX, playerPosY);
}

function jump() {
 if (onGround == 1) {
  playerVelY -= 30;
 }
}

function addPhysics() {

 // because of these two lines, motion can be set using velocity variables
 playerPosX += playerVelX;
 playerPosY += playerVelY;
 
 
if (playerPosY &gt; canvas.height-playerImg.height) {
 onGround = 1;
}
else {
 onGround = 0;
}

// stop character from building up too much speed
// this means the character can realistically accelerate and continue at normal speed
 if (playerVelX &gt;= 10) {
  playerVelX = 10;
 } else if (playerVelX &lt;= -10) {
  playerVelX = -10;
 }
 
// friction
playerVelX *= 0.85;
if (playerVelX &lt; 0.2 &amp;&amp; playerVelX &gt; -0.2)
{ // so that it leaves it as a clean zero when it gets to a stop.
 playerVelX = 0;
}

 // gravity (acceleration of the velocity towards the ground)
 if (onGround == 0) {
 playerVelY += 3;
 }
 else {
 playerVelY = 0; // when on ground, gravity doesn't pull you through the floor
 }
 
}
Result here: http://slashgame.net/html5physics.php



How to Rotate an Image on Canvas (back to top)

Rotation is a tricky one to understand fully, especially for beginners. A lot of people prefer to just blindy accept the way of coding it, and other like to know what the heck they are actually coding. So I'll give the opportunity for both types of people here.

Firstly, I'll put this function here for you to use, this is helpful for any kind of person, but for those of you who just want the code, you only need to take the function and read my bit on how to use it. I'll then explain how rotation works, if you're interested.

Here's the function:
function drawImg(img, pX, pY, oX, oY, w, h, rot) {
 context2D.save();
  context2D.translate(pX+oX, pY+oY);
  context2D.rotate(rot * Math.PI / 180);
  context2D.drawImage(img, 0, 0, w, h, -(oX), -(oY), w, h);
 context2D.restore();
}

How it's used:
img: the image object
pX: the x position of the image
pY: the y position of the image
oX: how far across the image that the origin is
oY: how far down the image that the origin is
w: width of the image
h: height of the image
rot: angle of rotation


Ok, so it's not as simple as just "rotate image". There's a lot more to it. It's more like rotating the canvas, then setting the image's orientation, then resetting the canvas.

- So first it saves the canvas the way it is.
- Then the translate line makes the "start" of the image at the origin you want it to spin.
- It then rotates the actual canvas the amount you want the player to rotate.
- Then the image is drawn, but because the start of the image has changed place, it needs to start drawing at a different place (at the origin).
- It then brings the canvas back to where it was before, leaving the drawn image still showing as rotated.

It took me a while to figure that out at first. I was never able to find a good explanation of how it works. I just hope this helps you readers better.
Although to be honest, it isn't incredibly important that you know how it works. Just that you know how to use it.
Here's an example usage of rotation with canvas: http://slashgame.net/html5gamedevexample4.php



Use HTML5 Audio (back to top)

I'll just show HTML5 Audio being used with javascript without a canvas. Using it in canvas you just include it in the javascript like normal by calling the function that plays the sound. I very much so assume that by this point you can figure that kind of thing out yourself.
The JavaScript accesses the HTML5 audio, and in effect makes an

Example:
var boingSound = new Audio("http://slashgame.net/boing.wav");
function playSound() {
 boingSound.currentTime = 0;
 boingSound.play();
}

Notice how it sets the currentTime to 0 before playing. This is because you can't play the same sound object twice without moving the time back to the start again.


Here is a use of the result of that:
---CLICK HERE---



Conclusion of Tutorial (back to top)

So, by now you should be able to put your wonderful imagination to use, and put your new knowledge of HTML5 game development to practice, and create something awesome.

There may be some things that I haven't explained, but my hope is that I've explained enough so that you are able to figure new things out yourself. Things like complicated physics can be figured out with some Maths knowledge, and game design for the most part comes from your imagination and your ability to understand what people like in games.

Saturday, 20 August 2011

Introduction to JavaScript

It just occurred to me that I've been going on about how to make a HTML5 game, while there's people who want to make a game who haven't even started with programming/scripting at all yet.
Before you get started with games development, you're going to want to have a little bit of experience with the coding first.

So, what I'll do here is introduce you to the basics of JavaScript. I'll go into enough that will allow you to start learning to make HTML5 games.


JavaScript is not Java. This is something too many people get confused with. JavaScript is a scripting language, whereas Java is a compiled language. JavaScript is very loosely based off of the Java language.
And when I say that Java is a compiled language, what I mean by that is, once you write the code, you have to run a compiler to then get the file that you actually run as the program. Scripting languages on the other hand are run line-by-line without compiling the whole code into a file. This means all you have to do is write the code and run the program. (In JavaScript's case, you just write the code then open the web page, and it's running)



Ok so that's what JavaScript is, now let's get into how to write code.
Here is a little snippet of code, I'll then explain it:
<script type="text/javascript">   var string = "Hello";   function writeSomeText()      document.write(string+" World");   } </script> <a onmouseover="this.style.cursor='pointer';" onclick="writeSomeText();"> CLICK HERE </a>

So, you see the <script> HTML tags. That is where the JavaScript goes in.
The first line of JavaScript there is var string = "Hello";
That line creates a variable called string, and gives it a value of "Hello". The semi-colon at the end of the line is part of the JavaScript syntax, it splits the lines up so that when the code is run, it knows how to execute it.
JavaScript is quite good with variables, because it decides itself what type a variable is. In other languages, you may have to tell it what type it is, but JavaScript automatically knows that it is a string value. And if we gave the variable a value of 500 instead of "Hello", it would have known that it was a numeric value. However, "500" is counted as a string.

Now, the next block of code is creating a function.
To make a function, you do function functionName(params) { functionCode }
In my example, I didn't give it any params (parameters), but they are basically for the purpose of passing in a variable for the function to use when you call the function. I'll get to function calling later.
The function code in my example writes text to the document screen. document is an object which holds a function called write(). It takes a parameter which the function then takes and writes to the screen.
In my example, it takes the string variable that we set outside the function, and attaches " World" to it. It joins up to make a string value of "Hello World", but does not change the value of the variable.

Function calling: Outside the <script> tags, we see an <a> element. Since there is no href attribute given, I had to manually add the code that makes the mouse cursor change to the pointer when you mouse over the link. This was done with a line of JavaScript triggered by an event. The event was onmouseover.
The other event I used was onclick, which I used to trigger a line of JavaScript which called our writeSomeText() function. This is where the JavaScript calls up the function with that name and executes the code inside the function.


So, that's my Intro to JavaScript. It's purpose is to show you the syntax, and hopefully allow you to better understand my HTML5 game development guides.
You can move onto this Full HTML5 Game Development Tutorial if you want.

Sunday, 17 July 2011

Snippet - AJAX

This is useful for many things with HTML5 game development. You could use it as a means to pass a user's score to a php script which adds it to a database.
Or you could do it the other way round, and make it get the highscores from the database, and the function would return the script's response, which could be used to then write the scores on the canvas, or wherever.


For Example:
ajaxCall("addScore.php?username=Slash&score=500");

That would have called the php script in addScore.php, and passed in the username and score parameters.
The php script could have simply been written to take those parameters with $_GET['username'] and $_GET['score'], and insert the values into a MySQL database.


This is just a snippet. I might later make a full tutorial on how to keep a scoreboard. But this function will allow you to call any php script with AJAX and use it's responseText if necessary.


The JavaScript Code:
function ajaxCall(scriptURL) {
  var xmlhttp;
  if(window.XMLHttpRequest)
  {
    xmlhttp=new XMLHttpRequest();
  }
  else
  {
    xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
  }
  xmlhttp.onreadystatechange=function()
  {
     if (xmlhttp.readyState==4 && xmlhttp.status==200)
     {
       return xmlhttp.responseText;
     }
  }
  
  xmlhttp.open("GET", scriptURL, true);
  xmlhttp.send();
}


Example PHP Script:
// set up connection
$con = mysql_connect("localhost", "DBuser","DBpass") or die(mysql_error());
mysql_select_db("DBname", $con) or die(mysql_error());

// Get params from the url used
$username = mysql_real_escape_string($_GET['username']);
$score = mysql_real_escape_string($_GET['score']);

// insert the score into the scores table for the user
$query = "INSERT INTO scores (username, score) VALUES ('" . $username . "', '" . $score . "')";
mysql_query($query, $con) or die(mysql_error());


This example PHP script will work for the stuff I mentioned earlier, calling the JavaScript function with something like ajaxCall("addScore.php?username=Slash&score=500");

Note that this is an example to show what goes on with AJAX. However, in a professional situation, PDO would be used rather than MySQL, and jQuery would often be used in the JavaScript. Libraries are used a lot because they are already optimized code and you also have less code to write yourself.

Snippet - Keyboard Input for HTML5 Games

Examples of use:
If you wanted to check if the A key is pressed down:
if (isKeyPressed('a')==true) { /* do whatever */ }
If you wanted to check for the left arrow key being pressed:
isKeyPressed('left')
For escape key:
isKeyPressed('esc')



The Code:
window.addEventListener('keydown',keyPressDown,true);
window.addEventListener('keyup',keyPressUp,true);

function keyPressDown(evt){
 keys[evt.keyCode] = true;
}
function keyPressUp(evt){
 keys[evt.keyCode] = false;
}


function isKeyPressed(checkKey) {
 
 // alphabet
 if ((checkKey == 'a' || checkKey == 'A') && (65 in keys && keys[65])){
  return true;
 }
 else if ((checkKey == 'b' || checkKey == 'B') && (66 in keys && keys[66])){
  return true;
 }
 else if ((checkKey == 'c' || checkKey == 'C') && (67 in keys && keys[67])){
  return true;
 }
 else if ((checkKey == 'd' || checkKey == 'D') && (68 in keys && keys[68])){
  return true;
 }
 else if ((checkKey == 'e' || checkKey == 'E') && (69 in keys && keys[69])){
  return true;
 }
 else if ((checkKey == 'f' || checkKey == 'F') && (70 in keys && keys[70])){
  return true;
 }
 else if ((checkKey == 'g' || checkKey == 'G') && (71 in keys && keys[71])){
  return true;
 }
 else if ((checkKey == 'h' || checkKey == 'H') && (72 in keys && keys[72])){
  return true;
 }
 else if ((checkKey == 'i' || checkKey == 'I') && (73 in keys && keys[73])){
  return true;
 }
 else if ((checkKey == 'j' || checkKey == 'J') && (74 in keys && keys[74])){
  return true;
 }
 else if ((checkKey == 'k' || checkKey == 'K') && (75 in keys && keys[75])){
  return true;
 }
 else if ((checkKey == 'l' || checkKey == 'L') && (76 in keys && keys[76])){
  return true;
 }
 else if ((checkKey == 'm' || checkKey == 'M') && (77 in keys && keys[77])){
  return true;
 }
 else if ((checkKey == 'n' || checkKey == 'N') && (78 in keys && keys[78])){
  return true;
 }
 else if ((checkKey == 'o' || checkKey == 'O') && (79 in keys && keys[79])){
  return true;
 }
 else if ((checkKey == 'p' || checkKey == 'P') && (80 in keys && keys[80])){
  return true;
 }
 else if ((checkKey == 'q' || checkKey == 'Q') && (81 in keys && keys[81])){
  return true;
 }
 else if ((checkKey == 'r' || checkKey == 'R') && (82 in keys && keys[82])){
  return true;
 }
 else if ((checkKey == 's' || checkKey == 'S') && (83 in keys && keys[83])){
  return true;
 }
 else if ((checkKey == 't' || checkKey == 'T') && (84 in keys && keys[84])){
  return true;
 }
 else if ((checkKey == 'u' || checkKey == 'U') && (85 in keys && keys[85])){
  return true;
 }
 else if ((checkKey == 'v' || checkKey == 'V') && (86 in keys && keys[86])){
  return true;
 }
 else if ((checkKey == 'w' || checkKey == 'W') && (87 in keys && keys[87])){
  return true;
 }
 else if ((checkKey == 'x' || checkKey == 'X') && (88 in keys && keys[88])){
  return true;
 }
 else if ((checkKey == 'y' || checkKey == 'Y') && (89 in keys && keys[89])){
  return true;
 }
 else if ((checkKey == 'z' || checkKey == 'Z') && (90 in keys && keys[90])){
  return true;
 }
 
 
 //numbers
 else if ((checkKey == '0') && (48 in keys && keys[48])){
  return true;
 }
 else if ((checkKey == '1') && (49 in keys && keys[49])){
  return true;
 }
 else if ((checkKey == '2') && (50 in keys && keys[50])){
  return true;
 }
 else if ((checkKey == '3') && (51 in keys && keys[51])){
  return true;
 }
 else if ((checkKey == '4') && (52 in keys && keys[52])){
  return true;
 }
 else if ((checkKey == '5') && (53 in keys && keys[53])){
  return true;
 }
 else if ((checkKey == '6') && (54 in keys && keys[54])){
  return true;
 }
 else if ((checkKey == '7') && (55 in keys && keys[55])){
  return true;
 }
 else if ((checkKey == '8') && (56 in keys && keys[56])){
  return true;
 }
 else if ((checkKey == '9') && (57 in keys && keys[57])){
  return true;
 }
 
 
 // special keys
 else if ((checkKey == 'left' || checkKey == 'LEFT') && (37 in keys && keys[37])){
  return true;
 }
 else if ((checkKey == 'right' || checkKey == 'RIGHT') && (39 in keys && keys[39])){
  return true;
 }
 else if ((checkKey == 'up' || checkKey == 'UP') && (38 in keys && keys[38])){
  return true;
 }
 else if ((checkKey == 'down' || checkKey == 'DOWN') && (40 in keys && keys[40])){
  return true;
 }
 else if ((checkKey == 'esc' || checkKey == 'ESC' || checkKey == 'escape' || checkKey == 'ESCAPE' ) && (27 in keys && keys[27])){
  return true;
 }
 
}

Saturday, 16 July 2011

Snippet - Mouse Input for HTML5 Games

The following code can all be copy-pasted to your javascript and used how you wish.
Keep in mind the clicked() function is empty, because you chose what goes in there if you need to use it. The rest simply set variables that can be used later in the code. (i.e. mouseX, mouseY and ismousedown)


var mouseX = 0;
var mouseY = 0;
window.addEventListener('mousemove', mouseMoved, true);
function mouseMoved(e) {
 mouseX = e.pageX;
 mouseY = e.pageY;
}
// ^put that in your code and you will be able
// to use mouseX and mouseY variables anywhere in that code.


window.addEventListener('click', clicked, true);
function clicked(e) {
 // you can put whatever you want in here
 // for example, you could use the mouseX and mouseY variables
 // to place a bullet-hole image where the mouse was when clicked
}


var ismousedown = 0;
window.onmousedown = function(e) {
 ismousedown = 1;
}
window.onmouseup = function(e) {
 ismousedown = 0;
}
// ^with this code, you can now check the ismousedown variables
// at any time to check if the mouse is being clicked
// useful for mouse dragging or for holding the "shoot button", etc.

Snippet - Play Sound (HTML5 Audio)

Very simple set up and function:
var boingSound = new Audio("http://slashgame.net/boing.wav");
function playSound() {
 boingSound.currentTime = 0;
 boingSound.play();
}


Example usage: ---CLICK HERE---

Taken from HTML5 Audio Quick Tip

Snippet - Draw Text to HTML5 Canvas

This function draws text to the canvas with a specified position, color and font.
function drawCanvasText(txt, pX, pY, clr, fnt) {
 context2D.fillStyle = clr; // color
 context2D.font = fnt; // font
 context2D.fillText(txt, pX, pY); // text at position X, Y
}


Example Usage:
drawCanvasText("drawing text yas", 50, 50, "black", "bold 30px sans-serif");

Snippet - Draw Image with Rotation (HTML5 Games)

This is a function that draws an image with specified rotation.
(I first posted this function in the Rotate Image on Canvas tutorial.

function drawImg(img, pX, pY, oX, oY, w, h, rot) {
 context2D.save();
  context2D.translate(pX+oX, pY+oY);
  context2D.rotate(rot * Math.PI / 180);
  context2D.drawImage(img, 0, 0, w, h, -(oX), -(oY), w, h);
 context2D.restore();
}

Note:
img: the image object
pX: the x position of the image
pY: the y position of the image
oX: how far across the image that the origin is
oY: how far down the image that the origin is
w: width of the image
h: height of the image
rot: angle of rotation

Monday, 27 June 2011

User Input - Mouse Input for HTML5 Games

Note: This page has broken links and non-existant images. The code is correct, but you won't be able to use the exact code I give. Use your own images or learn from the code.
Note to self: Update this page :P



A while ago I showed you guys how to do keyboard input here and here. Now I'll show you how to do mouse input.

It's fairly simple, just use an eventListener for the event "mousemove" and use a function that takes the event as a parameter, and use the e.pageX and e.pageY for the mouse's X and Y position.

And for mouse clicks, just use eventListener for the "click" event, and use a function that does whatever. In the example I give, it sets the position of an image to the position of the mouse at the point it is clicked. In this case, a bullethole in the position the cursor was pointing at.


Here is the code:
<html>
<head>
<script type="text/javascript">
const FPS = 60;

var canvas = null;
var context2D = null;

var cursorImg = new Image();
cursorImg.src = "images/cursorexample.png";

var bulletHoleImg = new Image();
bulletHoleImg.src = "images/bullethole.png";
var bulletHolesX = new Array();
var bulletHolesY = new Array();
for (var i=0; i<50; i++) {
 bulletHolesX[i] = -500;
 bulletHolesY[i] = -500;
}
bulletNum = 0;

window.addEventListener('mousemove', mouseMoved, true);
window.addEventListener('click', clicked, true);
var mouseX = 0;
var mouseY = 0;

window.onload = init;
function init() {
 canvas = document.getElementById('canvas1');
 context2D = canvas.getContext('2d');
 
 setInterval(draw, 1000/FPS);
}

function draw() {
 context2D.clearRect(0, 0, canvas.width, canvas.height);
 for (var i=0; i<50; i++) {
  context2D.drawImage(bulletHoleImg, bulletHolesX[i]-(bulletHoleImg.width/2), bulletHolesY[i]-(bulletHoleImg.height/2));
 }
 context2D.drawImage(cursorImg, mouseX-(cursorImg.width/2), mouseY-(cursorImg.width/2));
}

function mouseMoved(e) {
 
 mouseX = e.pageX;
 mouseY = e.pageY;
 
}

function clicked(e) {
 
 bulletHolesX[bulletNum] = mouseX;
 bulletHolesY[bulletNum] = mouseY;
 bulletNum++;
 if (bulletNum > 50) {
  bulletNum = 0;
 }
 
}
</script>
</head>
<body style="padding: 0px; margin: 0px;">
 <canvas id="canvas1" width="600" height="480" style="background-color: #A9A9A9;">
 Browser not compatible with HTML5 canvas
 </canvas>
</body>
</html>


Here is the result: here

Monday, 20 June 2011

Quick Tip - HTML5 Audio for Game

Note: Audio file used in this page is non-existant. Must update this page soon.

I'll just show HTML5 Audio being used with javascript without a canvas. Using it in canvas you just include it in the javascript like normal by calling the function that plays the sound.
The JavaScript accesses the HTML5 audio, and in effect makes an <audio> element. But it's good this way, as it's less cluttered without the tags actually being there or being created.

Example:
var boingSound = new Audio("http://slashgame.net/boing.wav");
function playSound() {
 boingSound.currentTime = 0;
 boingSound.play();
}

Notice how it sets the currentTime to 0 before playing. This is because you can't play the same sound object twice without moving the time back to the start again.

Here is a use of the result of that:
---CLICK HERE---

Sunday, 19 June 2011

Quick Tip - fillText JavaScript Function - HUD

context2D.fillStyle = "white";
context2D.font = 'bold 30px sans-serif';
context2D.fillText("POINTS: "+numOfPoints, canvas.width-200, 30);
That right there is an example of drawing text to the canvas. It writes it on the top right of the canvas. That particular example is what would serve as the HUD in a game.


Here it is in practise:
(you get points for moving right and left)
Browser not compatible.
Recent versions of Firefox, Opera, Google Chrome and Safari work for this game.
If you are using Internet Explorer; Stop using it immediately before you die of idiocy.

Monday, 13 June 2011

3D Object in HTML5 Canvas

I was going to make a rotating cube to show you guys, but i decided to just quickly make a very simple rotating 3D shape instead.

This demonstrates that 3D is possible, even though there isn't a standard for 3D rendering in the canvas API. Here is the example.


You can look at the source (right click -> source/view source/open source), but it is very messy and hard-coded.
My original plan was to explain every bit of it; but that is a very tricky thing to do, so I just stopped there to demonstrate it's possibility.
What I will do instead is make a 3D engine for you guys to use or examine. A 3D engine that allows free use of z-axis values, making it very simple to create 3D objects.

In the example I linked, it uses a bit of simple maths (the maths is simple, but figuring out where and how to use it is not).
I recommend anyone wishing to do 3D from scratch to learn the maths first.


When you think about a 3D object on a screen, you need to look at it as a "2D projection" of the 3D object. First you must have the 3D points of reference and then use the maths to calculate where these points would be on a 2D projection of the 3D object, then join the points with lines.
That's basically how it works. I might explain it more when I post the 3D engine once I've written it.

Thursday, 9 June 2011

Canvas Background Image

In some posts, I use this line to clear the screen before drawing player image:
context2D.clearRect(0, 0, canvas.width, canvas.height);
You can either replace this line, or add a line after it, drawing the background image.
I would personally add the line after clearing, in case at some point we want to do other things with menus or something that could potentially affect it.

You could indeed just use CSS to add a background-image to the canvas element, but that is very bad practice, because many games have a moving background.


Shut up and tell me how to do it...
So, first you need to make the image object. Something like this:
var bgImg = new Image();
bgImg.src = "images/bg.png";
And then in the draw function (if you're not following me, come back to this when you've got to the stage of using a Game Loop), just after the screen is cleared (or instead of clearing the screen), you would want to use this line:
context2D.drawImage(bgImg, 0, 0);
If you want to use a scrolling background, replace the "0, 0" with x and y position variables, and update their values in the relevant place depending on how you want it to work. Remember that position is always relative to the top left corner by default.

Tuesday, 24 May 2011

Simple Game Physics

Even the simplest physics can make a game look and feel so much better. Instead of just suddenly moving full speed to the right when you press right key, it can be that the character builds speed until they reach normal speed. It could be a case of only taking 1-2 seconds to build the speed, or it could take more like 10 seconds.
It all depends on your game.

And there's gravity. There needs to be a fairly realistic rate of falling towards the ground. I don't mean close to earth's gravity, I just mean it can't just fall at a constant speed towards the ground. It needs to accelerate. (Although, this does depend on the game. There may be certain instances where a constant velocity is fine, but in most cases, it will need some sort of acceleration)

That's the simple physics. I'll go into the more complicated stuff in a later post. So let's start with a canvas of width 500x500. So that there will be room to move, to appreciate the physics a bit more.
<canvas id="canvas" width="500" height="500" style="background-color: #A9A9A9;">
Browser not compatible with HTML5 canvas
</canvas>
Now here's the javascript:
const FPS = 30;

var playerPosX = 0;
var playerPosY = 0;
var playerVelX = 0;
var playerVelY = 0;

var onGround = 0;

var playerImg = new Image();
playerImg.src = "http://i.imgur.com/nEYjaIe.png";

var canvas = null;
var context2D = null;
var keys = new Array();

window.onload = init;

window.addEventListener('keydown',keyDown,true);
window.addEventListener('keyup',keyUp,true);
function keyDown(evt){
 keys[evt.keyCode] = true;
}
function keyUp(evt){
 keys[evt.keyCode] = false;
}

function init()
{
 canvas = document.getElementById('canvas');
 context2D = canvas.getContext('2d');
 setInterval(draw, 1000 / FPS);
}

function draw()
{
 // detect user input
 if ((37 in keys && keys[37]) || (65 in keys && keys[65])){ //left
  playerVelX -= 3;
 }
 if ((39 in keys && keys[39]) || (68 in keys && keys[68])){ //right
  playerVelX += 3;
 }
 if ((38 in keys && keys[38]) || (87 in keys && keys[87])){ //up
  jump();
 }
 
 addPhysics();
 
 context2D.clearRect(0, 0, canvas.width, canvas.height);
 context2D.drawImage(playerImg, playerPosX, playerPosY);
}

function jump() {
 if (onGround == 1) {
  playerVelY -= 30;
 }
}

function addPhysics() {

 // because of these two lines, motion can be set using velocity variables
 playerPosX += playerVelX;
 playerPosY += playerVelY;
 
 
if (playerPosY > canvas.height-playerImg.height) {
 onGround = 1;
}
else {
 onGround = 0;
}

// stop character from building up too much speed
// this means the character can realistically accelerate and continue at normal speed
 if (playerVelX >= 10) {
  playerVelX = 10;
 } else if (playerVelX <= -10) {
  playerVelX = -10;
 }
 
// friction
playerVelX *= 0.85;
if (playerVelX < 0.2 && playerVelX > -0.2)
{ // so that it leaves it as a clean zero when it gets to a stop.
 playerVelX = 0;
}

 // gravity (acceleration of the velocity towards the ground)
 if (onGround == 0) {
 playerVelY += 3;
 }
 else {
 playerVelY = 0; // when on ground, gravity doesn't pull you through the floor
 }
 
}

This is correct for the sake of physics, however it is not correctly structured. What I'd like you to do is use your knowledge from this, and from the Game Loop Article to make a properly structured simple game with physics.
If you can do that, then you are on the right track.

I think my next physics post will be on making an object rotate properly when it hits the ground, so that it will land in a realistic manner. (like a box hitting the ground if it's rotated a bit)

Saturday, 21 May 2011

Rotate Image on Canvas

This is where it gets a little bit tricky. Once it's figured out, it's easy from then on in. However, figuring it out in the first place can be a bit of a pain.

It's not as simple as just "rotate image". There's a lot more to it. It's more like rotating the canvas, then setting the image's orientation, then resetting the canvas.
I'll show some example code, then explain that in more detail.

Let's just go with a small 100x100 canvas.
<canvas id="canvas" width="100" height="100" style="background-color: #A9A9A9;">
Browser not compatible with HTML5 canvas
</canvas>

Now here's the javascript:

const FPS = 30;
var playerPosX = 0;
var playerPosY = 0;
var playerRot = 0;
var onGround = 0;
var playerImg = new Image();
playerImg.src = "http://i.imgur.com/nEYjaIe.png";

var canvas = null;
var context2D = null;
var keys = new Array();

window.onload = init;

window.addEventListener('keydown',keyDown,true);
window.addEventListener('keyup',keyUp,true);
function keyDown(evt){
 keys[evt.keyCode] = true;
}
function keyUp(evt){
 keys[evt.keyCode] = false;
}

function init()
{
 canvas = document.getElementById('canvas');
 context2D = canvas.getContext('2d');
 setInterval(draw, 1000 / FPS);
}

function draw()
{
 // detect user input
 if ((37 in keys && keys[37]) || (65 in keys && keys[65])){ //left
  playerRot -= 3;
 }
 if ((39 in keys && keys[39]) || (68 in keys && keys[68])){ //right
  playerRot += 3;
 }
 
 
 context2D.clearRect(0, 0, canvas.width, canvas.height);

  context2D.save();
 context2D.translate(playerPosX+(playerImg.width/2), playerPosY+(playerImg.height/2));
 context2D.rotate(playerRot * Math.PI / 180);
 context2D.drawImage(playerImg, 0, 0, playerImg.width, playerImg.height, -(playerImg.width/2), -(playerImg.height/2), playerImg.width, playerImg.height);
 context2D.restore();
}


Result: Arrow keys or A and D to spin left and right.
Browser not compatible with HTML5 canvas


So, the main bit is this:
context2D.save();
 context2D.translate(playerPosX+(playerImg.width/2), playerPosY+(playerImg.height/2));
 context2D.rotate(playerRot * Math.PI / 180);
 context2D.drawImage(playerImg, 0, 0, playerImg.width, playerImg.height, -(playerImg.width/2), -(playerImg.height/2), playerImg.width, playerImg.height);
 context2D.restore();

- So first it saves the canvas the way it is.
- Then the translate line makes the "start" of the image at the origin you want it to spin (in this case, the center).
- It then rotates the actual canvas the amount you want the player to rotate.
- Then the image is drawn, but because the start of the image has changed place, it needs to start drawing at a different place; which is half of the width of the image to the left, and half of the height of the image to the top.
- It then brings the canvas back to where it was before, leaving the drawn image still showing as rotated.
It took me a while to figure that out at first. I was never able to find a good explanation of how it works. I just hope this helps you readers better.
Although to be honest, it isn't incredibly important that you know how it works. Just that you know how to use it.


EDIT:
This is a function that draws an image, it takes rotation into account. Use it as you wish.
function drawImg(img, pX, pY, oX, oY, w, h, rot) {
 context2D.save();
  context2D.translate(pX+oX, pY+oY);
  context2D.rotate(rot * Math.PI / 180);
  context2D.drawImage(img, 0, 0, w, h, -(oX), -(oY), w, h);
 context2D.restore();
}

Note:
img: the image object
pX: the x position of the image
pY: the y position of the image
oX: how far across the image that the origin is
oY: how far down the image that the origin is
w: width of the image
h: height of the image
rot: angle of rotation

Friday, 20 May 2011

User Input - Make it Easier on Yourself

I wanted to help make it a bit easier for you guys for getting keyboard presses. I was going to write a little library, but it ended up being that it only really needs this one function.
In my last post I showed an ASCII table that would be handy for user input. But with this, you don't need it.

Just copy the code from the box below, and either put it in a new file and include it in your page, or put it in an existing included script.

Examples of use:
If you wanted to check if the A key is pressed down:
if (isKeyPressed('a')==true) { /* do whatever */ }
If you wanted to check for the left arrow key being pressed:
isKeyPressed('left')
For escape key:
isKeyPressed('esc')
The Code:
window.addEventListener('keydown',keyPressDown,true);
window.addEventListener('keyup',keyPressUp,true);

function keyPressDown(evt){
 keys[evt.keyCode] = true;
}
function keyPressUp(evt){
 keys[evt.keyCode] = false;
}


function isKeyPressed(checkKey) {
 
 // alphabet
 if ((checkKey == 'a' || checkKey == 'A') && (65 in keys && keys[65])){
  return true;
 }
 else if ((checkKey == 'b' || checkKey == 'B') && (66 in keys && keys[66])){
  return true;
 }
 else if ((checkKey == 'c' || checkKey == 'C') && (67 in keys && keys[67])){
  return true;
 }
 else if ((checkKey == 'd' || checkKey == 'D') && (68 in keys && keys[68])){
  return true;
 }
 else if ((checkKey == 'e' || checkKey == 'E') && (69 in keys && keys[69])){
  return true;
 }
 else if ((checkKey == 'f' || checkKey == 'F') && (70 in keys && keys[70])){
  return true;
 }
 else if ((checkKey == 'g' || checkKey == 'G') && (71 in keys && keys[71])){
  return true;
 }
 else if ((checkKey == 'h' || checkKey == 'H') && (72 in keys && keys[72])){
  return true;
 }
 else if ((checkKey == 'i' || checkKey == 'I') && (73 in keys && keys[73])){
  return true;
 }
 else if ((checkKey == 'j' || checkKey == 'J') && (74 in keys && keys[74])){
  return true;
 }
 else if ((checkKey == 'k' || checkKey == 'K') && (75 in keys && keys[75])){
  return true;
 }
 else if ((checkKey == 'l' || checkKey == 'L') && (76 in keys && keys[76])){
  return true;
 }
 else if ((checkKey == 'm' || checkKey == 'M') && (77 in keys && keys[77])){
  return true;
 }
 else if ((checkKey == 'n' || checkKey == 'N') && (78 in keys && keys[78])){
  return true;
 }
 else if ((checkKey == 'o' || checkKey == 'O') && (79 in keys && keys[79])){
  return true;
 }
 else if ((checkKey == 'p' || checkKey == 'P') && (80 in keys && keys[80])){
  return true;
 }
 else if ((checkKey == 'q' || checkKey == 'Q') && (81 in keys && keys[81])){
  return true;
 }
 else if ((checkKey == 'r' || checkKey == 'R') && (82 in keys && keys[82])){
  return true;
 }
 else if ((checkKey == 's' || checkKey == 'S') && (83 in keys && keys[83])){
  return true;
 }
 else if ((checkKey == 't' || checkKey == 'T') && (84 in keys && keys[84])){
  return true;
 }
 else if ((checkKey == 'u' || checkKey == 'U') && (85 in keys && keys[85])){
  return true;
 }
 else if ((checkKey == 'v' || checkKey == 'V') && (86 in keys && keys[86])){
  return true;
 }
 else if ((checkKey == 'w' || checkKey == 'W') && (87 in keys && keys[87])){
  return true;
 }
 else if ((checkKey == 'x' || checkKey == 'X') && (88 in keys && keys[88])){
  return true;
 }
 else if ((checkKey == 'y' || checkKey == 'Y') && (89 in keys && keys[89])){
  return true;
 }
 else if ((checkKey == 'z' || checkKey == 'Z') && (90 in keys && keys[90])){
  return true;
 }
 
 
 //numbers
 else if ((checkKey == '0') && (48 in keys && keys[48])){
  return true;
 }
 else if ((checkKey == '1') && (49 in keys && keys[49])){
  return true;
 }
 else if ((checkKey == '2') && (50 in keys && keys[50])){
  return true;
 }
 else if ((checkKey == '3') && (51 in keys && keys[51])){
  return true;
 }
 else if ((checkKey == '4') && (52 in keys && keys[52])){
  return true;
 }
 else if ((checkKey == '5') && (53 in keys && keys[53])){
  return true;
 }
 else if ((checkKey == '6') && (54 in keys && keys[54])){
  return true;
 }
 else if ((checkKey == '7') && (55 in keys && keys[55])){
  return true;
 }
 else if ((checkKey == '8') && (56 in keys && keys[56])){
  return true;
 }
 else if ((checkKey == '9') && (57 in keys && keys[57])){
  return true;
 }
 
 
 // special keys
 else if ((checkKey == 'left' || checkKey == 'LEFT') && (37 in keys && keys[37])){
  return true;
 }
 else if ((checkKey == 'right' || checkKey == 'RIGHT') && (39 in keys && keys[39])){
  return true;
 }
 else if ((checkKey == 'up' || checkKey == 'UP') && (38 in keys && keys[38])){
  return true;
 }
 else if ((checkKey == 'down' || checkKey == 'DOWN') && (40 in keys && keys[40])){
  return true;
 }
 else if ((checkKey == 'esc' || checkKey == 'ESC' || checkKey == 'escape' || checkKey == 'ESCAPE' ) && (27 in keys && keys[27])){
  return true;
 }
 
}

Thursday, 19 May 2011

Game Loop for a HTML5 Game

In my last post, I showed you how to simply display an image on the canvas. But before going onto anything else, I'll show how to include a standard game loop. I'm using HTML5 games as example here, but the concept of the loop applies to most other kinds of game development.

So obviously you'd first put the canvas in the HTML, like so:
<canvas id="canvas" width="400" height="100" style="background-color: #A9A9A9;">
Browser not compatible with HTML5 canvas
</canvas>


A game loop is the normal structure a game would be built with.
First it would initiate the loop, then the loop would involve checking for user input, then all objects would be updated as required, then rendering/drawing the scene based on the object and variable values, and start again from checking user input.


This is an example of doing this in javascript:
const FPS = 30;

var playerPosX = 0;
var playerPosY = 0;

var playerImg = new Image();
playerImg.src = "http://i.imgur.com/nEYjaIe.png";

var canvas = null;
var context2D = null;
var keys = new Array();

window.addEventListener('keydown',keyDown,true);
window.addEventListener('keyup',keyUp,true);
function keyDown(evt){
 keys[evt.keyCode] = true;
}
function keyUp(evt){
 keys[evt.keyCode] = false;
}

window.onload = init;

function init()
{
 canvas = document.getElementById('canvas');
 context2D = canvas.getContext('2d');
 setInterval(runGameLoop, 1000 / FPS);
}

function runGameLoop()
{
 handleInput();
 update();
 draw();
}

function handleInput()
{
 if ((37 in keys && keys[37]) || (65 in keys && keys[65])){ //left
  playerPosX -= 2;
 }
 if ((39 in keys && keys[39]) || (68 in keys && keys[68])){ //right
  playerPosX += 2;
 }
}

function update()
{
 // Not used in this example
 // In a game with physics and logic, this is used for calculations, etc.
 // For example, in handleInput(), it could have been updating Velocity
 // rather than Position, so in this function you would update the
 // Position based on the current Velocity values
 // e.g:
 // playerPosX = playerPosX + playerVelX;
 // playerPosY = playerPosY + playerVelY;
 //
 // We will get to this kind of thing in the Simple Game Physics Article
}

function draw()
{
 context2D.clearRect(0, 0, canvas.width, canvas.height);
 context2D.drawImage(playerImg, playerPosX, playerPosY);
}


You will firstly declare all global variables, then add "event listeners" for input. For the sake of organization, I put a couple of functions right there to handle keypresses, which are called by the event listeners. These functions are called on keyDown and keyUp events, this means it will set relevant elements of an array to "true" or "false" depending on the key states, meaning we can later use this array to tell whether a key is pressed or not.

Then you'll see that when the window has been loaded, it will call the init function. Here is where we will initialize the canvas and the 2D context. Then the main point of this tutorial, it will call the runGameLoop() function 30 times a second.

In the runGameLoop() function, it will simply call 3 functions, which are the parts that will make the game actually run.

The handleInput() function checks the keys array, looking for what keys are currently pressed. If there are keys pressed that we can use (in this case, left and/or right), it will update the relevant variables. (In a more complicated script, we would usually have another function or other functions for things like movement, etc.

Then there is a call to the update() function, however it is not used in this example. In a more complicated example, all logic and calculations are handled in the update function.

Then draw() is called, which basically renders everything to the canvas, using the variables which have been manipulated through input and the logic done through update. This function is where everything in the current loop actually becomes "reality" in the canvas.

Then of course everything is repeated. But remember those 3 functions are called 30 times every second. This is why games are so responsive from input.


And it's as simple as that. With that knowledge, you can make a simple game. Here's the result of the example I just gave (use arrow keys or A and D to move left and right):
Browser not compatible with HTML5 canvas

Wednesday, 18 May 2011

Display Image on Canvas (Introduction to HTML5 Canvas)

This is about the simplest example of the use of HTML5 canvas you can get. This is to introduce you to the HTML5 canvas, to show how the canvas can be set up and drawn in. Once you've got this down, you can move onto using the canvas in more interesting ways.

Firstly, you would have this in the html of the page:
<canvas id="canvas" width="400" height="400">
Browser not compatible with HTML5 canvas
</canvas>
The id of the canvas element has been set to "canvas", which is how the javascript can identify the right canvas element to manipulate.
The width and height of the canvas will be 400px.
And if an incompatible browser is used, it will display the text "Browser not compatible with HTML5 canvas".


And here is an example of the kind of javascript you could use to draw an image (you could have this in script tags or have it in a .js file and call it from src attribute of script tags):
var canvas = document.getElementById('canvas');
var context2D = canvas.getContext('2d');

var img = new Image();
img.src = "http://www.blogger.com/img/logo40.png";
context2D.drawImage(img, 100, 50);
So first it gets the canvas element by using the id we gave it. It then creates the 2D context with that canvas element.
It then loads a new image object and then tells it to use the image from http://www.blogger.com/img/logo40.png by assigning it to the src variable of the Image object.

Then it uses the 2D graphics API by calling the drawImg() function.
The first parameter of the function is looking for an image object, the second is the x-position and the third is the y-position.


So here it is (I added style="background-color: #A9A9A9;" to the canvas so you can see it fully):
Browser not compatible with HTML5 canvas
So there we go, that is an extremely simple use of the canvas. This is just to get you kick-started.
Here's a pastebin of an example full HTML file for this: http://pastebin.com/zrsrdAGP