HTML5 Game Development – Lesson 4

Tutorials

Today we continue a series of articles on game development in HTML5 using canvas. Today we going to learn next elements: animation with sprites and basic work with sound. In our demonstration you will see a flying dragon. We will hear the sounds of wings all time (we will loop this sound), and another sound – dragon’s roar (on mouseup event). And finally we will teach our dragon be closer to the mouse cursor (when we hold down the mouse).

Our previous article you can read here: Developing Your First HTML5 Game – Lesson 3. Our new script is new enhanced version of previous one.

Here are our demo and downloadable package:

Live Demo

[sociallocker]

download in package

[/sociallocker]


Ok, download the example files and lets start coding !


Step 1. HTML

Here is html markup of our demo.

index.html

01 <!DOCTYPE html>
02 <html lang="en" >
03     <head>
04         <meta charset="utf-8" />
05         <title>HTML5 Game Development - Lesson 4 | Script Tutorials</title>
06         <link href="css/main.css" rel="stylesheet" type="text/css" />
07         <!--[if lt IE 9]>
08           <script src="http://html5shiv.googlecode.com/svn/trunk/html5.js"></script>
09         <![endif]-->
10         <script src="http://code.jquery.com/jquery-latest.min.js"></script>
11         <script type="text/javascript" src="js/script.js"></script>
12     </head>
13     <body>
14         <div class="container">
15             <canvas id="scene" width="1000" height="600"></canvas>
16         </div>
17         <footer>
18             <h2>HTML5 Game Development - Lesson 4</h2>
19             <a href="https://www.script-tutorials.com/html5-game-development-lesson-4/" class="stuts">Back to original tutorial on <span>Script Tutorials</span></a>
20         </footer>
21     </body>
22 </html>

Step 2. CSS

Here are used CSS styles.

css/main.css

I will not publish styles today – this is just page layout styles, nothing special. Available in package.

Step 3. JS

js/script.js

001 // inner variables
002 var canvas, ctx;
003 var backgroundImage;
004 var iBgShiftX = 100;
005 var dragon;
006 var dragonW = 75; // dragon width
007 var dragonH = 70; // dragon height
008 var iSprPos = 0; // initial sprite frame
009 var iSprDir = 4; // initial dragon direction
010 var dragonSound; // dragon sound
011 var wingsSound; // wings sound
012 var bMouseDown = false// mouse down state
013 var iLastMouseX = 0;
014 var iLastMouseY = 0;
015 // -------------------------------------------------------------
016 // objects :
017 function Dragon(x, y, w, h, image) {
018     this.x = x;
019     this.y = y;
020     this.w = w;
021     this.h = h;
022     this.image = image;
023     this.bDrag = false;
024 }
025 // -------------------------------------------------------------
026 // draw functions :
027 function clear() { // clear canvas function
028     ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
029 }
030 function drawScene() { // main drawScene function
031     clear(); // clear canvas
032     // draw background
033     iBgShiftX -= 4;
034     if (iBgShiftX <= 0) {
035         iBgShiftX = 1045;
036     }
037     ctx.drawImage(backgroundImage, 0 + iBgShiftX, 0, 1000, 940, 0, 0, 1000, 600);
038     // update sprite positions
039     iSprPos++;
040     if (iSprPos >= 9) {
041         iSprPos = 0;
042     }
043     // in case of mouse down - move dragon more close to our mouse
044     if (bMouseDown) {
045         if (iLastMouseX > dragon.x) {
046             dragon.x += 5;
047         }
048         if (iLastMouseY > dragon.y) {
049             dragon.y += 5;
050         }
051         if (iLastMouseX < dragon.x) {
052             dragon.x -= 5;
053         }
054         if (iLastMouseY < dragon.y) {
055             dragon.y -= 5;
056         }
057     }
058     // draw dragon
059     ctx.drawImage(dragon.image, iSprPos*dragon.w, iSprDir*dragon.h, dragon.w, dragon.h, dragon.x - dragon.w/2, dragon.y - dragon.h/2, dragon.w, dragon.h);
060 }
061 // -------------------------------------------------------------
062 // initialization
063 $(function(){
064     canvas = document.getElementById('scene');
065     ctx = canvas.getContext('2d');
066     var width = canvas.width;
067     var height = canvas.height;
068     // load background image
069     backgroundImage = new Image();
070     backgroundImage.src = 'images/hell.jpg';
071     backgroundImage.onload = function() {
072     }
073     backgroundImage.onerror = function() {
074         console.log('Error loading the background image.');
075     }
076     // 'Dragon' music init
077     dragonSound = new Audio('media/dragon.wav');
078     dragonSound.volume = 0.9;
079     // 'Wings' music init
080     wingsSound = new Audio('media/wings.wav');
081     wingsSound.volume = 0.9;
082     wingsSound.addEventListener('ended'function() { // looping wings sound
083         this.currentTime = 0;
084         this.play();
085     }, false);
086     wingsSound.play();
087     // initialization of dragon
088     var oDragonImage = new Image();
089     oDragonImage.src = 'images/dragon.gif';
090     oDragonImage.onload = function() {
091     }
092     dragon = new Dragon(400, 300, dragonW, dragonH, oDragonImage);
093     $('#scene').mousedown(function(e) { // binding mousedown event (for dragging)
094         var mouseX = e.layerX || 0;
095         var mouseY = e.layerY || 0;
096         if(e.originalEvent.layerX) { // changes for jquery 1.7
097             mouseX = e.originalEvent.layerX;
098             mouseY = e.originalEvent.layerY;
099         }
100         bMouseDown = true;
101         if (mouseX > dragon.x- dragon.w/2 && mouseX < dragon.x- dragon.w/2 +dragon.w &&
102             mouseY > dragon.y- dragon.h/2 && mouseY < dragon.y-dragon.h/2 +dragon.h) {
103             dragon.bDrag = true;
104             dragon.x = mouseX;
105             dragon.y = mouseY;
106         }
107     });
108     $('#scene').mousemove(function(e) { // binding mousemove event
109         var mouseX = e.layerX || 0;
110         var mouseY = e.layerY || 0;
111         if(e.originalEvent.layerX) { // changes for jquery 1.7
112             mouseX = e.originalEvent.layerX;
113             mouseY = e.originalEvent.layerY;
114         }
115         // saving last coordinates
116         iLastMouseX = mouseX;
117         iLastMouseY = mouseY;
118         // perform dragon dragging
119         if (dragon.bDrag) {
120             dragon.x = mouseX;
121             dragon.y = mouseY;
122         }
123         // change direction of dragon (depends on mouse position)
124         if (mouseX > dragon.x && Math.abs(mouseY-dragon.y) < dragon.w/2) {
125             iSprDir = 0;
126         else if (mouseX < dragon.x && Math.abs(mouseY-dragon.y) < dragon.w/2) {
127             iSprDir = 4;
128         else if (mouseY > dragon.y && Math.abs(mouseX-dragon.x) < dragon.h/2) {
129             iSprDir = 2;
130         else if (mouseY < dragon.y && Math.abs(mouseX-dragon.x) < dragon.h/2) {
131             iSprDir = 6;
132         else if (mouseY < dragon.y && mouseX < dragon.x) {
133             iSprDir = 5;
134         else if (mouseY < dragon.y && mouseX > dragon.x) {
135             iSprDir = 7;
136         else if (mouseY > dragon.y && mouseX < dragon.x) {
137             iSprDir = 3;
138         else if (mouseY > dragon.y && mouseX > dragon.x) {
139             iSprDir = 1;
140         }
141     });
142     $('#scene').mouseup(function(e) { // binding mouseup event
143         dragon.bDrag = false;
144         bMouseDown = false;
145         // play dragon sound
146         dragonSound.currentTime = 0;
147         dragonSound.play();
148     });
149     setInterval(drawScene, 30); // loop drawScene
150 });

How it work (shortly): Firstly we define canvas, context, then we load background image, two sounds, then we initialize our dragon and binding different mouse events. In our main loop draw function I am shifting background image (loop), then update sprite positions, and finally – draw our dragon. In our code you can find several new interesting methods:

1. Loop background sound

1 // 'Wings' music init
2 wingsSound = new Audio('media/wings.wav');
3 wingsSound.volume = 0.9;
4 wingsSound.addEventListener('ended'function() { // looping wings sound
5     this.currentTime = 0;
6     this.play();
7 }, false);
8 wingsSound.play();

2. Draw sprites

01     var oDragonImage = new Image();
02     oDragonImage.src = 'images/dragon.gif';
03     oDragonImage.onload = function() {
04     }
05 ....
06     // update sprite positions
07     iSprPos++;
08     if (iSprPos >= 9) {
09         iSprPos = 0;
10     }
11     // draw dragon
12     ctx.drawImage(dragon.image, iSprPos*dragon.w, iSprDir*dragon.h, dragon.w, dragon.h, dragon.x - dragon.w/2, dragon.y - dragon.h/2, dragon.w, dragon.h);

So, we loading initial image (with set of all sub-images), then – draw part of that image, then shifting its positions, and draw again (loop).

Step 4. Custom files

images/dragon.gif, images/hell.jpg, media/dragon.wav and media/wings.wav

All these files available in our package


Live Demo

Conclusion

Are you like our new handy dragon? 🙂 I will be glad to see your thanks and comments. Good luck!

Rate article