HTML5 Game Development – Lesson 2

Tutorials

HTML5 Game Development – Lesson 2. Today we continue a series of articles on game development in HTML5. Today we will continue basics (and maybe even advanced basics). I going to show you how to fill objects with gradient color, draw text, use custom fonts to draw text, basic animation, and most important: ui element – Button.

Our previous article you can read here: Developing Your First HTML5 Game – Lesson 1. I going to work with our previous script – we will just enhance it. I going to draw text using custom font, animate object (square) filled with gradient color, and will draw ‘Play / Pause’ button to pausing animation.

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 are all html of my demo

index.html

01 <!DOCTYPE html>
02 <html lang="en" >
03     <head>
04         <meta charset="utf-8" />
05         <title>HTML5 Game Development - Lesson 2 | 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 type="text/javascript" src="js/jquery-1.5.2.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="800" height="600"></canvas>
16         </div>
17         <footer>
18             <h2>HTML5 Game Development - Lesson 2</h2>
19             <a href="https://www.script-tutorials.com/html5-game-development-lesson-2" 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

01 /* general styles */
02 *{
03     margin:0;
04     padding:0;
05 }
06 @font-face {
07     font-family"DS-Digital";
08     srcurl("../fonts/Ds-digib.ttf");
09 }
10 body {
11     background-color:#bababa;
12     background-image: -webkit-radial-gradient(600px 300pxcircle#ffffff#bababa 60%);
13     background-image: -moz-radial-gradient(600px 300pxcircle#ffffff#bababa 60%);
14     background-image: -o-radial-gradient(600px 300pxcircle#ffffff#bababa 60%);
15     background-image: radial-gradient(600px 300pxcircle#ffffff#bababa 60%);
16     color:#fff;
17     font:14px/1.3 Arial,sans-serif;
18     min-height:1000px;
19 }
20 .container {
21     width:100%;
22 }
23 .container > * {
24     display:block;
25     margin:50px auto;
26 }
27 footer {
28     background-color:#212121;
29     bottom:0;
30     box-shadow: 0 -1px 2px #111111;
31     display:block;
32     height:70px;
33     left:0;
34     position:fixed;
35     width:100%;
36     z-index:100;
37 }
38 footer h2{
39     font-size:22px;
40     font-weight:normal;
41     left:50%;
42     margin-left:-400px;
43     padding:22px 0;
44     position:absolute;
45     width:540px;
46 }
47 footer a.stuts,a.stuts:visited{
48     border:none;
49     text-decoration:none;
50     color:#fcfcfc;
51     font-size:14px;
52     left:50%;
53     line-height:31px;
54     margin:23px 0 0 110px;
55     position:absolute;
56     top:0;
57 }
58 footer .stuts span {
59     font-size:22px;
60     font-weight:bold;
61     margin-left:5px;
62 }
63 h3 {
64     text-align:center;
65 }
66 #scene {
67     background-image:url(../images/01.jpg);
68     position:relative;
69 }

Pay attention to ‘@font-face’. We will using this way to link custom font file (ttf) to our lesson (to draw at canvas).

Step 3. JS

js/jquery-1.5.2.min.js

We will using jQuery for our demo. This allows easy bind different events (for mouse etc). Next file most important (here are all our html5 functional):

js/script.js

001 var canvas, ctx;
002 var circles = [];
003 var selectedCircle;
004 var hoveredCircle;
005 var button;
006 var moving = false;
007 var speed = 2.0;
008 // -------------------------------------------------------------
009 // objects :
010 function Circle(x, y, radius){
011     this.x = x;
012     this.y = y;
013     this.radius = radius;
014 }
015 function Button(x, y, w, h, state, image) {
016     this.x = x;
017     this.y = y;
018     this.w = w;
019     this.h = h;
020     this.state = state;
021     this.imageShift = 0;
022     this.image = image;
023 }
024 // -------------------------------------------------------------
025 // draw functions :
026 function clear() { // clear canvas function
027     ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
028 }
029 function drawCircle(ctx, x, y, radius) { // draw circle function
030     ctx.fillStyle = 'rgba(255, 35, 55, 1.0)';
031     ctx.beginPath();
032     ctx.arc(x, y, radius, 0, Math.PI*2, true);
033     ctx.closePath();
034     ctx.fill();
035     ctx.lineWidth = 1;
036     ctx.strokeStyle = 'rgba(0, 0, 0, 1.0)';
037     ctx.stroke(); // draw border
038 }
039 function drawScene() { // main drawScene function
040     clear(); // clear canvas
041     // draw the title text
042     ctx.font = '42px DS-Digital';
043     ctx.textAlign = 'center';
044     ctx.fillStyle = '#ffffff';
045     ctx.fillText('Welcome to lesson #2', ctx.canvas.width/2, 50);
046     var bg_gradient = ctx.createLinearGradient(0, 200, 0, 400);
047     bg_gradient.addColorStop(0.0, 'rgba(255, 0, 0, 0.8)');
048     bg_gradient.addColorStop(0.5, 'rgba(0, 255, 0, 0.8)');
049     bg_gradient.addColorStop(1.0, 'rgba(0, 0, 255, 0.8)');
050     ctx.beginPath(); // custom shape begin
051     ctx.fillStyle = bg_gradient;
052     ctx.moveTo(circles[0].x, circles[0].y);
053     for (var i=0; i<circles.length; i++) {
054         ctx.lineTo(circles[i].x, circles[i].y);
055     }
056     ctx.closePath(); // custom shape end
057     ctx.fill(); // fill custom shape
058     ctx.lineWidth = 2;
059     ctx.strokeStyle = 'rgba(0, 0, 255, 0.5)';
060     ctx.stroke(); // draw border
061     // reverting direction
062     if (circles[0].x <= 300 || circles[0].x >= 385) {
063         speed = -speed;
064     }
065     // central object behavior
066     if (moving) {
067         circles[0].x -= speed;
068         circles[0].y -= speed;
069         circles[1].x += speed;
070         circles[1].y -= speed;
071         circles[2].x += speed;
072         circles[2].y += speed;
073         circles[3].x -= speed;
074         circles[3].y += speed;
075     }
076     drawCircle(ctx, circles[0].x, circles[0].y, (hoveredCircle == 0) ? 25 : 15);
077     drawCircle(ctx, circles[1].x, circles[1].y, (hoveredCircle == 1) ? 25 : 15);
078     drawCircle(ctx, circles[2].x, circles[2].y, (hoveredCircle == 2) ? 25 : 15);
079     drawCircle(ctx, circles[3].x, circles[3].y, (hoveredCircle == 3) ? 25 : 15);
080     // draw button
081     ctx.drawImage(button.image, 0, button.imageShift, button.w, button.h, button.x, button.y, button.w, button.h);
082     // draw text
083     ctx.font = '30px DS-Digital';
084     ctx.fillStyle = '#ffffff';
085     ctx.fillText('Play/Pause', 135, 480);
086     ctx.fillText(button.state, 135, 515);
087 }
088 // -------------------------------------------------------------
089 // initialization
090 $(function(){
091     canvas = document.getElementById('scene');
092     ctx = canvas.getContext('2d');
093     var circleRadius = 15;
094     var width = canvas.width;
095     var height = canvas.height;
096     // lets add 4 circles manually
097     circles.push(new Circle(width / 2 - 20, height / 2 - 20, circleRadius));
098     circles.push(new Circle(width / 2 + 20, height / 2 - 20, circleRadius));
099     circles.push(new Circle(width / 2 + 20, height / 2 + 20, circleRadius));
100     circles.push(new Circle(width / 2 - 20, height / 2 + 20, circleRadius));
101     // load the guide sprite image
102     buttonImage = new Image();
103     buttonImage.src = 'images/button.png';
104     buttonImage.onload = function() {
105     }
106     button = new Button(50, 450, 180, 120, 'normal', buttonImage);
107     // binding mousedown event (for dragging)
108     $('#scene').mousedown(function(e) {
109         var mouseX = e.layerX || 0;
110         var mouseY = e.layerY || 0;
111         for (var i=0; i<circles.length; i++) { // checking through all circles - are mouse down inside circle or not
112             var circleX = circles[i].x;
113             var circleY = circles[i].y;
114             var radius = circles[i].radius;
115             if (Math.pow(mouseX-circleX,2) + Math.pow(mouseY-circleY,2) < Math.pow(radius,2)) {
116                 selectedCircle = i;
117                 break;
118             }
119         }
120         // button behavior
121         if (mouseX > button.x && mouseX < button.x+button.w && mouseY > button.y && mouseY < button.y+button.h) {
122             button.state = 'pressed';
123             button.imageShift = 262;
124         }
125     });
126     $('#scene').mousemove(function(e) { // binding mousemove event for dragging selected circle
127         var mouseX = e.layerX || 0;
128         var mouseY = e.layerY || 0;
129         if (selectedCircle != undefined) {
130             // var canvasPosition = $(this).offset();
131             var radius = circles[selectedCircle].radius;
132             circles[selectedCircle] = new Circle(mouseX, mouseY,radius); // changing position of selected circle
133         }
134         hoveredCircle = undefined;
135         for (var i=0; i<circles.length; i++) { // checking through all circles - are mouse down inside circle or not
136             var circleX = circles[i].x;
137             var circleY = circles[i].y;
138             var radius = circles[i].radius;
139             if (Math.pow(mouseX-circleX,2) + Math.pow(mouseY-circleY,2) < Math.pow(radius,2)) {
140                 hoveredCircle = i;
141                 circles[hoveredCircle] = new Circle(circleX, circleY, 25);
142                 break;
143             }
144         }
145         // button behavior
146         if (button.state != 'pressed') {
147             button.state = 'normal';
148             button.imageShift = 0;
149             if (mouseX > button.x && mouseX < button.x+button.w && mouseY > button.y && mouseY < button.y+button.h) {
150                 button.state = 'hover';
151                 button.imageShift = 131;
152             }
153         }
154     });
155     $('#scene').mouseup(function(e) { // on mouseup - cleaning selectedCircle
156         selectedCircle = undefined;
157         // button behavior
158         if (button.state == 'pressed') {
159             moving = !moving;
160         }
161         button.state = 'normal';
162         button.imageShift = 0;
163     });
164     setInterval(drawScene, 30); // loop drawScene
165 });

Here are several explanations about new features. 1. We can draw text (with custom font) using next code:

1 ctx.font = '42px DS-Digital';
2 ctx.textAlign = 'center';
3 ctx.fillStyle = '#ffffff';
4 ctx.fillText('Welcome to lesson #2', ctx.canvas.width/2, 50);

2. Applying gradient color to objects:

1 var bg_gradient = ctx.createLinearGradient(0, 200, 0, 400);
2 bg_gradient.addColorStop(0.0, 'rgba(255, 0, 0, 0.8)');
3 bg_gradient.addColorStop(0.5, 'rgba(0, 255, 0, 0.8)');
4 bg_gradient.addColorStop(1.0, 'rgba(0, 0, 255, 0.8)');
5 ctx.fillStyle = bg_gradient;

3. Button itself – I used one sprite image with all 3 button states. Also I added event handlers to hover/down events. Here are way of loading and drawing image at canvas:

1 buttonImage = new Image();
2 buttonImage.src = 'images/button.png';
3 .......
4 ctx.drawImage(image, sx, sy, sWidth, sHeight, dx, dy, width, height);

Step 4. Custom files

fonts/Ds-digib.ttf and images/button.png

Both files will available in our package


Live Demo

Conclusion

Cool, isn’t it? I will be glad to see your thanks and comments. Good luck!

Rate article