我们继续这一系列文章,使用HTML5的canvas组件进行游戏开发。我们将要更新完善我们的第4课html5游戏制作入门系列教程(四)的游戏实例,并增加了火球,敌人和碰撞检测等功能模块。所以,现在我们的飞龙可以施放火球来杀死敌人(还有成绩统计)。现在,这个游戏的互动性更强了。你可以点击这里阅读这一系列教程的前一篇文章:html5游戏制作入门系列教程(六)。我们将基于之前的程序和代码进行开发。

这里有我们的演示和下载包:

在线演示 源码下载

好吧,下载所需文件,让我们开始编码!

步骤1:HTML
下面是基本的HTML代码:
这里是我演示的HTML,非常简单,对不对?

<!DOCTYPE html>
<html lang="en" >
<head>
<meta charset="utf-8" />
<title>html5游戏制作入门系列教程(七)</title>
<link href="css/main.css" rel="stylesheet" type="text/css" /><!--[if lt IE 9]>
<script src="http://html5shiv.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
<script src="js/jquery.js"></script>
<script src="js/script.js"></script>
</head>
<body>
<header tabindex="0">
<h2>html5游戏制作入门系列教程(七)</h2>
<a href="http://html5gamedev.org/?p=343" class="stuts">返回原文<span>HTML5GAME</span></a>
</header>
<div class="container">
<canvas id="scene" width="1000" height="600" tabindex="1"></canvas>
</div>
</body>
</html>

步骤2:CSS
下面是所使用的CSS样式表文件。
css/main.css
今天就不把css样式贴出来了,和以前的一样,没有什么特别之处。你可以在下载包里找到它。

步骤3:JS
js/script.js

// inner variables
var canvas, ctx;
var backgroundImage;
var iBgShiftX = 100;var dragon, enemy = null; // game objects
var balls = [];
var enemies = [];var dragonW = 75; // dragon width
var dragonH = 70; // dragon height
var iSprPos = 0; // initial sprite frame
var iSprDir = 0; // initial dragon direction
var iEnemyW = 128; // enemy width
var iEnemyH = 128; // enemy height
var iBallSpeed = 10; // initial ball speed
var iEnemySpeed = 2; // initial enemy speedvar dragonSound; // dragon sound
var wingsSound; // wings sound
var explodeSound, explodeSound2; // explode sounds
var laughtSound; // wings soundvar bMouseDown = false; // mouse down state
var iLastMouseX = 0;
var iLastMouseY = 0;
var iScore = 0;
// -------------------------------------------------------------// objects :
function Dragon(x, y, w, h, image) {
this.x = x;
this.y = y;
this.w = w;
this.h = h;
this.image = image;
this.bDrag = false;
}
function Ball(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;
}
// -------------------------------------------------------------
// get random number between X and Y
function getRand(x, y) {
return Math.floor(Math.random()*y)+x;
}// draw functions :
function drawScene() { // main drawScene function
ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height); // clear canvas// draw background
iBgShiftX += 4;
if (iBgShiftX >= 1045) {
iBgShiftX = 0;
}
ctx.drawImage(backgroundImage, 0 + iBgShiftX, 0, 1000, 940, 0, 0, 1000, 600);// update sprite positions
iSprPos++;
if (iSprPos >= 9) {
iSprPos = 0;
}// in case of mouse down - move dragon more close to our mouse
if (bMouseDown) {
if (iLastMouseX > dragon.x) {
dragon.x += 5;
}
if (iLastMouseY > dragon.y) {
dragon.y += 5;
}
if (iLastMouseX < dragon.x) {
dragon.x -= 5;
}
if (iLastMouseY < dragon.y) {
dragon.y -= 5;
}
}// draw dragon
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);// draw fireballs
if (balls.length > 0) {
for (var key in balls) {
if (balls[key] != undefined) {
ctx.drawImage(balls[key].image, balls[key].x, balls[key].y);
balls[key].x += balls[key].speed;if (balls[key].x > canvas.width) {
delete balls[key];
}
}
}
}// draw enemies
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].x += enemies[ekey].speed;if (enemies[ekey].x < - iEnemyW) {
delete enemies[ekey];// play laught sound
laughtSound.currentTime = 0;
laughtSound.play();
}
}
}
}// collision detection
if (balls.length > 0) {
for (var key in balls) {
if (balls[key] != undefined) {if (enemies.length > 0) {
for (var ekey in enemies) {
if (enemies[ekey] != undefined && balls[key] != undefined) {
if (balls[key].x + balls[key].w > enemies[ekey].x && balls[key].y + balls[key].h > enemies[ekey].y && balls[key].y < enemies[ekey].y + enemies[ekey].h) {
delete enemies[ekey];
delete balls[key];
iScore++;// play explode sound #2
explodeSound2.currentTime = 0;
explodeSound2.play();
}
}
}
}
}
}
}// draw score
ctx.font = '16px Verdana';
ctx.fillStyle = '#fff';
ctx.fillText('Score: ' + iScore * 10, 900, 580);
ctx.fillText('Plese click "1" to cast fireball', 100, 580);}// -------------------------------------------------------------// initialization
$(function(){
canvas = document.getElementById('scene');
ctx = canvas.getContext('2d');var width = canvas.width;
var height = canvas.height;// load background image
backgroundImage = new Image();
backgroundImage.src = 'images/hell.jpg';
backgroundImage.onload = function() {
}
backgroundImage.onerror = function() {
console.log('Error loading the background image.');
}// 'Dragon' music init
dragonSound = new Audio('media/dragon.wav');
dragonSound.volume = 0.9;// 'Laught' music init
laughtSound = new Audio('media/laught.wav');
laughtSound.volume = 0.9;// 'Explode' music inits
explodeSound = new Audio('media/explode1.wav');
explodeSound.volume = 0.9;
explodeSound2 = new Audio('media/explosion.wav');
explodeSound2.volume = 0.9;// 'Wings' music init
wingsSound = new Audio('media/wings.wav');
wingsSound.volume = 0.9;
wingsSound.addEventListener('ended', function() { // loop wings sound
this.currentTime = 0;
this.play();
}, false);
wingsSound.play();// initialization of empty ball
var oBallImage = new Image();
oBallImage.src = 'images/fireball.png';
oBallImage.onload = function() { }// initialization of empty enemy
var oEnemyImage = new Image();
oEnemyImage.src = 'images/enemy.png';
oEnemyImage.onload = function() { }// initialization of dragon
var oDragonImage = new Image();
oDragonImage.src = 'images/dragon.gif';
oDragonImage.onload = function() {
dragon = new Dragon(400, 300, dragonW, dragonH, oDragonImage);
}$('#scene').mousedown(function(e) { // binding mousedown event (for dragging)
var mouseX = e.layerX || 0;
var mouseY = e.layerY || 0;
if(e.originalEvent.layerX) { // changes for jquery 1.7
mouseX = e.originalEvent.layerX;
mouseY = e.originalEvent.layerY;
}bMouseDown = true;if (mouseX > dragon.x- dragon.w/2 && mouseX < dragon.x- dragon.w/2 +dragon.w &&
mouseY > dragon.y- dragon.h/2 && mouseY < dragon.y-dragon.h/2 +dragon.h) {dragon.bDrag = true;
dragon.x = mouseX;
dragon.y = mouseY;
}
});$('#scene').mousemove(function(e) { // binding mousemove event
var mouseX = e.layerX || 0;
var mouseY = e.layerY || 0;
if(e.originalEvent.layerX) {
mouseX = e.originalEvent.layerX;
mouseY = e.originalEvent.layerY;
}// saving last coordinates
iLastMouseX = mouseX;
iLastMouseY = mouseY;// perform dragon dragging
if (dragon.bDrag) {
dragon.x = mouseX;
dragon.y = mouseY;
}// change direction of dragon (depends on mouse position)
if (mouseX > dragon.x && Math.abs(mouseY-dragon.y) < dragon.w/2) {
iSprDir = 0;
} else if (mouseX < dragon.x && Math.abs(mouseY-dragon.y) < dragon.w/2) {
iSprDir = 4;
} else if (mouseY > dragon.y && Math.abs(mouseX-dragon.x) < dragon.h/2) {
iSprDir = 2;
} else if (mouseY < dragon.y && Math.abs(mouseX-dragon.x) < dragon.h/2) {
iSprDir = 6;
} else if (mouseY < dragon.y && mouseX < dragon.x) {
iSprDir = 5;
} else if (mouseY < dragon.y && mouseX > dragon.x) {
iSprDir = 7;
} else if (mouseY > dragon.y && mouseX < dragon.x) {
iSprDir = 3;
} else if (mouseY > dragon.y && mouseX > dragon.x) {
iSprDir = 1;
}
});$('#scene').mouseup(function(e) { //绑定鼠标键松开事件
dragon.bDrag = false;
bMouseDown = false;// play dragon sound
dragonSound.currentTime = 0;
dragonSound.play();
});$(window).keydown(function(event){ // 键盘事件处理
switch (event.keyCode) {
case 49: // '1' key
balls.push(new Ball(dragon.x, dragon.y, 32, 32, iBallSpeed, oBallImage));// 播放爆炸声音片段1 #1
explodeSound.currentTime = 0;
explodeSound.play();
break;
}
});setInterval(drawScene, 30); // 循环渲染场景// generate enemies randomly
var enTimer = null;
function addEnemy() {
clearInterval(enTimer);var randY = getRand(0, canvas.height - iEnemyH);
enemies.push(new Enemy(canvas.width, randY, iEnemyW, iEnemyH, - iEnemySpeed, oEnemyImage));var interval = getRand(5000, 10000);
enTimer = setInterval(addEnemy, interval); // 循环渲染场景(添加敌人)
}
addEnemy();
});
在一开始,我增加了两个新的对象:火球和敌人。每个对象都有自己的属性集(如位置,大小,形象,速度)。之后,我加入我们的drawScene()函数,负责绘制火球和敌人。另外,在这个函数的底部,你可以看到碰撞检测方法:
// collision detection
if (balls.length > 0) {
for (var key in balls) {
if (balls[key] != undefined) {if (enemies.length > 0) {
for (var ekey in enemies) {
if (enemies[ekey] != undefined && balls[key] != undefined) {
if (balls[key].x + balls[key].w > enemies[ekey].x && balls[key].y + balls[key].h > enemies[ekey].y && balls[key].y < enemies[ekey].y + enemies[ekey].h) {
delete enemies[ekey];
delete balls[key];
iScore++;// 播放爆炸声音片段#2
explodeSound2.currentTime = 0;
explodeSound2.play();
}
}
}
}
}
}
}
 

最后,我们必须定期添加我们的敌人(随机):

// 产生随机敌人
var enTimer = null;
function addEnemy() {
clearInterval(enTimer);var randY = getRand(0, canvas.height - iEnemyH);
enemies.push(new Enemy(canvas.width, randY, iEnemyW, iEnemyH, - iEnemySpeed, oEnemyImage));var interval = getRand(5000, 10000);
enTimer = setInterval(addEnemy, interval); // 循环绘制场景(添加敌人)
}
addEnemy();

步骤4:资源文件
游戏制作需要使用如下的游戏资源文件,包括图片和声音文件,这些你都可以在下载包中找到。
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游戏开发者社区 » html5游戏制作入门系列教程(七)

html5游戏制作入门系列教程(七)相关推荐

  1. html5游戏制作入门系列教程(八)

    今天,我已经准备了一个新的游戏 – SkyWalker.基本上 – 这是用飞飞行模拟射击类游戏.我们的目标到达终点线.这个游戏还有其它一些特点,例如使用飞机运动动画和爆炸动画,多按键处理(例如同时移动 ...

  2. html5游戏制作入门系列教程(六)

    我们继续这一系列文章,使用HTML5的canvas组件进行游戏开发.今天,我们将创建我们的第一个完整的游戏 – 打砖块.在这一课中,我会告诉你如何检测基本的碰撞和HTML5的本地存储.您可以使用鼠标和 ...

  3. html5游戏制作入门系列教程(五)

    我们继续这一系列文章,使用HTML5的canvas组件进行游戏开发.今天,这是相当完整的游戏例子 – 它会回顾经典的旧电脑游戏 – 坦克大战.我会教你使用阵列地图并教你如何检测活动对象(坦克)与环境( ...

  4. html5游戏制作入门系列教程(四)

    今天,我们继续一系列文章,使用HTML5的canvas组件进行游戏开发.今天我们要学习下元素:声音控制与动画.在我们的演示中,你会 看到一个飞龙.我们会听到持续的翅膀拍打的声音(我们将循环这个声音), ...

  5. html5游戏制作入门系列教程(三)

    今天,我们继续一系列文章,使用HTML5的canvas组件进行游戏开发.接下来,我们将开始学习如何添加动画以及一些更有趣的功能.我 们的演示将包括一艘太空船飞越时空,并使用一个新的游戏元素 – 对话框 ...

  6. html5游戏制作入门系列教程(二)

    今天,我们继续html5游戏制作入门系列的系列文章.今天,我们将继续基础知识(也许甚至是高级技巧的基础).我要告诉你如何具有渐变颜色填充对象,绘制文本,使用自定义的字体绘制文本,基本的动画,以及最重要 ...

  7. html5游戏制作入门系列教程(一)

    从今天开始,我们将开始HTML5游戏开发一系列的文章.在我们的第一篇文章中,我们将讲解在画布canvas上的基础工作,创建简单的对象,填充和事件处理程序.另外,要注意在这个阶段中,我们不会立即学习We ...

  8. 快节奏多人在线游戏网络入门系列教程(1):简介

    简介 该系列教程主要讨论快节奏多人在线游戏的网络相关的技术和算法.这是该系列教程的第一章,如果你对多人在线游戏有一定了解,可以跳过本章. 开发任何一款游戏都是一个挑战性的任务.而多人在线游戏增加了更多 ...

  9. 快节奏多人在线游戏网络入门系列教程(2):客户端预测与服务器协调

    简介 在上一篇文章中,我们简单介绍了权威服务器的体系.客户端发送交互信息给服务器,服务器周期性的更新游戏状态,然后返回游戏状态给客户端. 这个简单体系会导致用户发送命令时和屏幕渲染响应之间的延迟.产生 ...

最新文章

  1. 宁波Uber优步司机奖励政策(1月18日~1月24日)
  2. 【OpenCV3】平滑处理详解
  3. 洛谷 - P2324 - 骑士精神 - A*搜索
  4. sony z2 android 5.0,索尼Xperia Z2 5.0 root教程_索尼Z2获取5.0系统的root
  5. adb.exe可能被其他程序关闭_如何开启或关闭MacBook
  6. java datasource使用_java Datasource,数据库连接池
  7. web项目报404一直找不到图片(路径绝对正确)
  8. python实现网页截图功能——学习篇(01)
  9. 脉冲宽度调制pdm_脉冲宽度调制,脉宽调制
  10. Http 常见的 Headers
  11. springboot整合RabbitMQ启动报错:An unexpected connection driver error occured,Socket Closed
  12. python导入mysqldb_Python导入MySQLdb库
  13. 台式关掉计算机不断网,笔记本电脑在关掉屏幕后不断网设置方法
  14. 【Zookeeper】查看注册信息命令
  15. Java Map集合的详解
  16. 力扣(142.1002)补9.17
  17. 微信小程序注册入口及流程(完整版教程)
  18. 2022上半年系统集成项目管理师客观题参考答题解析(1)
  19. php libevent 问题,安装讯搜xunsearch libevent时遇到的问题,如何解决?
  20. C Prime Plus 第二章 C语言概述

热门文章

  1. 图论 —— 最短路 —— Bellman-Ford 算法与 SPFA
  2. 暑期训练日志----2018.8.15
  3. 单词翻转(信息学奥赛一本通-T1144)
  4. linux jobs继续运行,Linux jobs等前后台运行命令详解
  5. python判断文件是否存在 中文_python如何判断文件是否存在
  6. kubernetes怎么读_Kubernetes之有状态应用实践-搭建MySQL集群
  7. __call__方法解析
  8. 【tensorflow】张量tensor--数据容器(把它想象成一个数字的水桶)
  9. Flink java.lang.NoClassDefFoundError: org/apache/flink/api/common/functions/FlatMapFunction
  10. c语言答辩题目,中学数学《线的认识》答辩题目与解析