随着人们精神文化生活的日益丰富,为了让我们在闲暇的时间多方面发展个人的兴趣爱好,为了更好的开发个人智力,游戏成为人们生活中不可缺少的一部分。作为休闲游戏的起源应该追溯到早期的俄罗斯方块和坦克大战,坦克大战时童年经常玩的游戏,也是一款经典游戏,对我们90后而言,是童年最珍贵的回忆。
Html5横空出世,开启了新的RIA革命, 是未来Web发展的重要方向。这款Html5坦克大战是基于javascript,结合modernizr开源库设计的单机小游戏,用户可以控制坦克移动,可以选择关卡,攻击敌人等
下面给出敌人坦克移动的代码
functionenemyupdate() {
enemytank.shapenum =(0.1 + enemytank.shapenum) % 8 + 9; //减慢滚带的速度
enemytank.enemytankshape= Math.floor(enemytank.shapenum);
//下
if(enemytank.enemytankAngle== 180) {
swerve()
enemytank.nexty +=enemytank.enemytankspeed;
if(scene[Math.ceil((enemytank.nexty- 20) / 32)][Math.ceil((enemytank.nextx - 20) / 32)] != 0 ||scene[Math.ceil((enemytank.nexty - 20) / 32)][Math.floor((enemytank.nextx - 12)/ 32)] != 0) {
enemyhitwall()
}
}
//左
if(enemytank.enemytankAngle== 270) {
swerve()
enemytank.nextx -=enemytank.enemytankspeed;
if(scene[Math.floor((enemytank.nexty- 12) / 32)][Math.floor((enemytank.nextx - 12) / 32)] != 0 || scene[Math.ceil((enemytank.nexty- 20) / 32)][Math.floor((enemytank.nextx - 12) / 32)] != 0) {
enemyhitwall()
}
}
//右
if(enemytank.enemytankAngle== 90) {
swerve()
enemytank.nextx +=enemytank.enemytankspeed;
if(scene[Math.ceil((enemytank.nexty- 20) / 32)][Math.ceil((enemytank.nextx - 20) / 32)] != 0 ||scene[Math.floor((enemytank.nexty - 12) / 32)][Math.ceil((enemytank.nextx - 20)/ 32)] != 0) {
enemyhitwall()
}
}
//上
if(enemytank.enemytankAngle== 0) {
swerve()
enemytank.nexty -=enemytank.enemytankspeed;
if(scene[Math.floor((enemytank.nexty- 12) / 32)][Math.floor((enemytank.nextx - 12) / 32)] != 0 ||scene[Math.floor((enemytank.nexty - 12) / 32)][Math.ceil((enemytank.nextx - 20)/ 32)] != 0) {
enemyhitwall()
}
}
//随机发射炮弹
var enemyfire =Math.floor(Math.random() * 100);
if(enemyfire == 0) {
if(enemyshell.shellflage){
return;
}
if(enemytank.nextx< 0) {
return;
} else {
enemyshell.shellflage= true;
enemyshell.nextx = enemytank.nextx;
enemyshell.nexty= enemytank.nexty;
enemyshell.shellAngle= enemytank.enemytankAngle;
if(enemyshellInterval){
clearInterval(enemyshellInterval);
enemyshellInterval= null;
}
enemyshellInterval= setInterval(enemyrdrawshell, 33);
}
}
//检测是否打击到目标
if(impact(shell,enemytank)) {
if(shellInterval) {
clearInterval(shellInterval);
shellInterval =null;
}
score++;
if(score >=record) {
record = score;
localStorage.record= record;
}
if(score >= level* 5) {
level++;
if(level > 5){
gameover =true;
return
}
scene =scenenum[(level - 1) % 4];
for(var enemynum= 0; enemynum <= 2; enemynum++) {
var tempx = 48 + enemynum * 192;
//敌军坦克
tempenemytank= {
appearx:tempx,
appeary:48,
x: tempx,
y: 48,
nextx:tempx,
nexty: 48,
enemytankspeed:Speed + level * 0.5,
enemytankAngle:180,
enemytankshape:0,
shapenum:0
};
enemy[enemynum]= tempenemytank;
}
tankmove = {
appearx: 240,
appeary: 304,
x: 240,
y: 304,
nextx: 240,
nexty: 304,
tankAngle:Angle,
tankspeed:Speed,
tankshape:shape,
tanknextshape:shape
};
enemyshell = {
x: 0,
y: 0,
nextx: 0,
nexty: 0,
shellspeed:Speed + level * 0.5 + 2,
shellshape:21,
shellAngle:Angle,
shellflage:false
};
surplus = 6;
}
surplus--;
setTimeout(function(){
shell.shellflage= false
}, 300);
explode(enemytank)
enemytank.nextx =-500;
shell.nextx = -500;
shell.nexty = -500;
}
//检测是否打击到玩家
if(impact2(enemyshell,tankmove)) {
if(invincible) {
return;
}
if(enemyshellInterval){
clearInterval(enemyshellInterval);
enemyshellInterval= null;
}
life--;
if(life <= 0) {
gameover = true;
return;
}
invincible = true;
setTimeout(function(){
invincible =false
}, 2000)
explode(tankmove)
setTimeout(function(){
enemyshell.shellflage= false
}, 300);
tankmove.nextx =-500;
enemyshell.nextx =-500;
enemyshell.nexty =-500;
}
//与敌人相撞
if(impact(enemytank,tankmove)) {
if(enemyshellInterval){
clearInterval(enemyshellInterval);
enemyshellInterval= null;
}
if(invincible) {
return;
}
invincible = true;
setTimeout(function(){
invincible =false
}, 2000)
life--;
if(life <= 0) {
gameover = true;
return;
}
explode(tankmove)
tankmove.nextx =-500;
}
//自动转向
function swerve() {
var j =Math.floor(Math.random() * 100);
if(j == 0) {
enemytank.enemytankAngle+= 90;
}
if(j == 1) {
enemytank.enemytankAngle-= 90;
}
enemytank.enemytankAngle= (enemytank.enemytankAngle + 360) % 360;
}
//撞墙转向
function enemyhitwall(){
enemytank.nextx =enemytank.x;
enemytank.nexty =enemytank.y;
var j =Math.floor(Math.random() * 2);
if(j == 0) {
enemytank.enemytankAngle+= 90;
} else {
enemytank.enemytankAngle-= 90;
}
enemytank.enemytankAngle= (enemytank.enemytankAngle + 360) % 360;
}
}
//炮弹数组
shell= {
x:0,
y:0,
nextx:0,
nexty:0,
shellspeed:Speed + 4,
shellshape:20,
shellAngle:Angle,
shellflage:false
};
//敌军炮弹数组
varenemyshell = {
x:0,
y:0,
nextx:0,
nexty:0,
shellspeed:Speed + 2,
shellshape:21,
shellAngle:Angle,
shellflage:false
};
//空格,发射炮弹
functionspace() {
if(keyPressList[32]== true) {
if(gameover){
location.reload();
}
if(shell.shellflage){
return;
}
if(tankmove.nextx< 0) {
return;
}else {
shootSound.play();
shell.shellflage= true;
shell.nextx= tankmove.nextx;
shell.nexty= tankmove.nexty;
shell.shellAngle= tankmove.tankAngle;
if(shellInterval){
clearInterval(shellInterval);
shellInterval= null;
}
shellInterval= setInterval(drawshell, 33);
}
}
}
//检测炮弹是否撞墙
functionhitwall(i) {
switch(i){
case26:
if(shellInterval){
clearInterval(shellInterval);
shellInterval= null;
}
setTimeout(function(){
shell.shellflage= false
},300);
shell.nextx= -500;
shell.nexty= -500;
return0;
break
case31:
if(shellInterval){
clearInterval(shellInterval);
shellInterval= null;
}
setTimeout(function(){
shell.shellflage= false
},300);
shell.nextx= -500;
shell.nexty= -500;
returni;
break
case30:
if(shellInterval){
clearInterval(shellInterval);
shellInterval= null;
}
setTimeout(function(){
shell.shellflage= false
},300);
shell.nextx= -500;
shell.nexty= -500;
returni;
break
default:
return0;
}
}
//声音
//爆炸
varexplodeSound = document.createElement("audio");
document.body.appendChild(explodeSound);
explodeSound.setAttribute("src","audio/explode1.mp3");
explodeSound.valume= .5;
//发射子弹
varshootSound = document.createElement("audio");
document.body.appendChild(shootSound);
shootSound.setAttribute("src","audio/shoot1.mp3");
shootSound.volume= .5;
//玩家行走
varplayermove = document.createElement("audio");
document.body.appendChild(playermove);
playermove.setAttribute("src","audio/move1.mp3");
playermove.valume= .001;
//敌人行走
varenemyrmove = document.createElement("audio");
document.body.appendChild(enemyrmove);
enemyrmove.setAttribute("src","audio/move2.mp3");
enemyrmove.valume= .001;
context.clearRect(496, 16, 138, 352);
context.fillStyle= "#3cb371";
context.fillRect(496,16, 138, 352);
context.save();
context.fillStyle= "#000000";
context.font= "italic bold 23px serif";
context.fillText("关 卡:" + level +"", 500, 80);
context.fillText("敌 人:" + surplus +"", 500, 110);
context.fillText("生 命:" + life +"", 500, 140);
context.fillText("得 分:" + score +"", 500, 170);
context.fillText("最高分:" + record +"", 500, 200);
context.restore();
context.save();
context.fillStyle= "#000000";
context.font= "normal bold 15px normal";
context.fillText("游戏说明: 玩家", 500, 270);
context.fillText("操控坦克进行战", 500,290);
context.fillText("斗,击毁敌方得", 500,310);
context.fillText("分,被击毁或相", 500,330);
context.fillText("相撞减分。", 500,350);
context.restore();
score++;
if(score>= record) {
record= score;
localStorage.record= record;
}
if(score>= level * 5) {
level++;
if(level> 5) {
gameover= true;
return
}
scene= scenenum[(level - 1) % 4];
for(varenemynum = 0; enemynum <= 2; enemynum++) {
vartempx = 48 + enemynum * 192;
//敌军坦克
tempenemytank= {
appearx:tempx,
appeary:48,
x:tempx,
y:48,
nextx:tempx,
nexty:48,
enemytankspeed:Speed + level * 0.5,
enemytankAngle:180,
enemytankshape:0,
shapenum:0
};
enemy[enemynum]= tempenemytank;
这是我学习Html5一个多月以来,首次做的一个小项目,由于之前学过别的语言,所以做起来并不觉得困难。通过这个小项目,让我更深的了解了面向对象,同时也更深入的了解了一些新的知识点,稍作总结:对象能够移动的本质是:改变对象的坐标,再对对象重画。由于重画的速度很快,我们的肉眼无法察觉,因此就以为是移动了。根据坦克的起始坐标,根据坦克的方向设一个变量相应的改变坦克的起始坐标。然后在通过重画,就达到了运动的效果。通过这次编程实训和撰写实训报告,我们学会了一些编程技巧,同时也巩固了平常所学的理论知识,如html5、js、jquery,对调试程序也有了进一步的认识,有时候一个小小的语法错误都会导致程序编译不通过。所以在编程过程中,一定要认真对待,在使用HBuilder环境开发时,进一步的感受到了HBuilder的强大,对于拽写实训报告一定要注意格式,任何事情都有它的规范,不能因个人喜好而决定。
设计中存在的不足之处:
1.坦克行走没有声音
2.地图画大有困难
3.游戏刷新时有闪烁现象(双缓冲)
希望结束实训能在日后的学习中修复BUG,用于学习,勤于钻研、不断提高自己。
********************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************