Jump to content

  • Log In with Google      Sign In   
  • Create Account

Interested in a FREE copy of HTML5 game maker Construct 2?

We'll be giving away three Personal Edition licences in next Tuesday's GDNet Direct email newsletter!

Sign up from the right-hand sidebar on our homepage and read Tuesday's newsletter for details!


Like
14Likes
Dislike

How to Get Started with HTML5

By Maksim Mikityanskiy | Published Sep 05 2013 10:29 AM in Game Programming
Peer Reviewed by (EDI, Josh Vega, Dave Hunt)

javascript getting started basic html5

The following article will be a very minimalist and straightforward guide to getting started with HTML5. While it is targeted at beginners, some coding experience is preferable since I won't bother with explaining Javascript basics. I'll leave that to other online tutorials or a Intro to Compsci course. This also is not platform specific in any way. It should run equally well on Linux, Windows or MacOS.

The HTML


Since this will be a web game, an HTML file is required. This is not a proper web page; it's just enough to make it work.


<!DOCTYPE html>

<script src="http://code.jquery.com/jquery-latest.js"></script>
<script src="game.js"></script>

<body bgcolor=#808080>

<canvas id="gameCanvas" width="800" height="600"
	onContextMenu="javascript: return false;"></canvas>

</body>


The first line specifies which HTML version to use, specifically 5.

Note:  Some older versions of Internet Explorer force compatability mode on certain web domains which is impossible to override from the web page. This may have been fixed since I last used Internet Explorer. It isn't an issue when testing, but if you try to put your code into a blogspot for example, HTML5 features like canvas may not work for that reason.


The second line is a dependency. JQuery does a lot of very useful things, but I will only be using it for mouse input in this article. The third line is a link to the script containing game logic.

The background color is not necessary but I find it useful.

Finally, you have the HTML5 canvas. The only unusual thing here is the onContextMenu; it returns false when the user right clicks on the canvas and as a result, no menu pops up.

The Game Logic


Declarations


Now to the game logic that goes in game.js. First come the declarations:

var canvasID, context;
var cursorX = 0, cursorY = 0;
var canvasX = 0, canvasY = 0, canvasW = 800, canvasH = 600;
var playerScore=0, aiScore=0;

canvasID is the canvas itself. The context is an object specific to the canvas that contains all the drawing functionality.

The cursor location is self explanatory. The canvas position is necessary in order to calculate the cursor position relative to the canvas. Canvas dimensions as variables also allows for greater flexibility while coding.

Mouse Code and Initialization


These two things need to be done first, which is the only reason why they are lumped together:

function OnMouseMove(e){
	cursorX = e.pageX-canvasX;
	cursorY = e.pageY-canvasY;
}

$(document).ready(function(){
	canvasID = document.getElementById("gameCanvas");
	canvasID.addEventListener("mousemove", OnMouseMove, false);
	context = canvasID.getContext('2d');
	var rect = canvasID.getBoundingClientRect();
	canvasX = rect.left; canvasY = rect.top;
	canvasW = rect.right-canvasX; canvasH = rect.bottom-canvasY;
})

The OnMouseMove function takes an Event Handler as an argument. The event handler has the cursor position relative to the upper left corner of the page, not of the canvas. This is where canvasX and canvasY come in.

The next bit is JQuery magic. When the document is ready (everything is loaded) the function is executed.

Fetching the canvasID is straightforward.

The next line is the last of the mouse input code. It adds an event listener that calls OnMouseMove when the mouse is moved. There are also mousedown and mouseup for mouse button presses and releases. e.which in the event handler specifices which button was pressed.

Context fetching is simple.

Next is where we find the actual location and dimensions of the canvas. getBoundingClientRect() returns the space which is taken up by the client. Getting the location is trivial. The rect right and bottom are the sum of the y position & height and the x position & width.

The Update Loop


function Run(){
	context.fillStyle="black";
	
	context.clearRect(0,0, canvasW, canvasH);
	context.fillRect(0,0, canvasW, canvasH);
}

setInterval(Run,20);

Run will be the update loop. This is where everything that needs to be executed repeatedly will be put. setInterval tells the browser that it needs to be executed every 20 ms (or whatever you specify).

Now to the drawing code. fillStyle and strokeStyle specify the color which you will be working with. The former is for filling shapes, and the latter is for drawing lines.

clearRect empties the canvas of data. This doesn't really matter when you're starting out but it becomes important when you deal with transparency and compositing. The arguments are x, y, width and height. fillRect should be self explanatory; it takes the same arguments.

Drawing the Score


function DrawScores(){
	context.fillStyle = "white";
	context.font = "16px sans-serif";
	context.fillText(aiScore, 30,30);
	context.fillText(playerScore, canvasW-50,30);
}

We have already worked with fillStyle.

The font is specified as a string containing size and typeface. A couple of other valid typefaces are serif and monotype.

fillText takes a string, x coordinate and y coordinate as arguments. strokeText will draw an outline around the text; just be sure to specify strokeStyle instead.

Finally, call it in the Run function after you clear the canvas.

function Run(){
	context.fillStyle="black";
	
	context.clearRect(0,0, canvasW, canvasH);
	context.fillRect(0,0, canvasW, canvasH);
    
	DrawScores();
}

The Classes


Javascript doesn't have classes like most other programming languages do, but they work. The only two things really necessary for a ping-pong game are the ball and the paddles.

The Ball

function Ball(){
	this.radius = 8;
	this.x = canvasW/2;
	this.y = canvasH/2;
	this.vx = 5;
	this.vy = 0;
	
	this.Draw = function(){
		//...\\
	}
	
	this.Update = function(){
        //...\\
	}
}

The above code includes everything the ball will need; radius, position, and velocity. It will also need a Draw function and Update function. The Draw function is the simplest:

this.Draw = function(){
    context.fillStyle = "white";
    
    context.beginPath();
    context.arc(this.x, this.y, this.radius, 0, 3.1416*2);
    context.closePath();
    
    context.fill();
}

The only slightly unusual thing about drawing circles in HTML5 is the fact that the context doesn't have a function for explicitly drawing them. Instead, one can create an arc path. First call the beginPath function, then create an arc of angle 2π, and finally close the path. The arguments are x position, y position, radius, start angle and end angle. More complicated paths are possible, but that is beyond the scope of this article.

Now to the next function:

	this.Update = function(){
    this.x += this.vx;
    this.y += this.vy;
    //move the ball
    
    if(this.x > playerPaddle.x - playerPaddle.w/2 - this.radius){//check if the ball has traveled 
        	//far enough to the right to possibly interact with the right paddle.
        if(this.y >= playerPaddle.y - playerPaddle.h/2 && this.y <= playerPaddle.y + playerPaddle.h/2){
            	//check if it actually hit the paddle
            this.vy = (playerPaddle.y-this.y)*-0.4; //change the y velocity depending on which part 
            	//of the paddle the ball hit.
            this.x = playerPaddle.x - playerPaddle.w/2 - this.radius; //moves the ball out of the paddle
            this.vx*=-1; //make the ball bounce off
        }else{//if the player misses the ball, incriment the ai score and reset the ball.
            aiScore++;
            this.vy=0;
            this.x = canvasW/2;
            this.y = canvasH/2;
        }
        aiPaddle.AIChangeOffset();//AI thing, will make sense later.
    }
    if(this.x < aiPaddle.x + aiPaddle.w/2 + this.radius){//same thing
        if(this.y >= aiPaddle.y - aiPaddle.h/2 && this.y <= aiPaddle.y + aiPaddle.h/2){
            this.vy = (aiPaddle.y-this.y)*-0.2;
            this.x = aiPaddle.x + aiPaddle.w/2 + this.radius;
            this.vx*=-1;
        }else{
            playerScore++;
            this.vy=0;
            this.x = canvasW/2;
            this.y = canvasH/2;
        }
    }
    
    if(this.y<this.radius){
        this.vy*=-1; this.y=this.radius;}
    else if(this.y>canvasH-this.radius){
        this.vy*=-1; this.y=canvasH-this.radius;}
    //have the ball bounce off the top and bottom of the screen.
}

There's nothing HTML5-specific here, just ordinary arithmetic and algebra. I didn't comment the aiPaddle code because it's pretty much the same thing.

The Paddle

Start with the simplest things; variable declarations and the Draw function:

function Paddle(){
	this.x=0;
	this.y = canvasH/2;
	this.w = 32;
	this.h=64;
	
	this.aiv=9; //the maximum velocity with which the ai paddle can move
	this.aiOffset = 0; //how far off center the paddle will be when the ball reaches the end
	
	this.Draw = function(){
		context.fillStyle="white";
		context.fillRect(this.x - this.w/2, this.y - this.h/2, this.w, this.h);
	}

This includes all the relevant physical properties, and a pair of AI-related properties.

	this.FloorAndCeiling = function(){
		if(this.y < this.h/2) this.y = this.h/2;
		if(this.y > canvasH-this.h/2) this.y = canvasH-this.h/2;
	}

The above makes sure that the paddle is not outside the boundaries of the screen. It puts a floor and a ceiling on the y position. The syntax may seem unusual but it works just the same.

	this.PlayerUpdate = function(){
		this.y = cursorY;
		this.FloorAndCeiling();
	}

The above sets the paddle's y position equal to the cursor's y position.

	this.AIUpdate = function(){
		if(ball.vx < 0){//0.1
			if(ball.y + this.h*this.aiOffset > this.y -this.aiv){//1.0
				if(this.y+this.aiv<ball.y + this.h*this.aiOffset)//1.1
					this.y+=this.aiv;
				else
					this.y=ball.y + this.h*this.aiOffset;//1.2
			}
			if(ball.y + this.h*this.aiOffset < this.y + this.aiv){//2.0
				if(this.y-this.aiv>ball.y + this.h*this.aiOffset)
					this.y-=this.aiv;
				else
					this.y=ball.y + this.h*this.aiOffset;
			}
			
			this.FloorAndCeiling(); //3.0
		}
	}

The AI code is a little more difficult to understand conceptually, so the lines are labeled.

0.1 tells the AI to only do stuff if the ball is moving towards it. This isn't absolutely necessary and the game will work fine without this line.

1.0 checks where the ball is relative to the paddle. It's true specifically when the ball is above the paddle. + this.h*this.aiOffset simulates error by changing where the center of the paddle actually is. aiOffset is a number between -0.45 and 0.45 so the new "center" will always be on the paddle.

1.1 checks if the y distance between the paddle "center" and the ball is greater than the maximum velocity at which the AI can move the paddle. If it is, it moves the paddle by that amount. Otherwise,

1.2 the ball is "within range" so instead of overshooting, it just moves to the ball's y position.

2.0 is pretty much the same thing just in the other direction.

3.0 makes sure that the AI doesn't actually move the paddle off screen.

	this.AIChangeOffset = function(){
		this.aiOffset = (Math.random()-0.5)*0.9;
	}
}

Finally, just declare that last function which changes the offset. If you remember, it is called every time the ball bounces off the player's paddle. Remember to close all curly braces!

Variable Initialization


var ball = new Ball();
var aiPaddle = new Paddle(), playerPaddle = new Paddle();
playerPaddle.x = canvasW; //move the paddle to the other side of the screen

Here we create the ball and paddles.

The Game Loop


Finally, update the Run function;

function Run(){
    //NEW CODE PT 1
	aiPaddle.AIUpdate();  
	playerPaddle.PlayerUpdate();
	ball.Update(); //Update all the game objects
	//END NEW CODE PT 1
    
	context.fillStyle="black";
	
	context.clearRect(0,0, canvasW, canvasH);
	context.fillRect(0,0, canvasW, canvasH);//clear the context
	
    //NEW CODE PT 2
	ball.Draw();
	aiPaddle.Draw();
	playerPaddle.Draw();
	DrawScores();//Draw it all
    //END NEW CODE PT 2
}

Everything here is quite straightforward. Just call all the Update and Draw functions in the objects, and draw the score. The only important thing here is to Update before Drawing, and to clear the context before Drawing as well.

Conclusion


This is perhaps the simplest functioning game that one can make. It has a little bit of everything: graphics, input, physics, and AI. It doesn't use any advanced features, but it's a good starting point.





License


GDOL (Gamedev.net Open License)




Comments

Great article, thanks for promoting HTML5 games!

As an example of a more complex HTML5 game have a look at http://edigames.com/revelimmortal

its a work in progress large scale RPG we're developing.

 

-Raymond

I really needed this :)

I hope there's more to come

I studied html and javasrcipt. Thanks for the interesting article!

Nice article! Making games like pong, snake, pacman, space invaders ect is a great way to learn.

 

Checkout this open source word puzzle game i made with html5 Word Smashing Word Puzzle Game

 

The source code is on github, it uses JQuery, Twitter Bootstrap and Python for storing high scores/achievements.

 

--Lee Penkman

Addicting Word Games

Nice! How are you with Object Oriented JavaScript? It was my understanding you were meant to add object properties to Ball.prototype instead of doing that in the constructor using this.

Nice read, as I'm learning HTML5 myself. I've just finished the basic with Bucky Roberts from The New Boston, and once I'm done TheCherno's Java Game Programming, I'm gonna go more in-depth with HTML5. Mostly for general web design, but I do want to design some HTML5 games as well.

 

Also, to all you newbiew. Notepad++ might be a good programming tool, but personally I've just downloaded Sublime Text 2 and it's very similar to Notepad++ but seems MUCH better.

 

Thanks for the positive feedback everyone!
 
@Krohm while you are technically right, I think that using the prototype would add too much complexity to this game.  There is no need for more advanced OOP, so just using this does the trick.

 

However I am not an expert in Javascript by any means.  I will look further into it to see if maybe I did indeed miss something.

Thanks for this article.

I implemented and published it on my github with some modifications.

https://github.com/lvendrame/Html5CanvasPong


Note: Please offer only positive, constructive comments - we are looking to promote a positive atmosphere where collaboration is valued above all else.




PARTNERS