HTML5游戏开发系列教程9

原文地址:http://www.script-tutorials.com/html5-game-development-lesson-9/

今天我们将继续使用canvas来进行HTML5游戏开发系列的文章。这次我准备了一个新游戏,是基于第4篇的游戏,但是增加了火球,敌人和碰撞检测。故,我们的龙可以发射火球来杀死敌人,并且记录分数。这样该游戏就有更多的交互性。

之前的翻译文章可以点击这里:http://www.cnblogs.com/pigzhu/p/3234255.html

第一步:HTML

首先是我们基础的html代码:

 1 <!DOCTYPE html>

 2 <html lang="en" >

 3     <head>

 4         <meta charset="utf-8" />

 5         <title>HTML5 Game Development - Lesson 9 | Script Tutorials</title>

 6         <link href="css/main.css" rel="stylesheet" type="text/css" />

 7 

 8         <!--[if lt IE 9]>

 9           <script src="http://html5shiv.googlecode.com/svn/trunk/html5.js"></script>

10         <![endif]-->

11         <script src="js/jquery-2.0.0.min.js"></script>

12         <script src="js/script.js"></script>

13     </head>

14     <body>

15         <header tabindex="0">

16             <h2>HTML5 Game Development - Lesson 9</h2>

17             <a  href="http://www.script-tutorials.com/html5-game-development-lesson-9/" class="stuts">Back to original tutorial on <span>Script Tutorials</span></a>

18         </header>

19 

20         <div class="container">

21             <canvas id="scene" width="1000" height="600" tabindex="1"></canvas>

22         </div>

23     </body>

24 </html>
View Code

第二步:CSS

接着这里是CSS样式。

css/main.css

这次依然不打算显示出CSS文件的内容了,因为仅仅只是些页面布局样式。你可以在源代码包里找到该文件。

第三步:JS

js/script.js

  1 // 内部变量

  2 var canvas, ctx;

  3 var backgroundImage;

  4 var iBgShiftX = 100;

  5 

  6 var dragon, enemy = null; // 游戏中两个主要实体对象

  7 var balls = [];

  8 var enemies = [];

  9 

 10 var dragonW = 75; // 龙的宽度

 11 var dragonH = 70; // 龙的高度

 12 var iSprPos = 0; // 初始帧的位置

 13 var iSprDir = 0; // 初始龙的朝向

 14 var iEnemyW = 128; // 敌人的宽度

 15 var iEnemyH = 128; // 敌人的高度

 16 var iBallSpeed = 10; // 火球的速度

 17 var iEnemySpeed = 2; // 敌人的速度

 18 

 19 var dragonSound; // 龙的声音

 20 var wingsSound; // 翅膀的声音

 21 var explodeSound, explodeSound2; // 爆炸声音

 22 var laughtSound; // 敌人从左边逃出,嘲笑的声音

 23 

 24 var bMouseDown = false; // 鼠标是否按下

 25 var iLastMouseX = 0;

 26 var iLastMouseY = 0;

 27 var iScore = 0;

 28 // -------------------------------------------------------------

 29 

 30 //

 31 function Dragon(x, y, w, h, image) {

 32     this.x = x;

 33     this.y = y;

 34     this.w = w;

 35     this.h = h;

 36     this.image = image;

 37     this.bDrag = false;

 38 }

 39 //

 40 function Ball(x, y, w, h, speed, image) {

 41     this.x = x;

 42     this.y = y;

 43     this.w = w;

 44     this.h = h;

 45     this.speed = speed;

 46     this.image = image;

 47 }

 48 // 敌人

 49 function Enemy(x, y, w, h, speed, image) {

 50     this.x = x;

 51     this.y = y;

 52     this.w = w;

 53     this.h = h;

 54     this.speed = speed;

 55     this.image = image;

 56 }

 57 // -------------------------------------------------------------

 58 // 获得位于x和y之间的随机数。

 59 function getRand(x, y) {

 60     return Math.floor(Math.random() * y) + x;

 61 }

 62 

 63 // draw functions :

 64 function drawScene() { // main drawScene function

 65     ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height); // 清除这个画布

 66 

 67     // 画背景

 68     iBgShiftX += 4;

 69     if (iBgShiftX >= 1045) {

 70         iBgShiftX = 0;

 71     }

 72     ctx.drawImage(backgroundImage, 0 + iBgShiftX, 0, 1000, 940, 0, 0, 1000, 600);

 73 

 74     // 更新帧的位置

 75     iSprPos++;

 76     if (iSprPos >= 9) {

 77         iSprPos = 0;

 78     }

 79 

 80     // 当鼠标被按下,龙朝着鼠标移动

 81     if (bMouseDown) {

 82         if (iLastMouseX > dragon.x) {

 83             dragon.x += 5;

 84         }

 85         if (iLastMouseY > dragon.y) {

 86             dragon.y += 5;

 87         }

 88         if (iLastMouseX < dragon.x) {

 89             dragon.x -= 5;

 90         }

 91         if (iLastMouseY < dragon.y) {

 92             dragon.y -= 5;

 93         }

 94     }

 95 

 96     // 绘制龙

 97     ctx.drawImage(dragon.image, iSprPos * dragon.w, iSprDir * dragon.h, dragon.w, dragon.h,

 98      dragon.x - dragon.w / 2, dragon.y - dragon.h / 2, dragon.w, dragon.h);

 99 

100     // 如果有火球则绘制

101     if (balls.length > 0) {

102         for (var key in balls) {

103             if (balls[key] != undefined) {

104                 ctx.drawImage(balls[key].image, balls[key].x, balls[key].y);

105                 balls[key].x += balls[key].speed;

106 

107                 if (balls[key].x > canvas.width) {  //超出屏幕,移除

108                     delete balls[key];

109                 }

110             }

111         }

112     }

113 

114     // 如果有敌人则绘制

115     if (enemies.length > 0) {

116         for (var ekey in enemies) {

117             if (enemies[ekey] != undefined) {

118                 ctx.drawImage(enemies[ekey].image, enemies[ekey].x, enemies[ekey].y);

119                 enemies[ekey].x += enemies[ekey].speed;

120 

121                 if (enemies[ekey].x < - iEnemyW) {  //敌人没有被击中,从左边消失,并发出嘲笑声音

122                     delete enemies[ekey];

123 

124                     laughtSound.currentTime = 0;

125                     laughtSound.play();

126                 }

127             }

128         }

129     }

130 

131     // 检测是否击中敌人

132     if (balls.length > 0) {

133         for (var key in balls) {

134             if (balls[key] != undefined) {

135 

136                 if (enemies.length > 0) {

137                     for (var ekey in enemies) {

138                         if (enemies[ekey] != undefined && balls[key] != undefined) {

139                             if (balls[key].x + balls[key].w > enemies[ekey].x && balls[key].y + balls[key].h > enemies[ekey].y 

140                                 && balls[key].y < enemies[ekey].y + enemies[ekey].h) {

141                                 delete enemies[ekey];

142                                 delete balls[key];

143                                 iScore++;

144 

145                                 explodeSound2.currentTime = 0;

146                                 explodeSound2.play();

147                             }

148                         }

149                     }

150                 }

151             }

152         }

153     }

154 

155     // 绘制分数

156     ctx.font = '16px Verdana';

157     ctx.fillStyle = '#fff';

158     ctx.fillText('Score: ' + iScore * 10, 900, 580);

159     ctx.fillText('Plese click "1" to cast fireball', 100, 580);

160 

161 }

162 

163 // -------------------------------------------------------------

164 

165 // 初始化

166 $(function(){

167     canvas = document.getElementById('scene');

168     ctx = canvas.getContext('2d');

169 

170     var width = canvas.width;

171     var height = canvas.height;

172 

173     // 加载背景图片

174     backgroundImage = new Image();

175     backgroundImage.src = 'images/hell.jpg';

176     backgroundImage.onload = function() {

177     }

178     backgroundImage.onerror = function() {

179         console.log('Error loading the background image.');

180     }

181 

182     //初始化各种声音

183     dragonSound = new Audio('media/dragon.wav');

184     dragonSound.volume = 0.9;

185 

186     laughtSound = new Audio('media/laught.wav');

187     laughtSound.volume = 0.9;

188 

189     explodeSound = new Audio('media/explode1.wav');

190     explodeSound.volume = 0.9;

191     explodeSound2 = new Audio('media/explosion.wav');

192     explodeSound2.volume = 0.9;

193 

194     wingsSound = new Audio('media/wings.wav');

195     wingsSound.volume = 0.9;

196     wingsSound.addEventListener('ended', function() { // loop wings sound

197         this.currentTime = 0;

198         this.play();

199     }, false);

200     wingsSound.play();

201 

202     // 加载各种图片

203     var oBallImage = new Image();

204     oBallImage.src = 'images/fireball.png';

205     oBallImage.onload = function() { }

206 

207     var oEnemyImage = new Image();

208     oEnemyImage.src = 'images/enemy.png';

209     oEnemyImage.onload = function() { }

210 

211     var oDragonImage = new Image();

212     oDragonImage.src = 'images/dragon.gif';

213     oDragonImage.onload = function() {

214         dragon = new Dragon(400, 300, dragonW, dragonH, oDragonImage);

215     }

216 

217     $('#scene').mousedown(function(e) { // 处理鼠标按下

218         var mouseX = e.layerX || 0;

219         var mouseY = e.layerY || 0;

220         if(e.originalEvent.layerX) { // jquery 1.7之后用下面这种方式

221             mouseX = e.originalEvent.layerX;

222             mouseY = e.originalEvent.layerY;

223         }

224 

225         bMouseDown = true;

226 

227         if (mouseX > dragon.x- dragon.w/2 && mouseX < dragon.x- dragon.w/2 +dragon.w &&

228             mouseY > dragon.y- dragon.h/2 && mouseY < dragon.y-dragon.h/2 +dragon.h) {

229 

230             dragon.bDrag = true;

231             dragon.x = mouseX;

232             dragon.y = mouseY;

233         }

234     });

235 

236     $('#scene').mousemove(function(e) { // 处理鼠标移动

237         var mouseX = e.layerX || 0;

238         var mouseY = e.layerY || 0;

239         if(e.originalEvent.layerX) {

240             mouseX = e.originalEvent.layerX;

241             mouseY = e.originalEvent.layerY;

242         }

243 

244         // 保存上次鼠标的位置

245         iLastMouseX = mouseX;

246         iLastMouseY = mouseY;

247 

248         // 执行龙的拖动

249         if (dragon.bDrag) {

250             dragon.x = mouseX;

251             dragon.y = mouseY;

252         }

253 

254         // 根据鼠标的位置,改变龙的方向

255         if (mouseX > dragon.x && Math.abs(mouseY-dragon.y) < dragon.w/2) {

256             iSprDir = 0;

257         } else if (mouseX < dragon.x && Math.abs(mouseY-dragon.y) < dragon.w/2) {

258             iSprDir = 4;

259         } else if (mouseY > dragon.y && Math.abs(mouseX-dragon.x) < dragon.h/2) {

260             iSprDir = 2;

261         } else if (mouseY < dragon.y && Math.abs(mouseX-dragon.x) < dragon.h/2) {

262             iSprDir = 6;

263         } else if (mouseY < dragon.y && mouseX < dragon.x) {

264             iSprDir = 5;

265         } else if (mouseY < dragon.y && mouseX > dragon.x) {

266             iSprDir = 7;

267         } else if (mouseY > dragon.y && mouseX < dragon.x) {

268             iSprDir = 3;

269         } else if (mouseY > dragon.y && mouseX > dragon.x) {

270             iSprDir = 1;

271         }

272     });

273 

274     $('#scene').mouseup(function(e) { // 处理鼠标释放事件

275         dragon.bDrag = false;

276         bMouseDown = false;

277 

278         // play dragon sound

279         dragonSound.currentTime = 0;

280         dragonSound.play();

281     });

282 

283     $(window).keydown(function(event){ // 按键1,开火

284         switch (event.keyCode) {

285             case 49: // '1' key

286                 balls.push(new Ball(dragon.x, dragon.y, 32, 32, iBallSpeed, oBallImage));

287 

288                 // play explode sound #1

289                 explodeSound.currentTime = 0;

290                 explodeSound.play();

291                 break;

292         }

293     });

294 

295     setInterval(drawScene, 30); // loop drawScene

296 

297     // 随机生产出敌人

298     var enTimer = null;

299     function addEnemy() {

300         clearInterval(enTimer);

301 

302         var randY = getRand(0, canvas.height - iEnemyH);

303         enemies.push(new Enemy(canvas.width, randY, iEnemyW, iEnemyH, - iEnemySpeed, oEnemyImage));

304 

305         var interval = getRand(5000, 10000);

306         enTimer = setInterval(addEnemy, interval); // loop drawScene

307     }

308     addEnemy();

309 });

在上面代码的开始处,我增加了两个新对象,球和敌人。每个对象都有他们自己的属性集(比如位置,大小,图片,速度),然后通过‘drawScene’方法来绘制他们,在该方法底部,你可以看到处理球和敌人的碰撞检测代码:

 1 // 检测是否击中敌人

 2     if (balls.length > 0) {

 3         for (var key in balls) {

 4             if (balls[key] != undefined) {

 5 

 6                 if (enemies.length > 0) {

 7                     for (var ekey in enemies) {

 8                         if (enemies[ekey] != undefined && balls[key] != undefined) {

 9                             if (balls[key].x + balls[key].w > enemies[ekey].x && balls[key].y + balls[key].h > enemies[ekey].y 

10                                 && balls[key].y < enemies[ekey].y + enemies[ekey].h) {

11                                 delete enemies[ekey];

12                                 delete balls[key];

13                                 iScore++;

14 

15                                 explodeSound2.currentTime = 0;

16                                 explodeSound2.play();

17                             }

18                         }

19                     }

20                 }

21             }

22         }

23     }
View Code

最后,我们通过下面的代码不定时间的增加敌人:

 1 // 随机生产出敌人

 2     var enTimer = null;

 3     function addEnemy() {

 4         clearInterval(enTimer);

 5 

 6         var randY = getRand(0, canvas.height - iEnemyH);

 7         enemies.push(new Enemy(canvas.width, randY, iEnemyW, iEnemyH, - iEnemySpeed, oEnemyImage));

 8 

 9         var interval = getRand(5000, 10000);

10         enTimer = setInterval(addEnemy, interval); // loop drawScene

11     }

12     addEnemy();

 

 第四步:Custom files

  • images/dragon.gif, images/enemy.png, images/fireball.png, images/hell.jpg

  • media/dragon.wav, media/explode1.wav, media/explosion.wav, media/laught.wav, media/wings.wav

上面所有的文件都在源码包里。

你可能感兴趣的:(html5)