html game

Must Watch!



MustWatch

javascript Games


Learn how to make games, using nothing but HTML and JavaScript.

Push the buttons to move the red square:





Example

function startGame() { myGamePiece = new component(30, 30, "red", 10, 120); myGamePiece.gravity = 0.05; myScore = new component("30px", "Consolas", "black", 280, 40, "text"); myGameArea.start(); } var myGameArea = { canvas : document.createElement("canvas"), start : function() { this.canvas.width = 480; this.canvas.height = 270; this.context = this.canvas.getContext("2d"); document.body.insertBefore(this.canvas, document.body.childNodes[0]); this.frameNo = 0; }, clear : function() { this.context.clearRect(0, 0, this.canvas.width, this.canvas.height); } } <div id="canvascontainer"></div> The HTML <canvas> element is displayed as a rectangular object on a web page: <script> var myGameArea; function startGame() { myGameArea = new gamearea(); } var x = 0, y = 0; function gamearea() { this.canvas = document.createElement("canvas"); this.canvas.width = 320; this.canvas.height = 180; document.getElementById("canvascontainer").appendChild(this.canvas); this.context = this.canvas.getContext("2d"); this.context.scale(1.4, 1.4); //var v = document.getElementById("video1"); var i; //v.addEventListener("play", function() { i = window.setInterval(function() { myGameArea.context.clearRect(0, 0, myGameArea.canvas.width, myGameArea.canvas.height); x++; var ctx = document.getElementsByTagName("canvas")[0].getContext("2d"); //ctx.drawImage(v,5,5,260,125); ctx.strokeStyle="#000000"; ctx.font="20px Georgia"; if (x > 0) { ctx.strokeText("You can do anything",10,30); } if (x > 50) { y += 0.5; ctx.strokeText("on the canvas",10,50+y); } if (x > 250) { clearInterval(i); var ctx = document.getElementsByTagName("canvas")[0].getContext("2d"); ctx.font="20px Georgia"; ctx.strokeText("Try it!",140,100); } },20)//;}, false); //v.addEventListener("pause", function() {window.clearInterval(i);}, false); //v.addEventListener("ended", function() { //}, false); } startGame(); </script> <h2>HTML Canvas</h2> The <canvas> element is perfect for making games in HTML. The <canvas> element offers all the functionality you need for making games. Use JavaScript to draw, write, insert images, and more, onto the <canvas>.

.getContext("2d")

The <canvas> element has a built-in object, called the getContext("2d") object, with methods and properties for drawing.

Get Started

To make a game, start by creating a gaming area, and make it ready for drawing:

Example

function startGame() { myGameArea.start(); } var myGameArea = { canvas : document.createElement("canvas"), start : function() { this.canvas.width = 480; this.canvas.height = 270; this.context = this.canvas.getContext("2d"); document.body.insertBefore(this.canvas, document.body.childNodes[0]); } } Try it Yourself » The object myGameArea will have more properties and methods later in this tutorial. The function startGame() invokes the method start() of the myGameArea object. The start() method creates a <canvas> element and inserts it as the first childnode of the <body> element. <script> var myGameArea; var myGamePiece; function startGame() { myGameArea = new gamearea(); myGamePiece = new component(30, 30, "rgb(255, 0, 0)", 10, 75); } function gamearea() { this.canvas = document.createElement("canvas"); this.canvas.width = 320; this.canvas.height = 180; document.getElementById("canvascontainer").appendChild(this.canvas); this.context = this.canvas.getContext("2d"); } function component(width, height, color, x, y) { this.width = width; this.height = height; this.x = x; this.y = y; ctx = myGameArea.context; ctx.fillStyle = color; ctx.fillRect(this.x, this.y, this.width, this.height); } startGame(); </script>

Add a Component

Make a component constructor, which lets you add components onto the gamearea. The object constructor is called component, and we make our first component, called myGamePiece:

Example

var myGamePiece; function startGame() { myGameArea.start(); myGamePiece = new component(30, 30, "red", 10, 120);} function component(width, height, color, x, y) { this.width = width; this.height = height; this.x = x; this.y = y; ctx = myGameArea.context; ctx.fillStyle = color; ctx.fillRect(this.x, this.y, this.width, this.height); } Try it Yourself » The components have properties and methods to control their appearances and movements.

Frames

To make the game ready for action, we will update the display 50 times per second, which is much like frames in a movie. First, create a new function called updateGameArea(). In the myGameArea object, add an interval which will run the updateGameArea() function every 20th millisecond (50 times per second). Also add a function called clear(), that clears the entire canvas. In the component constructor, add a function called update(), to handle the drawing of the component. The updateGameArea() function calls the clear() and the update() method. The result is that the component is drawn and cleared 50 times per second:

Example

var myGameArea = { canvas : document.createElement("canvas"), start : function() { this.canvas.width = 480; this.canvas.height = 270; this.context = this.canvas.getContext("2d"); document.body.insertBefore(this.canvas, document.body.childNodes[0]); this.interval = setInterval(updateGameArea, 20); }, clear : function() { this.context.clearRect(0, 0, this.canvas.width, this.canvas.height); }} function component(width, height, color, x, y) { this.width = width; this.height = height; this.x = x; this.y = y; this.update = function(){ ctx = myGameArea.context; ctx.fillStyle = color; ctx.fillRect(this.x, this.y, this.width, this.height); }} function updateGameArea() { myGameArea.clear(); myGamePiece.update(); } Try it Yourself »

Make it Move

To prove that the red square is being drawn 50 times per second, we will change the x position (horizontal) by one pixel every time we update the game area:

Example

function updateGameArea() { myGameArea.clear(); myGamePiece.x += 1; myGamePiece.update(); } Try it Yourself »

Why Clear The Game Area?

It might seem unnecessary to clear the game area at every update. However, if we leave out the clear() method, all movements of the component will leave a trail of where it was positioned in the last frame:

Example

function updateGameArea() { // myGameArea.clear(); myGamePiece.x += 1; myGamePiece.update(); } Try it Yourself »

Change the Size

You can control the width and height of the component:

Example

Create a 10x140 pixels rectangle: function startGame() { myGameArea.start(); myGamePiece = new component(140, 10, "red", 10, 120); } Try it Yourself »

Change the Color

You can control the color of the component:

Example

function startGame() { myGameArea.start(); myGamePiece = new component(30, 30, "blue", 10, 120); } Try it Yourself » You can also use other colorvalues like hex, rgb, or rgba:

Example

function startGame() { myGameArea.start(); myGamePiece = new component(30, 30, "rgba(0, 0, 255, 0.5)", 10, 120); } Try it Yourself »

Change the Position

We use x- and y-coordinates to position components onto the game area. The upper-left corner of the canvas has the coordinates (0,0) Mouse over the game area below to see its x and y coordinates: You can position the components wherever you like on the game area:

Example

function startGame() { myGameArea.start(); myGamePiece = new component(30, 30, "red", 2, 2); } Try it Yourself »

Many Components

You can put as many components as you like on the game area:

Example

var redGamePiece, blueGamePiece, yellowGamePiece; function startGame() { redGamePiece = new component(75, 75, "red", 10, 10); yellowGamePiece = new component(75, 75, "yellow", 50, 60); blueGamePiece = new component(75, 75, "blue", 10, 110); myGameArea.start(); } function updateGameArea() { myGameArea.clear(); redGamePiece.update(); yellowGamePiece.update(); blueGamePiece.update(); } Try it Yourself »

Moving Components

Make all three components move in different directions:

Example

function updateGameArea() { myGameArea.clear(); redGamePiece.x += 1; yellowGamePiece.x += 1; yellowGamePiece.y += 1; blueGamePiece.x += 1; blueGamePiece.y -= 1; redGamePiece.update(); yellowGamePiece.update(); blueGamePiece.update(); } Try it Yourself » var myGameArea; var myGamePiece; function startGame() { myGameArea = new gamearea(); myGamePiece = new component(30, 30, "red", 10, 75); myGameArea.start(); } function gamearea() { this.canvas = document.createElement("canvas"); this.canvas.width = 320; this.canvas.height = 180; document.getElementById("canvascontainer").appendChild(this.canvas); this.context = this.canvas.getContext("2d"); this.start = function() { this.interval = setInterval(updateGameArea, 20); } this.clear = function(){ this.context.clearRect(0, 0, this.canvas.width, this.canvas.height); } } function component(width, height, color, x, y) { this.width = width; this.height = height; this.x = x; this.y = y; this.speedX = 0; this.speedY = 0; this.update = function() { ctx = myGameArea.context; ctx.fillStyle = color; ctx.fillRect(this.x, this.y, this.width, this.height); } } function updateGameArea() { myGameArea.clear(); myGamePiece.x += myGamePiece.speedX; myGamePiece.y += myGamePiece.speedY; myGamePiece.update(); } function moveup(e) { myGamePiece.speedY = -1; } function movedown() { myGamePiece.speedY = 1; } function moveleft() { myGamePiece.speedX = -1; } function moveright() { myGamePiece.speedX = 1; } function clearmove(e) { myGamePiece.speedX = 0; myGamePiece.speedY = 0; } startGame();

Get in Control

Now we want to control the red square. Add four buttons, up, down, left, and right. Write a function for each button to move the component in the selected direction. Make two new properties in the component constructor, and call them speedX and speedY. These properties are being used as speed indicators. Add a function in the component constructor, called newPos(), which uses the speedX and speedY properties to change the component's position. The newpos function is called from the updateGameArea function before drawing the component:

Example

<script> function component(width, height, color, x, y) { this.width = width; this.height = height; this.speedX = 0; this.speedY = 0; this.x = x; this.y = y; this.update = function() { ctx = myGameArea.context; ctx.fillStyle = color; ctx.fillRect(this.x, this.y, this.width, this.height); } this.newPos = function() { this.x += this.speedX; this.y += this.speedY; } } function updateGameArea() { myGameArea.clear(); myGamePiece.newPos(); myGamePiece.update(); } function moveup() { myGamePiece.speedY -= 1; } function movedown() { myGamePiece.speedY += 1; } function moveleft() { myGamePiece.speedX -= 1; } function moveright() { myGamePiece.speedX += 1; } </script> <button onclick="moveup()">UP</button> <button onclick="movedown()">DOWN</button> <button onclick="moveleft()">LEFT</button> <button onclick="moveright()">RIGHT</button> Try it Yourself »

Stop Moving

If you want, you can make the red square stop when you release a button. Add a function that will set the speed indicators to 0. To deal with both normal screens and touch screens, we will add code for both devices:

Example

function stopMove() { myGamePiece.speedX = 0; myGamePiece.speedY = 0; } </script> <button onmousedown="moveup()" onmouseup="stopMove()" ontouchstart="moveup()">UP</button> <button onmousedown="movedown()" onmouseup="stopMove()" ontouchstart="movedown()">DOWN</button> <button onmousedown="moveleft()" onmouseup="stopMove()" ontouchstart="moveleft()">LEFT</button> <button onmousedown="moveright()" onmouseup="stopMove()" ontouchstart="moveright()">RIGHT</button> Try it Yourself »

Keyboard as Controller

We can also control the red square by using the arrow keys on the keyboard. Create a method that checks if a key is pressed, and set the key property of the myGameArea object to the key code. When the key is released, set the key property to false:

Example

var myGameArea = { canvas : document.createElement("canvas"), start : function() { this.canvas.width = 480; this.canvas.height = 270; this.context = this.canvas.getContext("2d"); document.body.insertBefore(this.canvas, document.body.childNodes[0]); this.interval = setInterval(updateGameArea, 20); window.addEventListener('keydown', function (e) { myGameArea.key = e.keyCode; }) window.addEventListener('keyup', function (e) { myGameArea.key = false; }) }, clear : function(){ this.context.clearRect(0, 0, this.canvas.width, this.canvas.height); } } Then we can move the red square if one of the arrow keys are pressed:

Example

function updateGameArea() { myGameArea.clear(); myGamePiece.speedX = 0; myGamePiece.speedY = 0; if (myGameArea.key && myGameArea.key == 37) {myGamePiece.speedX = -1; } if (myGameArea.key && myGameArea.key == 39) {myGamePiece.speedX = 1; } if (myGameArea.key && myGameArea.key == 38) {myGamePiece.speedY = -1; } if (myGameArea.key && myGameArea.key == 40) {myGamePiece.speedY = 1; } myGamePiece.newPos(); myGamePiece.update(); } Try it Yourself »

Multiple Keys Pressed

What if more than one key is pressed at the same time? In the example above, the component can only move horizontally or vertically. Now we want the component to also move diagonally. Create a keys array for the myGameArea object, and insert one element for each key that is pressed, and give it the value true , the value remains true untill the key is no longer pressed, the value becomes false in the keyup event listener function:

Example

var myGameArea = { canvas : document.createElement("canvas"), start : function() { this.canvas.width = 480; this.canvas.height = 270; this.context = this.canvas.getContext("2d"); document.body.insertBefore(this.canvas, document.body.childNodes[0]); this.interval = setInterval(updateGameArea, 20); window.addEventListener('keydown', function (e) { myGameArea.keys = (myGameArea.keys || []); myGameArea.keys[e.keyCode] = true; }) window.addEventListener('keyup', function (e) { myGameArea.keys[e.keyCode] = false; }) }, clear : function(){ this.context.clearRect(0, 0, this.canvas.width, this.canvas.height); } } function updateGameArea() { myGameArea.clear(); myGamePiece.speedX = 0; myGamePiece.speedY = 0; if (myGameArea.keys && myGameArea.keys[37]) {myGamePiece.speedX = -1; } if (myGameArea.keys && myGameArea.keys[39]) {myGamePiece.speedX = 1; } if (myGameArea.keys && myGameArea.keys[38]) {myGamePiece.speedY = -1; } if (myGameArea.keys && myGameArea.keys[40]) {myGamePiece.speedY = 1; } myGamePiece.newPos(); myGamePiece.update(); } Try it Yourself »

Using The Mouse Cursor as a Controller

If you want to control the red square by using the mouse cursor, add a method in myGameArea object that updates the x and y coordinates of the mouse cursor:.

Example

var myGameArea = { canvas : document.createElement("canvas"), start : function() { this.canvas.width = 480; this.canvas.height = 270; this.canvas.style.cursor = "none"; //hide the original cursor this.context = this.canvas.getContext("2d"); document.body.insertBefore(this.canvas, document.body.childNodes[0]); this.interval = setInterval(updateGameArea, 20); window.addEventListener('mousemove', function (e) { myGameArea.x = e.pageX; myGameArea.y = e.pageY; }) }, clear : function(){ this.context.clearRect(0, 0, this.canvas.width, this.canvas.height); } } Then we can move the red square using the mouse cursor:

Example

function updateGameArea() { myGameArea.clear(); if (myGameArea.x && myGameArea.y) { myGamePiece.x = myGameArea.x; myGamePiece.y = myGameArea.y; } myGamePiece.update(); } Try it Yourself »

Touch The Screen to Control The Game

We can also control the red square on a touch screen. Add a method in the myGameArea object that uses the x and y coordinates of where the screen is touched:

Example

var myGameArea = { canvas : document.createElement("canvas"), start : function() { this.canvas.width = 480; this.canvas.height = 270; this.context = this.canvas.getContext("2d"); document.body.insertBefore(this.canvas, document.body.childNodes[0]); this.interval = setInterval(updateGameArea, 20); window.addEventListener('touchmove', function (e) { myGameArea.x = e.touches[0].screenX; myGameArea.y = e.touches[0].screenY; }) }, clear : function(){ this.context.clearRect(0, 0, this.canvas.width, this.canvas.height); } } Then we can move the red square if the user touches the screen, by using the same code as we did for the mouse cursor:

Example

function updateGameArea() { myGameArea.clear(); if (myGameArea.x && myGameArea.y) { myGamePiece.x = myGameArea.x; myGamePiece.y = myGameArea.y; } myGamePiece.update(); } Try it Yourself »

Controllers on The Canvas

We can also draw our own buttons on the canvas, and use them as controllers:

Example

function startGame() { myGamePiece = new component(30, 30, "red", 10, 120); myUpBtn = new component(30, 30, "blue", 50, 10); myDownBtn = new component(30, 30, "blue", 50, 70); myLeftBtn = new component(30, 30, "blue", 20, 40); myRightBtn = new component(30, 30, "blue", 80, 40); myGameArea.start(); } Add a new function that figures out if a component, in this case a button, is clicked. Start by adding event listeners to check if a mouse button is clicked (mousedown and mouseup). To deal with touch screens, also add event listeners to check if the screen is clicked on (touchstart and touchend):

Example

var myGameArea = { canvas : document.createElement("canvas"), start : function() { this.canvas.width = 480; this.canvas.height = 270; this.context = this.canvas.getContext("2d"); document.body.insertBefore(this.canvas, document.body.childNodes[0]); this.interval = setInterval(updateGameArea, 20); window.addEventListener('mousedown', function (e) { myGameArea.x = e.pageX; myGameArea.y = e.pageY; }) window.addEventListener('mouseup', function (e) { myGameArea.x = false; myGameArea.y = false; }) window.addEventListener('touchstart', function (e) { myGameArea.x = e.pageX; myGameArea.y = e.pageY; }) window.addEventListener('touchend', function (e) { myGameArea.x = false; myGameArea.y = false; }) }, clear : function(){ this.context.clearRect(0, 0, this.canvas.width, this.canvas.height); } } Now the myGameArea object has properties that tells us the x- and y-coordinates of a click. We use these properties to check if the click was performed on one of our blue buttons. The new method is called clicked, it is a method of the component constructor, and it checks if the component is being clicked. In the updateGameArea function, we take the neccessarry actions if one of the blue buttons is clicked:

Example

function component(width, height, color, x, y) { this.width = width; this.height = height; this.speedX = 0; this.speedY = 0; this.x = x; this.y = y; this.update = function() { ctx = myGameArea.context; ctx.fillStyle = color; ctx.fillRect(this.x, this.y, this.width, this.height); } this.clicked = function() { var myleft = this.x; var myright = this.x + (this.width); var mytop = this.y; var mybottom = this.y + (this.height); var clicked = true; if ((mybottom < myGameArea.y) || (mytop > myGameArea.y) || (myright < myGameArea.x) || (myleft > myGameArea.x)) { clicked = false; } return clicked; } } function updateGameArea() { myGameArea.clear(); if (myGameArea.x && myGameArea.y) { if (myUpBtn.clicked()) { myGamePiece.y -= 1; } if (myDownBtn.clicked()) { myGamePiece.y += 1; } if (myLeftBtn.clicked()) { myGamePiece.x += -1; } if (myRightBtn.clicked()) { myGamePiece.x += 1; } } myUpBtn.update(); myDownBtn.update(); myLeftBtn.update(); myRightBtn.update(); myGamePiece.update(); } Try it Yourself » <script> var myGameArea; var myGamePiece; var myObstacles = []; function startGame() { myGameArea = new gamearea(); myGamePiece = new component(30, 30, "red", 10, 75); myGameArea.start(); } function gamearea() { this.canvas = document.createElement("canvas"); this.canvas.width = 320; this.canvas.height = 180; document.getElementById("canvascontainer").appendChild(this.canvas); this.context = this.canvas.getContext("2d"); this.pause = false; this.frameNo = 0; this.start = function() { this.interval = setInterval(updateGameArea, 20); } this.stop = function() { clearInterval(this.interval); this.pause = true; } this.clear = function(){ this.context.clearRect(0, 0, this.canvas.width, this.canvas.height); } } function component(width, height, color, x, y) { this.width = width; this.height = height; this.speedX = 0; this.speedY = 0; this.x = x; this.y = y; this.update = function() { ctx = myGameArea.context; ctx.fillStyle = color; ctx.fillRect(this.x, this.y, this.width, this.height); } this.crashWith = function(otherobj) { var myleft = this.x; var myright = this.x + (this.width); var mytop = this.y; var mybottom = this.y + (this.height); var otherleft = otherobj.x; var otherright = otherobj.x + (otherobj.width); var othertop = otherobj.y; var otherbottom = otherobj.y + (otherobj.height); var crash = true; if ((mybottom < othertop) || (mytop > otherbottom) || (myright < otherleft) || (myleft > otherright)) { crash = false; } return crash; } } function updateGameArea() { var x, y, min, max, height, gap; for (i = 0; i < myObstacles.length; i += 1) { if (myGamePiece.crashWith(myObstacles[i])) { myGameArea.stop(); } } if (myGameArea.pause == false) { myGameArea.clear(); myGameArea.frameNo += 1; if (myGameArea.frameNo == 1 || everyinterval(100)) { x = myGameArea.canvas.width; y = myGameArea.canvas.height - 100; min = 20; max = 100; height = Math.floor(Math.random()*(max-min+1)+min); min = 50; max = 100; gap = Math.floor(Math.random()*(max-min+1)+min); myObstacles.push(new component(10, height, "green", x, 0)); myObstacles.push(new component(10, x - height - gap, "green", x, height + gap)); } for (i = 0; i < myObstacles.length; i += 1) { myObstacles[i].x += -1; myObstacles[i].update(); } myGamePiece.x += myGamePiece.speedX; myGamePiece.y += myGamePiece.speedY; myGamePiece.update(); } } function everyinterval(n) { if ((myGameArea.frameNo / n) % 1 == 0) {return true;} return false; } function moveup(e) { myGamePiece.speedY = -1; } function movedown() { myGamePiece.speedY = 1; } function moveleft() { myGamePiece.speedX = -1; } function moveright() { myGamePiece.speedX = 1; } function clearmove(e) { myGamePiece.speedX = 0; myGamePiece.speedY = 0; } startGame(); </script>

Add Some Obstacles

Now we want to add some obstacles to our game. Add a new component to the gaming area. Make it green, 10px wide, 200px high, and place it 300px to the right and 120px down. Also update the obstacle component in every frame:

Example

var myGamePiece; var myObstacle; function startGame() { myGamePiece = new component(30, 30, "red", 10, 120); myObstacle = new component(10, 200, "green", 300, 120); myGameArea.start(); } function updateGameArea() { myGameArea.clear(); myObstacle.update(); myGamePiece.newPos(); myGamePiece.update(); } Try it Yourself »

Hit The Obstacle = Game Over

In the example above, nothing happens when you hit the obstacle. In a game, that is not very satisfying. How do we know if our red square hits the obstacle? Create a new method in the component constructor, that checks if the component crashes with another component. This method should be called every time the frames updates, 50 times per second. Also add a stop() method to the myGameArea object, which clears the 20 milliseconds interval.

Example

var myGameArea = { canvas : document.createElement("canvas"), start : function() { this.canvas.width = 480; this.canvas.height = 270; this.context = this.canvas.getContext("2d"); document.body.insertBefore(this.canvas, document.body.childNodes[0]); this.interval = setInterval(updateGameArea, 20); }, clear : function() { this.context.clearRect(0, 0, this.canvas.width, this.canvas.height); }, stop : function() { clearInterval(this.interval); } } function component(width, height, color, x, y) { this.width = width; this.height = height; this.speedX = 0; this.speedY = 0; this.x = x; this.y = y; this.update = function() { ctx = myGameArea.context; ctx.fillStyle = color; ctx.fillRect(this.x, this.y, this.width, this.height); } this.newPos = function() { this.x += this.speedX; this.y += this.speedY; } this.crashWith = function(otherobj) { var myleft = this.x; var myright = this.x + (this.width); var mytop = this.y; var mybottom = this.y + (this.height); var otherleft = otherobj.x; var otherright = otherobj.x + (otherobj.width); var othertop = otherobj.y; var otherbottom = otherobj.y + (otherobj.height); var crash = true; if ((mybottom < othertop) || (mytop > otherbottom) || (myright < otherleft) || (myleft > otherright)) { crash = false; } return crash; } } function updateGameArea() { if (myGamePiece.crashWith(myObstacle)) { myGameArea.stop(); } else { myGameArea.clear(); myObstacle.update(); myGamePiece.newPos(); myGamePiece.update(); } } Try it Yourself »

Moving Obstacle

The obstacle is of no danger when it is static, so we want it to move. Change the property value of myObstacle.x at every update:

Example

function updateGameArea() { if (myGamePiece.crashWith(myObstacle)) { myGameArea.stop(); } else { myGameArea.clear(); myObstacle.x += -1; myObstacle.update(); myGamePiece.newPos(); myGamePiece.update(); } } Try it Yourself »

Multiple Obstacles

How about adding multiple obstacles? For that we need a property for counting frames, and a method for execute something at a given frame rate.

Example

var myGameArea = { canvas : document.createElement("canvas"), start : function() { this.canvas.width = 480; this.canvas.height = 270; this.context = this.canvas.getContext("2d"); document.body.insertBefore(this.canvas, document.body.childNodes[0]); this.frameNo = 0; this.interval = setInterval(updateGameArea, 20); }, clear : function() { this.context.clearRect(0, 0, this.canvas.width, this.canvas.height); }, stop : function() { clearInterval(this.interval); } } function everyinterval(n) { if ((myGameArea.frameNo / n) % 1 == 0) {return true;} return false; } The everyinterval function returns true if the current framenumber corresponds with the given interval. To define multiple obstacles, first declare the obstacle variable as an array. Second, we need to make some changes in the updateGameArea function.

Example

var myGamePiece; var myObstacles = []; function updateGameArea() { var x, y; for (i = 0; i < myObstacles.length; i += 1) { if (myGamePiece.crashWith(myObstacles[i])) { myGameArea.stop(); return; } } myGameArea.clear(); myGameArea.frameNo += 1; if (myGameArea.frameNo == 1 || everyinterval(150)) { x = myGameArea.canvas.width; y = myGameArea.canvas.height - 200 myObstacles.push(new component(10, 200, "green", x, y)); } for (i = 0; i < myObstacles.length; i += 1) { myObstacles[i].x += -1; myObstacles[i].update(); } myGamePiece.newPos(); myGamePiece.update(); } Try it Yourself » In the updateGameArea function we must loop through every obstacle to see if there is a crash. If there is a crash, the updateGameArea function will stop, and no more drawing is done. The updateGameArea function counts frames and adds an obstacle for every 150th frame.

Obstacles of Random Size

To make the game a bit more difficult, and fun, we will send in obstacles of random sizes, so that the red square must move up and down to not crash.

Example

function updateGameArea() { var x, height, gap, minHeight, maxHeight, minGap, maxGap; for (i = 0; i < myObstacles.length; i += 1) { if (myGamePiece.crashWith(myObstacles[i])) { myGameArea.stop(); return; } } myGameArea.clear(); myGameArea.frameNo += 1; if (myGameArea.frameNo == 1 || everyinterval(150)) { x = myGameArea.canvas.width; minHeight = 20; maxHeight = 200; height = Math.floor(Math.random()*(maxHeight-minHeight+1)+minHeight); minGap = 50; maxGap = 200; gap = Math.floor(Math.random()*(maxGap-minGap+1)+minGap); myObstacles.push(new component(10, height, "green", x, 0)); myObstacles.push(new component(10, x - height - gap, "green", x, height + gap)); } for (i = 0; i < myObstacles.length; i += 1) { myObstacles[i].x += -1; myObstacles[i].update(); } myGamePiece.newPos(); myGamePiece.update(); } Try it Yourself » <script> var myGameArea; var myGamePiece; var myObstacles = []; var myscore; function restartGame() { document.getElementById("myfilter").style.display = "none"; document.getElementById("myrestartbutton").style.display = "none"; myGameArea.stop(); myGameArea.clear(); myGameArea = {}; myGamePiece = {}; myObstacles = []; myscore = {}; document.getElementById("canvascontainer").innerHTML = ""; startGame() } function startGame() { myGameArea = new gamearea(); myGamePiece = new component(30, 30, "red", 10, 75); myscore = new component("15px", "Consolas", "black", 220, 25, "text"); myGameArea.start(); } function gamearea() { this.canvas = document.createElement("canvas"); this.canvas.width = 320; this.canvas.height = 180; document.getElementById("canvascontainer").appendChild(this.canvas); this.context = this.canvas.getContext("2d"); this.pause = false; this.frameNo = 0; this.start = function() { this.interval = setInterval(updateGameArea, 20); } this.stop = function() { clearInterval(this.interval); this.pause = true; } this.clear = function(){ this.context.clearRect(0, 0, this.canvas.width, this.canvas.height); } } function component(width, height, color, x, y, type) { this.type = type; if (type == "text") { this.text = color; } this.score = 0; this.width = width; this.height = height; this.speedX = 0; this.speedY = 0; this.x = x; this.y = y; this.update = function() { ctx = myGameArea.context; if (this.type == "text") { ctx.font = this.width + " " + this.height; ctx.fillStyle = color; ctx.fillText(this.text, this.x, this.y); } else { ctx.fillStyle = color; ctx.fillRect(this.x, this.y, this.width, this.height); } } this.crashWith = function(otherobj) { var myleft = this.x; var myright = this.x + (this.width); var mytop = this.y; var mybottom = this.y + (this.height); var otherleft = otherobj.x; var otherright = otherobj.x + (otherobj.width); var othertop = otherobj.y; var otherbottom = otherobj.y + (otherobj.height); var crash = true; if ((mybottom < othertop) || (mytop > otherbottom) || (myright < otherleft) || (myleft > otherright)) { crash = false; } return crash; } } function updateGameArea() { var x, y, min, max, height, gap; for (i = 0; i < myObstacles.length; i += 1) { if (myGamePiece.crashWith(myObstacles[i])) { myGameArea.stop(); document.getElementById("myfilter").style.display = "block"; document.getElementById("myrestartbutton").style.display = "block"; return; } } if (myGameArea.pause == false) { myGameArea.clear(); myGameArea.frameNo += 1; myscore.score +=1; if (myGameArea.frameNo == 1 || everyinterval(150)) { x = myGameArea.canvas.width; y = myGameArea.canvas.height - 100; min = 20; max = 100; height = Math.floor(Math.random()*(max-min+1)+min); min = 50; max = 100; gap = Math.floor(Math.random()*(max-min+1)+min); myObstacles.push(new component(10, height, "green", x, 0)); myObstacles.push(new component(10, x - height - gap, "green", x, height + gap)); } for (i = 0; i < myObstacles.length; i += 1) { myObstacles[i].x += -1; myObstacles[i].update(); } myscore.text="SCORE: " + myscore.score; myscore.update(); myGamePiece.x += myGamePiece.speedX; myGamePiece.y += myGamePiece.speedY; myGamePiece.update(); } } function everyinterval(n) { if ((myGameArea.frameNo / n) % 1 == 0) {return true;} return false; } function moveup(e) { myGamePiece.speedY = -1; } function movedown() { myGamePiece.speedY = 1; } function moveleft() { myGamePiece.speedX = -1; } function moveright() { myGamePiece.speedX = 1; } function clearmove(e) { myGamePiece.speedX = 0; myGamePiece.speedY = 0; } startGame(); </script>

Count The Score

There are many ways to keep the score in a game, we will show you how to write a score onto the canvas. First make a score component:

Example

var myGamePiece; var myObstacles = []; var myScore; function startGame() { myGamePiece = new component(30, 30, "red", 10, 160); myScore = new component("30px", "Consolas", "black", 280, 40, "text"); myGameArea.start(); } The syntax for writing text on a canvas element is different from drawing a rectangle. Therefore we must call the component constructor using an additional argument, telling the constructor that this component is of type "text". In the component constructor we test if the component is of type "text", and use the fillText method instead of the fillRect method:

Example

function component(width, height, color, x, y, type) { this.type = type; this.width = width; this.height = height; this.speedX = 0; this.speedY = 0; this.x = x; this.y = y; this.update = function() { ctx = myGameArea.context; if (this.type == "text") { ctx.font = this.width + " " + this.height; ctx.fillStyle = color; ctx.fillText(this.text, this.x, this.y); } else { ctx.fillStyle = color; ctx.fillRect(this.x, this.y, this.width, this.height); } } ... } At last we add some code in the updateGameArea function that writes the score onto the canvas. We use the frameNo property to count the score:

Example

function updateGameArea() { var x, height, gap, minHeight, maxHeight, minGap, maxGap; for (i = 0; i < myObstacles.length; i += 1) { if (myGamePiece.crashWith(myObstacles[i])) { myGameArea.stop(); return; } } myGameArea.clear(); myGameArea.frameNo += 1; if (myGameArea.frameNo == 1 || everyinterval(150)) { x = myGameArea.canvas.width; minHeight = 20; maxHeight = 200; height = Math.floor(Math.random()*(maxHeight-minHeight+1)+minHeight); minGap = 50; maxGap = 200; gap = Math.floor(Math.random()*(maxGap-minGap+1)+minGap); myObstacles.push(new component(10, height, "green", x, 0)); myObstacles.push(new component(10, x - height - gap, "green", x, height + gap)); } for (i = 0; i < myObstacles.length; i += 1) { myObstacles[i].speedX = -1; myObstacles[i].newPos(); myObstacles[i].update(); } myScore.text = "SCORE: " + myGameArea.frameNo; myScore.update(); myGamePiece.newPos(); myGamePiece.update(); } Try it Yourself » <script> var myGameArea; var myGamePiece; function startGame() { myGameArea = new gamearea(); myGamePiece = new component(30, 30, "smiley.gif", 10, 75, "image"); myGameArea.start(); } function gamearea() { this.canvas = document.createElement("canvas"); this.canvas.width = 320; this.canvas.height = 180; document.getElementById("canvascontainer").appendChild(this.canvas); this.context = this.canvas.getContext("2d"); this.start = function() { this.interval = setInterval(updateGameArea, 20); } this.clear = function(){ this.context.clearRect(0, 0, this.canvas.width, this.canvas.height); } } function component(width, height, color, x, y, type) { this.type = type; if (type == "image") { this.image = new Image(); this.image.src = color; } this.width = width; this.height = height; this.speedX = 0; this.speedY = 0; this.x = x; this.y = y; this.update = function() { ctx = myGameArea.context; if (type == "image") { ctx.drawImage(this.image, this.x, this.y, this.width, this.height); } else { ctx.fillStyle = color; ctx.fillRect(this.x, this.y, this.width, this.height); } } } function updateGameArea() { myGameArea.clear(); myGamePiece.x += myGamePiece.speedX; myGamePiece.y += myGamePiece.speedY; myGamePiece.update(); } function move(dir) { myGamePiece.image.src = "angry.gif"; if (dir == "up") {myGamePiece.speedY = -1; } if (dir == "down") {myGamePiece.speedY = 1; } if (dir == "left") {myGamePiece.speedX = -1; } if (dir == "right") {myGamePiece.speedX = 1; } } function clearmove() { myGamePiece.image.src = "smiley.gif"; myGamePiece.speedX = 0; myGamePiece.speedY = 0; } startGame(); </script>

How to Use Images?

To add images on a canvas, the getContext("2d") object has built-in image properties and methods. In our game, to create the gamepiece as an image, use the component constructor, but instead of referring to a color, you must refer to the url of the image. And you must tell the constructor that this component is of type "image":

Example

function startGame() { myGamePiece = new component(30, 30, "smiley.gif", 10, 120, "image"); myGameArea.start(); } In the component constructor we test if the component is of type "image", and create an image object by using the built-in "new Image()" object constructor. When we are ready to draw the image, we use the drawImage method instead of the fillRect method:

Example

function component(width, height, color, x, y, type) { this.type = type; if (type == "image") { this.image = new Image(); this.image.src = color; } this.width = width; this.height = height; this.speedX = 0; this.speedY = 0; this.x = x; this.y = y; this.update = function() { ctx = myGameArea.context; if (type == "image") { ctx.drawImage(this.image, this.x, this.y, this.width, this.height); } else { ctx.fillStyle = color; ctx.fillRect(this.x, this.y, this.width, this.height); } } } Try it Yourself »

Change Images

You can change the image whenever you like by changing the src property of the image object of your component. If you want to change the smiley everytime it moves, change the image source when the user clicks a button, and back to normal when the button is not clicked:

Example

function move(dir) { myGamePiece.image.src = "angry.gif"; if (dir == "up") {myGamePiece.speedY = -1; } if (dir == "down") {myGamePiece.speedY = 1; } if (dir == "left") {myGamePiece.speedX = -1; } if (dir == "right") {myGamePiece.speedX = 1; } } function clearmove() { myGamePiece.image.src = "smiley.gif"; myGamePiece.speedX = 0; myGamePiece.speedY = 0; } Try it Yourself »

Background Images

Add a background image to your game area by adding it as a component, and also update the background in every frame:

Example

var myGamePiece; var myBackground; function startGame() { myGamePiece = new component(30, 30, "smiley.gif", 10, 120, "image"); myBackground = new component(656, 270, "citymarket.jpg", 0, 0, "image"); myGameArea.start(); } function updateGameArea() { myGameArea.clear(); myBackground.newPos(); myBackground.update(); myGamePiece.newPos(); myGamePiece.update(); } Try it Yourself »

Moving Background

Change the background component's speedX property to make the background move:

Example

function updateGameArea() { myGameArea.clear(); myBackground.speedX = -1; myBackground.newPos(); myBackground.update(); myGamePiece.newPos(); myGamePiece.update(); } Try it Yourself »

Background Loop

To make the same background loop forever, we must use a specific technique. Start by telling the component constructor that this is a background. The component constructor will then add the image twice, placing the second image immediately after the first image. In the newPos() method, check if the x position of the component has reach the end of the image, if it has, set the x position of the component to 0:

Example

function component(width, height, color, x, y, type) { this.type = type; if (type == "image" || type == "background") { this.image = new Image(); this.image.src = color; } this.width = width; this.height = height; this.speedX = 0; this.speedY = 0; this.x = x; this.y = y; this.update = function() { ctx = myGameArea.context; if (type == "image" || type == "background") { ctx.drawImage(this.image, this.x, this.y, this.width, this.height); if (type == "background") { ctx.drawImage(this.image, this.x + this.width, this.y, this.width, this.height); } } else { ctx.fillStyle = color; ctx.fillRect(this.x, this.y, this.width, this.height); } } this.newPos = function() { this.x += this.speedX; this.y += this.speedY; if (this.type == "background") { if (this.x == -(this.width)) { this.x = 0; } } } } Try it Yourself » <script> var myGameArea; var myGamePiece; var myObstacles = []; var mysound; function startGame() { myGameArea = new gamearea(); myGamePiece = new component(30, 30, "red", 10, 75); mysound = new sound("bounce.mp3"); myGameArea.start(); } function gamearea() { this.canvas = document.createElement("canvas"); this.canvas.width = 320; this.canvas.height = 180; document.getElementById("canvascontainer").appendChild(this.canvas); this.context = this.canvas.getContext("2d"); this.pause = false; this.frameNo = 0; this.start = function() { this.interval = setInterval(updateGameArea, 20); } this.stop = function() { this.pause = true; clearInterval(this.interval); } this.clear = function(){ this.context.clearRect(0, 0, this.canvas.width, this.canvas.height); } } function component(width, height, color, x, y) { this.width = width; this.height = height; this.speedX = 0; this.speedY = 0; this.x = x; this.y = y; this.update = function() { ctx = myGameArea.context; ctx.fillStyle = color; ctx.fillRect(this.x, this.y, this.width, this.height); } this.crashWith = function(otherobj) { var myleft = this.x; var myright = this.x + (this.width); var mytop = this.y; var mybottom = this.y + (this.height); var otherleft = otherobj.x; var otherright = otherobj.x + (otherobj.width); var othertop = otherobj.y; var otherbottom = otherobj.y + (otherobj.height); var crash = true; if ((mybottom < othertop) || (mytop > otherbottom) || (myright < otherleft) || (myleft > otherright)) { crash = false; } return crash; } } function updateGameArea() { var x, y, min, max, height, gap; for (i = 0; i < myObstacles.length; i += 1) { if (myGamePiece.crashWith(myObstacles[i])) { mysound.play(); myGameArea.stop(); } } if (myGameArea.pause == false) { myGameArea.clear(); myGameArea.frameNo += 1; if (myGameArea.frameNo == 1 || everyinterval(150)) { x = myGameArea.canvas.width; y = myGameArea.canvas.height - 100; min = 20; max = 100; height = Math.floor(Math.random()*(max-min+1)+min); min = 50; max = 100; gap = Math.floor(Math.random()*(max-min+1)+min); myObstacles.push(new component(10, height, "green", x, 0)); myObstacles.push(new component(10, x - height - gap, "green", x, height + gap)); } for (i = 0; i < myObstacles.length; i += 1) { myObstacles[i].x += -1; myObstacles[i].update(); } myGamePiece.x += myGamePiece.speedX; myGamePiece.y += myGamePiece.speedY; myGamePiece.update(); } } function sound(src) { this.sound = document.createElement("audio"); this.sound.src = src; this.sound.setAttribute("preload", "auto"); this.sound.setAttribute("controls", "none"); this.sound.style.display = "none"; document.body.appendChild(this.sound); this.play = function(){ this.sound.play(); } } function everyinterval(n) { if ((myGameArea.frameNo / n) % 1 == 0) {return true;} return false; } function moveup(e) { myGamePiece.speedY = -1; } function movedown() { myGamePiece.speedY = 1; } function moveleft() { myGamePiece.speedX = -1; } function moveright() { myGamePiece.speedX = 1; } function clearmove(e) { myGamePiece.speedX = 0; myGamePiece.speedY = 0; } startGame(); </script>

How to Add Sounds?

Use the HTML5 <audio> element to add sound and music to your games. In our examples, we create a new object constructor to handle sound objects:

Example

function sound(src) { this.sound = document.createElement("audio"); this.sound.src = src; this.sound.setAttribute("preload", "auto"); this.sound.setAttribute("controls", "none"); this.sound.style.display = "none"; document.body.appendChild(this.sound); this.play = function(){ this.sound.play(); } this.stop = function(){ this.sound.pause(); } } To create a new sound object use the sound constructor, and when the red square hits an obstacle, play the sound:

Example

var myGamePiece; var myObstacles = []; var mySound; function startGame() { myGamePiece = new component(30, 30, "red", 10, 120); mySound = new sound("bounce.mp3"); myGameArea.start(); } function updateGameArea() { var x, height, gap, minHeight, maxHeight, minGap, maxGap; for (i = 0; i < myObstacles.length; i += 1) { if (myGamePiece.crashWith(myObstacles[i])) { mySound.play(); myGameArea.stop(); return; } } ... } Try it Yourself »

Background Music

To add background music to your game, add a new sound object, and start playing when you start the game:

Example

var myGamePiece; var myObstacles = []; var mySound; var myMusic; function startGame() { myGamePiece = new component(30, 30, "red", 10, 120); mySound = new sound("bounce.mp3"); myMusic = new sound("gametheme.mp3"); myMusic.play(); myGameArea.start(); } Try it Yourself » <script> var myGameArea; var myGamePiece; var myoverlay; var myresult; var accel = false; function startGame() { myGameArea = new gamearea("canvascontainer"); //myresult = new component(myGameArea, "30px", "Consolas", "white", 30, 50, "text"); //myresult.text = "Land me Safely" myGamePiece = new component(30, 30, "red", 50, 50); //myoverlay = new component(myGameArea, 640, 360, "rgba(0,255,0,0.1)", 0, 0); myGameArea.start(); } function gamearea() { this.canvas = document.createElement("canvas"); this.canvas.width = 320; this.canvas.height = 180; document.getElementById("canvascontainer").appendChild(this.canvas); this.context = this.canvas.getContext("2d"); this.start = function() { this.interval = setInterval(updateGameArea, 20); } this.stop = function() { clearInterval(this.interval); this.pause = true; } this.clear = function(){ this.context.clearRect(0, 0, this.canvas.width, this.canvas.height); } } function component(width, height, color, x, y, type) { this.type = type; if (type == "image") { this.image = new Image(); this.image.src = color; } this.width = width; this.height = height; this.angle = 0; this.moveangle = 0; this.color = color; this.rotation = 0; this.speed = 0; this.fallspeed = 0; this.x = x; this.y = y; this.speedX = 0; this.speedY = 0; this.update = function() { ctx = myGameArea.context; ctx.save(); ctx.translate(this.x, this.y); ctx.rotate(this.angle); if (this.type == "text") { ctx.font = this.width + " " + this.height; ctx.fillStyle = color; ctx.fillText(this.text, this.x, this.y); } else { ctx.fillStyle = this.color; ctx.fillRect(-(this.width / 2), -(this.height / 2), this.width, this.height); } ctx.restore(); } this.newGravityPos = function(degrees, thrust) { degrees -= 90; angle = degrees * Math.PI / 180; this.speedX += thrust * Math.cos(angle); this.speedY += thrust * Math.sin(angle); this.calcSpeedAngle(); } this.calcSpeedAngle = function(){ this.speed = Math.sqrt((this.speedX * this.speedX) + (this.speedY * this.speedY)); } } function updateGameArea() { myGameArea.clear(); myGamePiece.x += myGamePiece.speedX; myGamePiece.y += myGamePiece.speedY; if (accel == true || (document.key && document.key == 38)) { myGamePiece.newGravityPos(0, 0.2); } myGamePiece.newGravityPos(180, 0.05); if (myGamePiece.speed > 2 || myGamePiece.y < -15) { // myoverlay.color = "rgba(255,0,0,0.1)" } else { // myoverlay.color = "rgba(0,255,0,0.1)" } myGamePiece.update(); //myoverlay.update(); if (myGamePiece.y > 165) { myGameArea.stop(); if (myGamePiece.speed > 2) { //myresult.width = "26px"; //myresult.x = 10; //myresult.text = "Landing was to hard!"; //myoverlay.color = "rgba(255,0,0,0.1)" } else { //myoverlay.color = "rgba(0,255,0,0.1)" //myresult.text = "Nice landing!"; } } if (myGamePiece.y < -15) { myGameArea.stop(); //myresult.width = "18px"; //myresult.x = 4; //myresult.text = "You lost the red square!"; } //myresult.update(); } function accelerate(x) { accel = x; } function restartgame(x) { myGameArea.stop(); document.getElementById("canvascontainer").innerHTML = ""; startGame(); } startGame(); </script>

Gravity

To add this functionality to our component constructor, first add a gravity property, which sets the current gravity. Then add a gravitySpeed property, which increases everytime we update the frame:

Example

function component(width, height, color, x, y, type) { this.type = type; this.width = width; this.height = height; this.x = x; this.y = y; this.speedX = 0; this.speedY = 0; this.gravity = 0.05; this.gravitySpeed = 0; this.update = function() { ctx = myGameArea.context; ctx.fillStyle = color; ctx.fillRect(this.x, this.y, this.width, this.height); } this.newPos = function() { this.gravitySpeed += this.gravity; this.x += this.speedX; this.y += this.speedY + this.gravitySpeed; } } Try it Yourself »

Hit the Bottom

To prevent the red square from falling forever, stop the falling when it hits the bottom of the game area:

Example

this.newPos = function() { this.gravitySpeed += this.gravity; this.x += this.speedX; this.y += this.speedY + this.gravitySpeed; this.hitBottom(); } this.hitBottom = function() { var rockbottom = myGameArea.canvas.height - this.height; if (this.y > rockbottom) { this.y = rockbottom; } } Try it Yourself »

Accelerate Up

In a game, when you have a force that pulls you down, you should have a method to force the component to accelerate up. Trigger a function when someone clicks a button, and make the red square fly up in the air:

Example

<script> function accelerate(n) { myGamePiece.gravity = n; } </script> <button onmousedown="accelerate(-0.2)" onmouseup="accelerate(0.1)">ACCELERATE</button> Try it Yourself »

A Game

Make a game based on what we have learned so far:

Example

Try it Yourself » <script> var myGamePiece; var myoverlay; var myresult; var accel = false; function startGame() { myGamePiece = new component(30, 30, "red", 50, 50); myGameArea.start(); } var myGameArea = { canvas : document.createElement("canvas"), start : function() { this.canvas.width = 320; this.canvas.height = 180; this.context = this.canvas.getContext("2d"); document.getElementById("canvascontainer").appendChild(this.canvas); this.interval = setInterval(updateGameArea, 20); }, stop : function() { clearInterval(this.interval); }, clear : function() { this.context.clearRect(0, 0, this.canvas.width, this.canvas.height); } } function component(width, height, color, x, y, type) { this.type = type; this.width = width; this.height = height; this.speed = 0; this.gravity = 0.1; this.gravitySpeed = 0; this.bounce = 0.6; this.angle = 0; this.x = x; this.y = y; this.update = function() { ctx = myGameArea.context; ctx.save(); ctx.translate(this.x, this.y); ctx.rotate(this.angle); ctx.fillStyle = color; ctx.fillRect(this.width / -2, this.height / -2, this.width, this.height); ctx.restore(); } this.newPos = function() { var rockbottom = myGameArea.canvas.height - (this.height / 2); this.gravitySpeed += this.gravity; this.x += this.speed * Math.cos(this.angle); this.y += (this.speed * Math.sin(this.angle)) + this.gravitySpeed; if (this.y > rockbottom) { this.gravitySpeed=-(this.gravitySpeed * this.bounce); this.gravitySpeed = Number(this.gravitySpeed.toFixed(2)); this.y = rockbottom; } } } function updateGameArea() { myGameArea.clear(); myGamePiece.newPos(); myGamePiece.update(); } function restartgame(x) { myGameArea.stop(); document.getElementById("canvascontainer").innerHTML = ""; startGame(); } startGame(); </script>

Bouncing

Another functionallity we want to add is the bounce property. The bounce property indicates if the component will bounce back when gravity makes it fall down to the ground. The bounce property value must be a number. 0 is no bounce at all, and 1 will make the component bounce all the way backto where it start falling.

Example

function component(width, height, color, x, y, type) { this.type = type; this.width = width; this.height = height; this.x = x; this.y = y; this.speedX = 0; this.speedY = 0; this.gravity = 0.1; this.gravitySpeed = 0; this.bounce = 0.6; this.update = function() { ctx = myGameArea.context; ctx.fillStyle = color; ctx.fillRect(this.x, this.y, this.width, this.height); } this.newPos = function() { this.gravitySpeed += this.gravity; this.x += this.speedX; this.y += this.speedY + this.gravitySpeed; this.hitBottom(); } this.hitBottom = function() { var rockbottom = this.gamearea.canvas.height - this.height; if (this.y > rockbottom) { this.y = rockbottom; this.gravitySpeed = -(this.gravitySpeed * this.bounce); } } } Try it Yourself » <button id="playagain" onclick="clickPlayagain()">Rotate</button> <script> var myGameArea; var myGamePiece; function startGame() { myGameArea = new gamearea(""); myGamePiece = new component(30, 30, "red", 25, 90); myGameArea.start(); } function gamearea(x) { this.canvas = document.createElement("canvas"); this.canvas.width = 320; this.canvas.height = 180; document.getElementById("canvascontainer" + x).innerHTML = ""; document.getElementById("canvascontainer" + x).appendChild(this.canvas); this.context = this.canvas.getContext("2d"); this.frameNo = 0; this.start = function() { this.interval = setInterval(updateGameArea, 20); } this.stop = function() { clearInterval(this.interval); } this.clear = function(){ this.context.clearRect(0, 0, this.canvas.width, this.canvas.height); } } function component(width, height, color, x, y, type) { this.type = type; this.width = width; this.height = height; this.speed = 0; this.angle = 0; this.moveangle = 0; this.x = x; this.y = y; this.update = function() { ctx = myGameArea.context; ctx.save(); ctx.translate(this.x, this.y); ctx.rotate(this.angle); if (this.type == "text") { ctx.font = this.width + " " + this.height; ctx.fillStyle = color; width = ctx.measureText(this.text).width; height = ctx.measureText("m").width ctx.fillText(this.text, width/ -2, height/2); } else { ctx.fillStyle = color; ctx.fillRect(this.width / -2, this.height / -2, this.width, this.height); } ctx.restore(); } this.newPos = function() { this.x += this.speed * Math.cos(this.angle); this.y += this.speed * Math.sin(this.angle); this.angle += this.moveangle } } var rotation; function updateGameArea(y) { myGameArea.clear(); myGameArea.frameNo++; myGamePiece.speed = 0; myGamePiece.moveangle = 1 * Math.PI / 180; if (myGameArea.frameNo > 90) { myGamePiece.moveangle = 0; } myGamePiece.newPos(); myGamePiece.update(); } function clickPlayagain() { myGameArea.stop(); startGame(); } startGame(); </script>

Rotating Components

Earlier in this tutorial, the red square was able to move around on the gamearea, but it could not turn or rotate. To rotate components, we have to change the way we draw components. The only rotation method available for the canvas element will rotate the entire canvas: Everything else you draw on the canvas will also be rotated, not only the specific component. That is why we have to make some changes in the update() method: First, we save the current canvas context object: ctx.save(); Then we move the entire canvas to the center of the specific component, using the translate method: ctx.translate(x, y); Then we perform the wanted rotation using the rotate() method: ctx.rotate(angle); Now we are ready to draw the component onto the canvas, but now we will draw it with its center position at position 0,0 on the translated (and rotated) canvas: ctx.fillRect(width / -2, height / -2, width, height); When we are finished, we must restore the context object back to its saved position, using the restore method: ctx.restore(); The component is the only thing that is rotated:

The Component Constructor

The component constructor has a new property called angle, which is radian number that represents the angle of the component. The update method of the component constructor is were we draw the component, and here you can see the changes that will allow the component to rotate:

Example

function component(width, height, color, x, y) { this.width = width; this.height = height; this.angle = 0; this.x = x; this.y = y; this.update = function() { ctx = myGameArea.context; ctx.save(); ctx.translate(this.x, this.y); ctx.rotate(this.angle); ctx.fillStyle = color; ctx.fillRect(this.width / -2, this.height / -2, this.width, this.height); ctx.restore(); } } function updateGameArea() { myGameArea.clear(); myGamePiece.angle += 1 * Math.PI / 180; myGamePiece.update(); } Try it Yourself » <button id="playagain" onclick="clickPlayagain()">Play again</button>

How to Move Objects?

Add a speed property to the component constructor, which represents the current speed of the component. Also make some changes in the newPos() method, to calculate the position of the component, based on speed and angle. By default, the components are facing up, and by setting the speed property to 1, the component will start moving forward.

Example

function component(width, height, color, x, y) { this.gamearea = gamearea; this.width = width; this.height = height; this.angle = 0; this.speed = 1; this.x = x; this.y = y; this.update = function() { ctx = myGameArea.context; ctx.save(); ctx.translate(this.x, this.y); ctx.rotate(this.angle); ctx.fillStyle = color; ctx.fillRect(this.width / -2, this.height / -2, this.width, this.height); ctx.restore(); } this.newPos = function() { this.x += this.speed * Math.sin(this.angle); this.y -= this.speed * Math.cos(this.angle); } } Try it Yourself »

Making Turns

We also want to be able to make left and right turns. Make a new property called moveAngle, which indicates the current moving value, or rotation angle. In the newPos() method calculate the angle based on the moveAngle property:

Example

Set the moveangle property to 1, and see what happens: function component(width, height, color, x, y) { this.width = width; this.height = height; this.angle = 0; this.moveAngle = 1; this.speed = 1; this.x = x; this.y = y; this.update = function() { ctx = myGameArea.context; ctx.save(); ctx.translate(this.x, this.y); ctx.rotate(this.angle); ctx.fillStyle = color; ctx.fillRect(this.width / -2, this.height / -2, this.width, this.height); ctx.restore(); } this.newPos = function() { this.angle += this.moveAngle * Math.PI / 180; this.x += this.speed * Math.sin(this.angle); this.y -= this.speed * Math.cos(this.angle); } } Try it Yourself »

Use the Keyboard

How does the red square move when using the keyboard? Instead of moving up and down, and from side to side, the red square moves forward when you use the "up" arrow,and turns left and right when pressing the left and right arrows.

Example

Try it Yourself » <script> var myGameArea; var myGamePiece; //var myGameArea2; //var myGamePiece2; function startGame() { myGameArea = new gamearea(""); myGamePiece = new component(20, 20, "red", 15, 110); myGameArea.start(); // myGameArea2 = new gamearea("2"); // myGamePiece2 = new component(myGameArea2, "50px", "Consolas", "red", 100, 15, "text"); // myGamePiece2.text = "\u00BB"; // myGameArea2.start(); } function gamearea(x) { this.canvas = document.createElement("canvas"); this.canvas.width = 320; this.canvas.height = 180; document.getElementById("canvascontainer" + x).innerHTML = ""; document.getElementById("canvascontainer" + x).appendChild(this.canvas); this.context = this.canvas.getContext("2d"); this.frameNo = 0; this.start = function() { this.interval = setInterval(updateGameArea, 20); } this.stop = function() { clearInterval(this.interval); } this.clear = function(){ this.context.clearRect(0, 0, this.canvas.width, this.canvas.height); } } function component(width, height, color, x, y, type) { this.type = type; this.width = width; this.height = height; this.speed = 0; this.angle = 0; this.moveangle = 0; this.x = x; this.y = y; this.update = function() { ctx = myGameArea.context; ctx.save(); ctx.translate(this.x, this.y); ctx.rotate(this.angle); if (this.type == "text") { ctx.font = this.width + " " + this.height; ctx.fillStyle = color; width = ctx.measureText(this.text).width; height = ctx.measureText("m").width ctx.fillText(this.text, width/ -2, height/2); } else { ctx.fillStyle = color; ctx.fillRect(this.width / -2, this.height / -2, this.width, this.height); } ctx.restore(); } this.newPos = function() { this.x += this.speed * Math.sin(this.angle); this.y -= this.speed * Math.cos(this.angle); this.angle += this.moveangle } } var rotation; function updateGameArea(y) { myGameArea.clear(); myGameArea.frameNo++; myGamePiece.speed = 1; if (myGameArea.frameNo == 1) { rotation = 0; document.getElementById("playagain").disabled = true; // document.getElementById("playagain2").disabled = true; } rotation++; if (rotation == 40) { myGamePiece.moveangle = 1 * Math.PI / 180; } if (rotation == 130) { myGamePiece.moveangle = 0; } if (myGameArea.frameNo >= 520) { myGamePiece.speed = 0; myGamePiece.moveangle = 0; document.getElementById("playagain").disabled = false; // document.getElementById("playagain2").disabled = false; } myGamePiece.newPos(); myGamePiece.update(); // myGameArea2.clear(); // myGameArea2.frameNo++; // myGamePiece2.speed = 1; // if (rotation == 40) { // myGamePiece2.moveangle = 1 * Math.PI / 180; // } if (rotation == 130) { // myGamePiece2.moveangle = 0; rotation = 0; } // if (myGameArea2.frameNo >= 520) { // myGamePiece2.speed = 0; // myGamePiece2.moveangle = 0; // } // myGamePiece2.newPos(); // myGamePiece2.update(); } function clickPlayagain() { myGameArea.stop(); // myGameArea2.stop(); startGame(); } startGame(); </script>