HTML5游戏开发系列教程10(译)
原文地址:http://www.script-tutorials.com/html5-game-development-lesson-10/
最后我们将继续使用canvas来进行HTML5游戏开发系列的文章。今天我准备了一个新游戏--SkyWalker。这游戏基本上算是一个射击模拟类型的游戏(有飞机和敌人)。我们的目标是到达终点线。该游戏有几个关键的特征:使用了精灵来处理飞机和爆炸,可以按下多个按键(比如你可以移动飞机的同时发射子弹),a certain level length,增强的碰撞检测(敌人可以撞击飞机),飞机的生命值和获得的分数。
之前的翻译文章可以点击这里:http://www.cnblogs.com/pigzhu/p/3281537.html
第一步:HTML
和往常一样,我们有个基本的html文件:
- <!DOCTYPE html>
- <html lang="en" >
- <head>
- <meta charset="utf-8" />
- <title>HTML5 Game Development - Lesson 10 (SkyWalker) | Script Tutorials</title>
- <link href="css/main.css" rel="stylesheet" type="text/css" />
- <script src="js/jquery-2.0.0.min.js"></script>
- <script src="js/script.js"></script>
- </head>
- <body>
- <header tabindex="0">
- <h2>HTML5 Game Development - Lesson 10</h2>
- <a href="http://www.script-tutorials.com/html5-game-development-lesson-10/" class="stuts">Back to original tutorial on <span>Script Tutorials</span></a>
- </header>
- <div class="container">
- <canvas id="scene" width="700" height="700" tabindex="1"></canvas>
- </div>
- </body>
- </html>
第二步:JS
现在,请在文件夹js中创建一个空文件:“script.js”,并把下面的这些代码粘贴到里面去。我将解释主要的功能。
- //内部变量
- var canvas, ctx;
- //各种图片
- var backgroundImage;
- var oRocketImage;
- var oExplosionImage;
- var introImage;
- var oEnemyImage;
- var iBgShiftY = 9300;
- var bPause = true; //游戏是否暂停
- var plane = null; //飞机
- var rockets = []; //子弹对象的数组
- var enemies = []; //敌人对象的数组
- var explosions = []; //爆炸对象的数组
- var planeW = 200; //飞机的宽度
- var planeH = 110; //飞机的高度
- var iSprPos = 2; //飞机初始帧的位置
- var iMoveDir = 0; //移动的方向
- var iEnemyW = 128; //敌人的宽度
- var iEnemyH = 128; //敌人的高度
- var iRocketSpeed =10; //子弹的速度
- var iEnemySpeed = 5; //敌人的速度
- var pressedKeys = []; //按键的序列
- var iScore = 0; //总得分
- var iLife = 100; //生命值
- var iDamage = 10; //每次敌人碰到飞机的损耗值
- var enTimer = null; //产生敌人的定时器
- function Plane(x, y, w, h, image) {
- this.x = x;
- this.y = y;
- this.w = w;
- this.h = h;
- this.image = image;
- this.bDrag = false;
- }
- function Rocket(x, y, w, h, speed, image) {
- this.x = x;
- this.y = y;
- this.w = w;
- this.h = h;
- this.speed = speed;
- this.image = image;
- }
- function Enemy(x, y, w, h, speed, image) {
- this.x = x;
- this.y = y;
- this.w = w;
- this.h = h;
- this.speed = speed;
- this.image = image;
- }
- function Explosion(x, y, w, h, sprite, image) {
- this.x = x;
- this.y = y;
- this.w = w;
- this.h = h;
- this.sprite = sprite;
- this.image = image;
- }
- //得到位于x和y之间的随机数
- function getRand(x, y) {
- return Math.floor(Math.random() * y) + x;
- }
- //显示游戏介绍界面
- function displayIntro() {
- ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
- ctx.drawImage(introImage, 0, 0, 700, 700);
- }
- //绘制主要的场景
- function drawScene() {
- if (! bPause) {
- iBgShiftY -= 2; //主背景向下移动
- if (iBgShiftY < 5) {
- bPause = true;
- //绘制分数
- ctx.font = '40px Verdana';
- ctx.fillStyle = '#fff';
- ctx.fillText('Finish, your score: ' + iSore * 10 + ' points', 50, 200);
- return;
- }
- //处理按下的建
- processPressedKeys();
- //清除整个画布
- ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
- //通过剪切图片绘制背景
- ctx.drawImage(backgroundImage, 0, 0 + iBgShiftY, 700, 700, 0, 0, 700, 700);
- //绘制飞机
- ctx.drawImage(plane.image, iSprPos * plane.w, 0, plane.w, plane.h,
- plane.x - plane.w / 2, plane.y - plane.h / 2, plane.w, plane.h);
- //绘制子弹
- if (rockets.length > 0) {
- for (var key in rockets) {
- if (rockets[key] != undefined) {
- ctx.drawImage(rockets[key].image, rockets[key].x, rockets[key].y);
- rockets[key].y -= rockets[key].speed;
- if (rockets[key].y < 0) { //如果子弹飞出界面,删除掉
- delete rockets[key];
- }
- }
- }
- }
- //绘制爆炸
- if (explosions.length > 0) {
- for (var key in explosions) {
- ctx.drawImage(explosions[key].image, explosions[key].sprite * explosions[key].w, 0, explosions[key].w, explosions[key].h,
- explosions[key].x - explosions[key].w / 2, explosions[key].y - explosions[key].h / 2,
- explosions[key].w, explosions[key].h);
- explosions[key].sprite++;
- if (explosions[key].sprite > 10) { //如果爆炸播放完,则删除掉
- delete explosions[key];
- }
- }
- }
- //绘制敌人
- if (enemies.length > 0) {
- for (var ekey in enemies) {
- if (enemies[ekey] != undefined) {
- ctx.drawImage(enemies[ekey].image, enemies[ekey].x, enemies[ekey].y);
- enemies[ekey].y -= enemies[ekey].speed;
- }
- if (enemies[ekey].y > canvas.height) { //如果敌人飞出界面,则删除掉
- delete enemies;
- }
- }
- }
- //处理各种碰撞
- if (enemies.length > 0) {
- for (var ekey in enemies) {
- if (enemies[ekey] != undefined) {
- //子弹打中敌人
- if (rockets.length > 0) {
- for (var key in rockets) {
- if (rockets[key] != undefined && enemies[ekey] != undefined) {
- if (rockets[key].y < enemies[ekey].y + enemies[ekey].h / 2
- && rockets[key].x > enemies[ekey].x
- && rockets[key].x + rockets[key].w < enemies[ekey].x + enemies[ekey].w) {
- explosions.push(new Explosion(enemies[ekey].x + enemies[ekey].w / 2, enemies[ekey].y + enemies[ekey].h / 2,
- 120, 120, 0, oExplosionImage));
- delete enemies[ekey];
- delete rockets[key];
- iScore++;
- }
- }
- }
- }
- //敌人打中飞机
- if (enemies[ekey] != undefined) {
- if (plane.y - plane.h / 2 < enemies[ekey].y + enemies[ekey].h / 2
- && plane.x - plane.w / 2 < enemies[ekey].x + enemies[ekey].w
- && plane.x + plane.w / 2 > enemies[ekey].x) {
- explosions.push(new Explosion(enemies[ekey].x + enemies[ekey].w / 2, enemies[ekey].y + enemies[ekey].h / 2,
- 120, 120, 0, oExplosionImage));
- delete enemies[ekey];
- iLife -= iDamage;
- if (iLife <= 0) { //游戏结束
- bPause = true;
- ctx.font = '38px Verdana';
- ctx.fillStyle = '#fff';
- ctx.fillText('Game voer, your socre: ' + iScore * 10 + ' points', 25, 200);
- return;
- }
- }
- }
- }
- }
- }
- //即时显示分数和生命值
- ctx.font = '14px Verdana';
- ctx.fillStyle = '#fff';
- ctx.fillText('life: ' + iLife + ' / 100', 50, 660);
- ctx.fillText('Score: ' + iScore * 10, 50, 680);
- }
- }
- //处理各种按键事件
- function processPressedKeys() {
- if (pressedKeys[37] != undefined) {
- if (iSprPos > 0) {
- iSprPos--;
- iMoveDir = -7;
- }
- if (plane.x - plane.w / 2 > 10) {
- plane.x += iMoveDir;
- }
- } else if (pressedKeys[39] != undefined) {
- if (iSprPos < 4) {
- iSprPos++;
- iMoveDir = 7;
- }
- if (plane.x + plane.w / 2 < canvas.width - 10) {
- plane.x += iMoveDir;
- }
- }
- }
- //不定时间的增加敌人
- function addEnemy() {
- clearInterval(enTimer);
- var randX = getRand(0, canvas.height - iEnemyH);
- enemies.push(new Enemy(randX, 0, iEnemyW, iEnemyH, -iEnemySpeed, oEnemyImage));
- var interval = getRand(1000, 4000);
- enTimer = setInterval(addEnemy, interval);
- }
- // 主初始化
- $(function() {
- canvas = document.getElementById('scene');
- ctx = canvas.getContext('2d');
- //加载背景图片
- backgroundImage = new Image();
- backgroundImage.src = 'images/levelmap.jpg';
- backgroundImage.onload = function() {}
- backgroundImage.onerror = function() {
- console.log('Error loading the background image.');
- }
- //初始化介绍图片
- introImage = new Image();
- introImage.src = 'images/intro.jpg';
- oRocketImage = new Image();
- oRocketImage.src = 'images/rocket.png';
- oRocketImage.onload = function(){}
- oExplosionImage = new Image();
- oExplosionImage.src = 'images/explosion.png';
- oExplosionImage.onload = function() {}
- oEnemyImage = new Image();
- oEnemyImage.src = 'images/enemy.png';
- oEnemyImage.onload = function() {}
- var oPlaneImage = new Image();
- oPlaneImage.src = 'images/plane.png';
- oPlaneImage.onload = function() {
- plane = new Plane(canvas.width / 2, canvas.height - 100, planeW, planeH, oPlaneImage);
- }
- $(window).keydown(function(evt) { //按下事件处理
- var pk = pressedKeys[evt.keyCode];
- if (!pk) {
- pressedKeys[evt.keyCode] = 1;
- }
- if (bPause && evt.keyCode == 13) { //enter键 开始游戏
- bPause = false;
- setInterval(drawScene , 30);
- addEnemy();
- }
- });
- $(window).keyup(function(evt) { //键释放事件处理
- var pk = pressedKeys[evt.keyCode];
- if (pk) {
- delete pressedKeys[evt.keyCode];
- }
- if (evt.keyCode == 65) { //'A'键发射子弹
- rockets.push(new Rocket(plane.x - 16, plane.y - plane.h, 32, 32, iRocketSpeed, oRocketImage));
- }
- if (evt.keyCode ==37 || evt.keyCode == 39) {
- //左右移动 37 左 39 右 但移动完之后,飞机恢复正常状态
- if (iSprPos > 2) {
- for (var i = iSprPos; i >= 2; i--) {
- iSprPos = i;
- iMoveDir = 0;
- }
- } else {
- for (var i = iSprPos; i <= 2; i++) {
- iSprPos = i;
- iMoveDir = 0;
- }
- }
- }
- });
- introImage.onload = function() {
- displayIntro();
- }
- });
在主初始化代码中,加载了所有必需的图片资源(level map, 介绍图片,子弹,爆炸,敌人和飞机)。然后,我们使用了数组来处理多个按键事件(在我们渲染主场景的时候,将会使用这个数组来操作我们的飞机),最后,介绍页被加载--显示界面图片。下面是一个重要的代码片段--怎样处理多个按键,请看下面代码:
- var pressedKeys = []; //按键的序列
- $(window).keydown(function (evt){ //鼠标按下事件处理
- var pk = pressedKeys[evt.keyCode];
- if (! pk) {
- pressedKeys[evt.keyCode] = 1; // 把按下的键添加的按键序列中
- }
- });
- $(window).keyup(function (evt) { // 鼠标释放事件处理
- var pk = pressedKeys[evt.keyCode];
- if (pk) {
- delete pressedKeys[evt.keyCode]; // 从按键序列中删除
- }
- });
这个技术允许我们操作多个按键,在渲染我们主场景时,我们绘制的对象有:背景,飞机,子弹,敌人和爆炸。一旦我们击中敌人,将会在敌人的位置处绘制出爆炸。最后我们的对手是有攻击力的,当他们碰到飞机时,他们会爆炸,同时对飞机造成损伤。如果我们飞机的生命值小于0,则游戏结束。为了实现碰撞和爆炸,我使用了下面的代码:
- if (plane.y - plane.h/2 < enemies[ekey].y + enemies[ekey].h/2 && plane.x - plane.w/2 < enemies[ekey].x + enemies[ekey].w && plane.x + plane.w/2 > enemies[ekey].x) {
- explosions.push(new Explosion(enemies[ekey].x + enemies[ekey].w / 2, enemies[ekey].y + enemies[ekey].h / 2, 120, 120, 0, oExplosionImage));
- // 删除敌人,并计算损伤
- delete enemies[ekey];
- iLife -= iDamage;
- if (iLife <= 0) { // 游戏结束
- bPause = true;
- // 绘制分数
- ctx.font = '38px Verdana';
- ctx.fillStyle = '#fff';
- ctx.fillText('Game over, your score: ' + iScore * 10 + ' points', 25, 200);
- return;
- }
- }
第三步:Custom graphics
enemy.png, explosion.png, intro.jpg, levelmap.jpg, plane.png, rocket.png
上面所有的图片都在源码包里。
结论
你喜欢我们的新SkyWalker游戏吗? 我非常乐意看见你的谢意和评论。好运!
HTML5游戏开发系列教程10(译)的更多相关文章
- HTML5游戏开发系列教程7(译)
原文地址:http://www.script-tutorials.com/html5-game-development-lesson-7/ 今天我们将完成我们第一个完整的游戏--打砖块.这次教程中,将 ...
- HTML5游戏开发系列教程6(译)
原文地址:http://www.script-tutorials.com/html5-game-development-lesson-6/ 这是我们最新一篇HTML5游戏开发系列文章.我们将继续使用c ...
- HTML5游戏开发系列教程5(译)
原文地址:http://www.script-tutorials.com/html5-game-development-lesson-5/ 最终我决定准备下一篇游戏开发系列的文章,我们将继续使用can ...
- HTML5游戏开发系列教程4(译)
原文地址:http://www.script-tutorials.com/html5-game-development-lesson-4/ 这篇文章是我们继续使用canvas来进行HTML5游戏开发系 ...
- HTML5游戏开发系列教程8(译)
原文地址:http://www.script-tutorials.com/html5-game-development-lesson-8/ 这是我们最新一篇HTML5游戏开发系列文章.我们将继续使用c ...
- HTML5游戏开发系列教程9(译)
原文地址:http://www.script-tutorials.com/html5-game-development-lesson-9/ 今天我们将继续使用canvas来进行HTML5游戏开发系列的 ...
- cocos2d-x游戏开发系列教程-前言
cocos2d-x游戏开发前景: 最近企业对于Cocos2D-X开发人才的用人需求很大,而且所提供的薪资相当可观. 为满足广大向往游戏开发行业同学的需求,特推出适合新手的Cocos2D-X手游开发教程 ...
- unity3D实际的原始视频游戏开发系列讲座10它《战斗:外来入侵》在第一季度游戏开发
解说文件夹 <保卫战:异形入侵>游戏开发 第一讲 游戏演示和资源的介绍 第二讲 "异形"怪物的实现 第三讲 "异形"怪物生命值的体现 第四讲 ...
- cocos2d-x游戏开发系列教程-超级玛丽07-CMGameMap
背景 在上一篇博客中,我们提到CMGameScene,但是CMGameScene只是个框架,实际担任游戏逻辑的是CMGameMap类,这个博文就来了解下CMGameMap 头文件 class CMGa ...
随机推荐
- MySQL<多表操作>
多表操作 外键 什么是外键 外键是指引用另一个表中的一列或多列,被引用的列应该具有主键约束或唯一性约束. 外键用于建立和加强两个表数据之间的链接. 为表添加外键约束 想要真正连接两个表的数据,就需要为 ...
- 如何配置samba 要求共享文件夹public
第一步:在根下执行:mkdir /public 修改下权限:chmod 777 /public第二步:vi /etc/samba/smb.conf修改如下配置:修改security = user为se ...
- beginUpdates和endUpdates-实现UITableView的动画块
我们在做UITableView的修改,删除,选择时,需要对UITableView进行一系列的动作操作. 这样,我们就会用到 [tableView beginUpdates]; if (newCount ...
- UVa 673 Parentheses Balance (stack)
题目描述 : 判断字符串是不是符合正确的表达式形式. 要点 : 考虑字符串为空的时候,用getline输入,每一次判断后如果为No则要清空栈.对称思想. 注意输入格式. 代码: #include &l ...
- [黑金原创教程] FPGA那些事儿《数学篇》- CORDIC 算法
简介 一本为完善<设计篇>的书,教你CORDIC算法以及定点数等,内容请看目录. 贴士 这本教程难度略高,请先用<时序篇>垫底. 目录 Experiment 01:认识CORD ...
- Object.prototype.toString()
Object.prototype.toString()方法返回一个代表该对象的字符串. var o = new Object(); o.toString(); //"[object Obje ...
- Lucene构建索引时的一些概念和索引构建的过程
在搜索文档内容之前要做的事情就是对从各种不同来源(网页,数据库,电子邮件等)的文档进行索引,索引的过程就是对内容进行提取,规范化(通过对内容进行建模来实现),然后存储. 在索引的过程中有几个基本的概念 ...
- [IIS] IIS Framework "aspnet_regiis.exe" 注册
Error:处理程序“PageHandlerFactory-Integrated”在其模块列表中有一个错误模块“
- ios UITableView默认选中第一行
NSIndexPath *ip = [NSIndexPath indexPathForRow:0inSection:0]; [titleTableViewselectRowAtIndexPath:ip ...
- windows MySQL5.7.9免安装版配置方法
1. 解压MySQL压缩包 将下载的MySQL压缩包解压到自定义目录下,我的解压目录是: "D:\Program Files\mysql-5.7.9-win32" ...