手机
当前位置:查字典教程网 >编程开发 >Javascript教程 >javascript 模拟坦克大战游戏(html5版)附源码下载
javascript 模拟坦克大战游戏(html5版)附源码下载
摘要:一、总结关键点和遇到的问题1.javascript中的继承,最好父类只提供方法共享,属性写到各自子类中,避免父类和子类的构造函数混杂。2.p...

一、总结关键点和遇到的问题

1.javascript中的继承,最好父类只提供方法共享,属性写到各自子类中,避免父类和子类的构造函数混杂。

2.prototype模拟继承的代码,应写在所有方法定义之前,否则原型对象被改变,方法就变成了未定义,如:

复制代码 代码如下:

Hero.prototype = new Tank (0, 0, 0);

Hero.prototype.constructor = Hero;

Hero.prototype.addLife = function(){

this.lifetimes++;

document.querySelector("#life").innerHTML = hero.lifetimes;

}

3.canvas画图形时,除了画矩形,其他的都要加上 ctx.beginPath();、ctx.closePath();,否则会出现意想不到的错误。

4.concat函数可以合并数组,或者是元素返回一个新的数组

5.Image的src属性赋值后就会加载图片,但如果没有加载完毕就画图片,会导致失效,所以使用onload事件处理

6.扩展Array功能,删除指定元素

复制代码 代码如下:

//扩展 删除指定元素

Array.prototype.deleteElement = function (obj) {

if (obj) {

for (var i = 0; i < this.length; i++) {

if (this[i] === obj) {

this.splice (i, 1);

}

}

}

}

7.定时器设置,setInterval(“fun”,1000)方法的第一个参数,可以是字符串,如"hero.say()",类似eval会去执行这串代码,所以它可以给函数带上参数,并且也指定了这个函数的运行上下文。但如果传入是函数的句柄,则不能带参数,并且不能指定上下文,除了第一种方式解决外,我用了闭包来解决这个问题

复制代码 代码如下:

//定时器,自行运动

this.timer = setInterval ((function (context) {

return function () {

Bullet.prototype.move.call (context)

}

}) (this), 30);

我保存了当前的执行环境,并调用call方法手动执行。

8.方法的功能设计,除了功能外,应该包括执行此功能的条件检测,如move,就应该包括什么情况下可以移动,移动到什么地方就不能移动了。此检测不应该放在外部。

9.写代码时不应该去想设计或者优化的问题,先实现功能,再谈优化,或者先设计再实现。思路要清晰,别混乱,着重于一点。

10.javascript中没有sleep的功能,可以创建一个变量作为缓冲,来达到间隔执行的目的

二、代码实现

1.本程序分为Bomb.js,Bullet.js,Draw.js,Tank.js,index.html,img,music,

2.最终效果

javascript 模拟坦克大战游戏(html5版)附源码下载1

javascript 模拟坦克大战游戏(html5版)附源码下载2

javascript 模拟坦克大战游戏(html5版)附源码下载3

3.代码

1.index.html

复制代码 代码如下:

<!DOCTYPE html>

<html>

<head>

<title></title>

<meta charset="utf-8">

<style type="text/css">

body {

font: 14px "sans-serif"

}

#Map {

background-color: #000000;

}

.show {

float: left

}

#guide {

float: left;

width: 200px;

height: 390px;

margin-left: 5px;

background: #CCCCCC;

padding: 5px;

}

</style>

<script type="text/javascript" src="Tank.js"></script>

<script type="text/javascript" src="Bullet.js"></script>

<script type="text/javascript" src="Bomb.js"></script>

<script type="text/javascript" src="Draw.js"></script>

<script type="text/javascript">

window.onload = function () {

//画布信息

width = document.getElementById ('Map').width;

height = document.getElementById ('Map').height;

ctx = document.getElementById ('Map').getContext ('2d');

//初始页面

var starImg = new Image ();

starImg.src = "img/star.jpg";

starImg.onload = function () {

ctx.drawImage (starImg, 0, 0, width, height);

}

//键盘监听 回车开始游戏

document.body.onkeydown = function () {

var keycode = event.keyCode;

switch (keycode) {

case 13:

//初始化参数

init ()

//刷新页面

setInterval (draw, 30);

document.body.onkeydown = gameControl;

break;

}

}

}

function init () {

//玩家和电脑

hero = new Hero (100, 300, 0);

enemys = [];

for (var i = 0; i < 3; i++) {

enemys.push (new Enemy (100 + i * 50, 0, 2));

}

//合并数组

allTank = enemys.concat (hero);

//炸弹

Bombs = [];

im = new Image ();

im2 = new Image ();

im3 = new Image ();

im.src = "img/bomb_3.gif";

im2.src = "img/bomb_2.gif";

im3.src = "img/bomb_1.gif";

}

function gameControl () {

var keycode = event.keyCode;

switch (keycode) {

case 65:

hero.moveLeft ();

break;//左

case 83:

hero.moveDown ();

break;//下

case 87:

hero.moveUp ();

break;//上

case 68:

hero.moveRight ();

break;//右

case 74:

hero.shot ();

break;

case 49:

hero.addLife ()

break;

}

}

//扩展 删除指定元素

Array.prototype.deleteElement = function (obj) {

if (obj) {

for (var i = 0; i < this.length; i++) {

if (this[i] === obj) {

this.splice (i, 1);

}

}

}

}

</script>

</head>

<body>

<div>

<canvas id="Map" width="500px" height="400px">

</canvas>

<audio id="music" autoplay="autoplay">

<source src="music/111.wav">

</audio>

</div>

<div id="guide">

<p>按下回车键开始游戏</p>

<p>按下1键增加生命,默认是1</p>

<p>剩余生命数 :<label id="life">1</label></p>

<div id="data">

</div>

</div>

</body>

</html>

2.Draw.js

复制代码 代码如下:

/**

* Created by Alane on 14-3-18.

*/

function draw(){

//检测子弹和坦克生死

checkDead();

//清空画布

ctx.clearRect(0,0,500,400);

//画玩家

if(!hero.isdead){

drawTank(hero);

}else{

hero.cutLife();

}

//画敌人坦克

for (var i = 0; i < enemys.length; i++) {

drawTank(enemys[i]);

}

//画敌人子弹

for(var j=0;j<enemys.length;j++){

var temp = enemys[j].bulletsList;

for (var i = 0; i < temp.length; i++) {

drawBullet(temp[i]);

}

}

//画玩家子弹

var temp = hero.bulletsList;

for (var i = 0; i < temp.length; i++) {

drawBullet(temp[i]);

}

//画炸弹

for(var i=0;i<Bombs.length;i++){

drawBown(Bombs[i]);

}

}

function drawTank(tank){

var x = tank.x;

var y = tank.y;

ctx.fillStyle = tank.color;

if(tank.direct == 0 || tank.direct ==2){

ctx.fillRect(x, y, 5,30);

ctx.fillRect(x+15, y, 5,30);

ctx.fillRect(x+6, y+8, 8,15);

ctx.strokeStyle = tank.color;

ctx.lineWidth = '1.5';

if(tank.direct == 0){

ctx.beginPath();

ctx.moveTo(x+10,y-2);

ctx.lineTo(x+10,y+8);

ctx.closePath();

}else{

ctx.beginPath();

ctx.moveTo(x+10,y+24);

ctx.lineTo(x+10,y+32);

ctx.closePath();

}

ctx.stroke();

}else{

ctx.fillRect(x, y, 30,5);

ctx.fillRect(x, y+15, 30,5);

ctx.fillRect(x+8, y+6, 15,8);

ctx.strokeStyle = '#FF0000';

ctx.lineWidth = '1.5';

if(tank.direct == 3){

ctx.beginPath();

ctx.moveTo(x-2,y+10);

ctx.lineTo(x+8,y+10);

ctx.closePath();

}else{

ctx.beginPath();

ctx.moveTo(x+24,y+10);

ctx.lineTo(x+32,y+10);

ctx.closePath();

}

ctx.stroke();

}

}

function drawBullet(bullet){

ctx.fillStyle = bullet.color;

ctx.beginPath();

ctx.arc(bullet.x,bullet.y,2,360,true);

ctx.closePath();

ctx.fill();

}

function drawBown (obj){

if(obj.life>8){

ctx.drawImage(im,obj.x,obj.y,50,50);

}else if(obj.life>4){

ctx.drawImage(im2,obj.x,obj.y,50,50);

}else{

ctx.drawImage(im3,obj.x,obj.y,50,50);

}

obj.lifeDown();

if(obj.life<=0){

Bombs.deleteElement(obj);

}

}

function checkDead(){

//检测敌人子弹生死

for(var j=0;j<enemys.length;j++){

var temp = enemys[j].bulletsList;

for (var i = 0; i < temp.length; i++) {

var o = temp[i];

if(o.isdead){

temp.deleteElement(o);

}

}

}

//检测玩家子弹生死

var temp = hero.bulletsList;

for (var i = 0; i < temp.length; i++) {

var o = temp[i];

if(o.isdead){

temp.deleteElement(o);

}

}

//检测敌人坦克生死

for (var i = 0; i < enemys.length; i++) {

var o = enemys[i];

if(o.isdead){

enemys.deleteElement(o);

}

}

}

Bomb.js

复制代码 代码如下:

/**

* Created by Alane on 14-3-18.

*/

function Bomb(x,y){

this.life = 12;

this.x = x;

this.y = y;

}

Bomb.prototype.lifeDown = function(){

this.life--;

}

Tank.js

复制代码 代码如下:

/**

* Created by Alane on 14-3-7.

*/

/**

* direct 0 上

* 1 右

* 2 下

* 3 左

* @param x

* @param y

* @param direct

* @constructor

*/

//******************************************************************************************/

//坦克父类

function Tank (x, y, direct) {

this.speed = 2;

}

Tank.prototype.moveUp = function () {

//边界检测

if (this.y < 0) {

//换方向

this.changeDirect ();

return;

}

this.y -= this.speed;

this.direct = 0;

}

Tank.prototype.moveDown = function () {

if (this.y > height - 30) {

this.changeDirect ();

return;

}

this.y += this.speed;

this.direct = 2;

}

Tank.prototype.moveLeft = function () {

if (this.x < 0) {

this.changeDirect ();

return;

}

this.x -= this.speed;

this.direct = 3;

}

Tank.prototype.moveRight = function () {

if (this.x > width - 30) {

this.changeDirect ();

return;

}

this.x += this.speed;

this.direct = 1;

}

//变换方向

Tank.prototype.changeDirect = function () {

while (true) {

var temp = Math.round (Math.random () * 3);

if (this.direct != temp) {

this.direct = temp;

break;

}

}

//alert("x="+this.x+" y="+this.y+" direct="+this.direct)

}

//射击子弹

Tank.prototype.shot = function () {

if(this.isdead){

return;

}

if (this.bulletsList.length < this.maxBulletSize) {

//新建子弹

var bullet = null;

switch (this.direct) {

case 0:

bullet = new Bullet (this.x + 10, this.y - 2, 0, this.color);

break;

case 1:

bullet = new Bullet (this.x + 32, this.y + 10, 1, this.color);

break;

case 2:

bullet = new Bullet (this.x + 10, this.y + 32, 2, this.color);

break;

case 3:

bullet = new Bullet (this.x - 2, this.y + 10, 3, this.color);

break;

}

//放入弹夹

this.bulletsList.push (bullet);

}

}

//******************************************************************************************/

//玩家

function Hero (x, y, direct) {

this.lifetimes = 5;

this.isdead = false;

this.color = '#FF0000';

this.x = x;

this.y = y;

this.direct = direct;

this.bulletsList = [];

this.maxBulletSize = 10;

this.newlife = null;

}

Hero.prototype = new Tank (0, 0, 0);

Hero.prototype.constructor = Hero;

Hero.prototype.addLife = function(){

this.lifetimes++;

document.querySelector("#life").innerHTML = hero.lifetimes;

}

Hero.prototype.cutLife = function(){

if(this.lifetimes>=1 && !this.newlife){

this.lifetimes--;

this.newlife = setTimeout("hero.newLife()",2000);

}

}

Hero.prototype.newLife = function(){

this.isdead = false;

clearTimeout(hero.newlife);

hero.newlife = null;

document.querySelector("#life").innerHTML = hero.lifetimes;

}

//******************************************************************************************/

//敌人坦克

function Enemy (x, y, direct) {

this.isdead = false;

this.color = 'blue';

this.x = x;

this.y = y;

this.direct = direct;

this.bulletsList = [];

this.maxBulletSize = 1;

//定时器,自动移动

this.timer1 = setInterval ((function (context) {

return function () {

//移动

Enemy.prototype.move.call (context);

}

}) (this), 30);

//定时器,射击

this.timer2 = setInterval ((function (context) {

return function () {

//射击

Tank.prototype.shot.call (context);

}

}) (this), 2000);

//定时器,变换方向

this.timer3 = setInterval ((function (context) {

return function () {

//射击

Tank.prototype.changeDirect.call (context);

}

}) (this), 3000);

}

Enemy.prototype = new Tank (0, 0, 0);

Enemy.prototype.constructor = Enemy;

Enemy.prototype.move = function () {

switch (this.direct) {

case 0:

this.moveUp ();

break;

case 1:

this.moveRight ();

break;

case 2:

this.moveDown ();

break;

case 3:

this.moveLeft ();

break;

}

}

Bullet.js

复制代码 代码如下:

/**

* Created by Alane on 14-3-11.

*/

function Bullet (x, y, direct, color) {

this.isdead = false;

this.x = x;

this.y = y;

this.direct = direct;

this.speed = 4;

this.color = color;

//定时器,自行运动

this.timer = setInterval ((function (context) {

return function () {

Bullet.prototype.move.call (context)

}

}) (this), 30);

}

Bullet.prototype.move = function () {

switch (this.direct) {

case 0:

this.y -= this.speed;

break;

case 1:

this.x += this.speed;

break;

case 2:

this.y += this.speed;

break;

case 3:

this.x -= this.speed;

break;

}

//边界检测

if (this.y < 0 || this.x > width || this.y > height || this.x < 0) {

clearInterval (this.timer);

this.isdead = true;

}

//碰撞检测 检测敌人坦克

for(var i=0;i<allTank.length;i++){

var temp = allTank[i];

if(temp.isdead){

continue;

}

switch (temp.direct){

case 0:

case 2:if(this.x>temp.x && this.x<temp.x+20 && this.y>temp.y&& this.y<temp.y+30){

if(this.color == temp.color){

break;

}

Bombs.push(new Bomb(temp.x-10,temp.y-10));

clearInterval (this.timer);

this.isdead = true;

temp.isdead = true;

}break

case 1:

case 3:if(this.x>temp.x && this.x<temp.x+30 && this.y>temp.y&& this.y<temp.y+20){

if(this.color == temp.color){

break;

}

Bombs.push(new Bomb(temp.x-10,temp.y-10));

clearInterval (this.timer);

this.isdead = true;

temp.isdead = true;

}break;

}

}

}

【javascript 模拟坦克大战游戏(html5版)附源码下载】相关文章:

怎么用javascript进行拖拽第1/2页

javascript实现动态改变层大小的方法

javascript搜索框效果实现方法

javascript模拟评分控件实现方法

Javascript中Date类型和Math类型详解

javascript实时显示当天日期的方法

javascript事件冒泡实例分析

javascript的事件描述

JavaScript版代码高亮

javascript操作表格

精品推荐
分类导航