您的位置:首页 > Web前端 > JavaScript

JavaScript游戏之小型打飞机

2010-10-26 11:53 316 查看
这次为大家带来的小游戏是:打飞机。呃。。。我本人就写不出什么惊天大作的游戏的了,只能写写小游戏,代码量小,又可以学习,

主要是想法思路,代码量大,估计也没啥人会去研究学习。。。

玩法说明:上下左右控制移动,空格发弹。 每打中一个敌机就加100分,每提升5000分,玩家的飞机的一次发弹数就加一,最多四,被敌机撞到或者让敌机飞到底部就算输。。。。

//飞机类---玩家飞机
var Flyer = function(){
//飞机对应的dom元素
this.dom = null;
//是否活着
this.isLive = true;
//是否移动中
this.isMove = false;
//移动的ID
this.moveId = null;
//是否发弹中
this.isSend = false;
//目前已经发了多少颗弹(存在屏幕显示)
this.nowBullet = 0;
this.init();
}
Flyer.prototype = {
//游戏背景Dom
gamePanel : null,
//游戏背景宽度
gameWidth : 0,
//游戏背景高度
gameHeight : 0,
//飞机移动速度
movepx : 10,
//飞机移动频率
movesp : 30,
//飞机子弹级别
bulletLevel : 1,
//最大发弹数(存在屏幕显示)
maxBullet : 12,
//方向键值对应
keyCodeAndDirection : {
37 : "left",
38 : "up",
39 : "right",
40 : "down"
},
//初始化
init : function(){
this.dom = document.createElement('div');
this.dom.className = 'flyer';
},
//设置位置
setPosition : function(gamePanel,width,height){
//将飞机添加进游戏背景中
this.gamePanel = gamePanel;
this.gamePanel.appendChild(this.dom);
//设置飞机的初始位置
this.dom.style.left = (width - this.dom.clientWidth) / 2 + 'px';
this.dom.style.top = height - this.dom.clientHeight + 'px';
//获取到游戏背景的宽和高
this.gameWidth = width;
this.gameHeight = height;
},
//键盘按下事件
keydown : function(e) {
var keyCode = e.keyCode;
//按了空格发弹
if(keyCode == 32){
//判断是否发弹中
if(!this.isSend){
//发弹
this.onSendBullet();
this.isSend = true;
}
}
//判断是否移动中,移动
else if(!this.isMove)this.move(keyCode);
},
//键盘释放事件
keyup : function(e){
//判断是否为键盘释放
if(this.keyCodeAndDirection[e.keyCode]){
//停止移动
this.stopMove();
}
//发弹键释放
else if(e.keyCode == 32){
//设置为非发弹中
this.isSend = false;
}
},
//移动
move : function(keyCode){
//设置为移动中
this.isMove = true;
var _this = this;
//判断移动方向
switch(this.keyCodeAndDirection[keyCode]){
case "left":{
this.moveId = setInterval(function(){_this.moveLeftUp("left");},_this.movesp);
break;
}
case "up":{
this.moveId = setInterval(function(){_this.moveLeftUp("up");},_this.movesp);
break;
}
case "right":{
this.moveId = setInterval(function(){_this.moveRightDown("right")},_this.movesp);
break;
}
case "down":{
this.moveId = setInterval(function(){_this.moveRightDown("down");},_this.movesp);
break;
}
default:break;
}
},
//左或上移动
moveLeftUp : function(direction){
var leftOrUp = this.dom[direction=="left"?"offsetLeft":"offsetTop"];
leftOrUp = leftOrUp - this.movepx >= 0 ? leftOrUp - this.movepx:0;
this.dom.style[direction=="left"?"left":"top"] = leftOrUp + 'px';
if(leftOrUp == 0){this.stopMove();}
},
//右或下移动
moveRightDown : function(direction){
var leftOrUp = this.dom[direction=="right"?"offsetLeft":"offsetTop"];
var maxDistance = direction=="right"?this.gameWidth-this.dom.clientWidth:this.gameHeight - this.dom.clientHeight;
leftOrUp = leftOrUp + this.movepx <= maxDistance ? leftOrUp + this.movepx:maxDistance;
this.dom.style[direction=="right"?"left":"top"] = leftOrUp + 'px';
if(leftOrUp == maxDistance){this.stopMove();}
},
//停止移动
stopMove : function(){
this.isMove = false;
clearInterval(this.moveId);
},
//发射子弹,enemyList为敌机列表
sendBullet :function(enemyList){
//判断发单数是否超出
if(this.bulletLevel + this.nowBullet > this.maxBullet){return;}
var _this = this;
//循环发弹,根据飞机子弹级别
for (var i = 1,l=this.bulletLevel; i <= l; i++) {
//新建一个子弹对象
var bullet = new Bullet();
//将子弹的dom添加到游戏背景中
this.gamePanel.appendChild(bullet.dom);
//设置子弹的初始位置
bullet.setPosition({
left: this.dom.offsetLeft,
top: this.dom.offsetTop,
width: this.dom.clientWidth,
position : i,
level : l
});
//重写子弹的检测是否打中敌机函数
bullet.checkBeat = function(){
//遍历敌机列表,判断是否打中敌机
for (var i = 0, l = enemyList.length; i < l; i++) {
//敌机是死的,跳过
if(!enemyList[i].isLive)continue;
//获取敌机的x,y坐标以及半径,还有子弹的x,y坐标以及半径
var e_left = enemyList[i].dom.offsetLeft, e_top = enemyList[i].dom.offsetTop, e_radius = enemyList[0].dom.clientWidth / 2, b_left = this.dom.offsetLeft, b_top = this.dom.offsetTop, b_radius = bullet.dom.clientWidth / 2;
//判断是否被击中
//原理,比较两个圆的圆心距与两个圆的半径之和
if (Math.sqrt(Math.pow(e_left - b_left, 2) + Math.pow(e_top - b_top, 2)) <= e_radius + b_radius) {
//敌机死亡
enemyList[i].isLive = false;
//修改分数
_this.onChangeScore();
//返回true
return true;
}
}
return false;
}
//重写子弹的结束函数
bullet.onend = function(){
//从游戏背景移除子弹
_this.gamePanel.removeChild(this.dom);
//已经发弹数减一
_this.nowBullet--;
}
//发弹动画,就是移动
bullet.animation();
//已发弹数加一
_this.nowBullet++;
}
},
//飞机爆炸
burstFlyer : function(){
this.dom.className = 'bingo';
},
//发射子弹外部接口,主要任务为回调sendBullet函数,传入敌机列表参数
onSendBullet : function(){},
//改分数外部接口
onChangeScore : function(){}
}
//子弹类
var Bullet = function(){
//子弹Dom元素
this.dom = null;
this.init();
}
Bullet.prototype = {
//子弹移动速度
movepx : 8,
//子弹移动频率
movesp : 10,
//初始化
init : function(){
this.dom = document.createElement('div');
this.dom.className = 'bullet';
},
//设置子弹初始位置
//flyerinfo = {left:1,top:1,width:1,position:1,level:1}
setPosition : function(flyerinfo){
//子弹在飞机的中点位置
var center = flyerinfo.left + ((flyerinfo.width-this.dom.clientWidth)/2),
//偏移量
offset = 0;
//设置第几发子弹
flyerinfo.position = (flyerinfo.level % 2 != 0)?flyerinfo.position:flyerinfo.position+1;
//计算偏移量
offset = (flyerinfo.position % 2 != 0)?(parseInt(flyerinfo.position/2,10) * this.dom.clientWidth):flyerinfo.position / 2 * this.dom.clientWidth * -1;
//设置子弹位置
this.dom.style.left = center + offset + 'px';
this.dom.style.top = flyerinfo.top - this.dom.clientHeight + 'px';
},
//子弹动画,移动
animation : function(){
var _this = this;
//处理移动函数
var process = function(){
var top = _this.dom.offsetTop;
top = top - _this.movepx >= 0 ? top - _this.movepx : 0;
_this.dom.style.top = top + 'px';
//判断是否移动到尽头,是否击中敌机
if(top > 0 && !_this.checkBeat()){
setTimeout(process,_this.movesp);
}
else {
_this.onend();
}
}
process();
},
//外部接口,是否击中敌机
checkBeat : function(){},
//外部接口,子弹结束事件
onend : function(){}
}
//敌机类
var Enemy = function(){
//敌机dom元素
this.dom = null;
//是否
this.isLive = true;
this.init();
}
Enemy.prototype = {
//敌机横向移动速度
movepx : 6,
//敌机纵向移动速度
movepy : 4,
//敌机移动频率
movesp : 75,
//敌机移动频率映射
movespMap : {
1: 75,
2: 65,
3: 50,
4: 40
},
//初始化
init : function(){
this.dom = document.createElement('div');
this.dom.className = 'enemy';
},
//设置敌机初始位置,x与y坐标
setPosition : function(x,y){
this.dom.style.left = x +'px';
this.dom.style.top = y + 'px';
},
//敌机动画,就是移动,传入参数为游戏背景的宽与高
animation : function(gameWidth,gameHeight){
var _this = this,
//实际的横向移动速度,左或者右
_movepx = this.dom.offsetLeft > gameWidth / 2 ?-1*this.movepx:this.movepx;
//处理移动函数
var process = function(){
//敌机的x,y坐标
var top = _this.dom.offsetTop;
//向下移动
top = top + _this.movepy >= gameHeight - _this.dom.clientHeight?gameHeight - _this.dom.clientHeight:top + _this.movepy;
//设置敌机位置
_this.dom.style.top = top + 'px';
//判断是否撞到飞机玩家
var isCrash = _this.OnCheckCrash();
//判断是否飞到尽头,是否活着,是否撞到飞机玩家
if(top < gameHeight - _this.dom.clientHeight && _this.isLive && !isCrash){
//继续移动
setTimeout(process,_this.movesp);
}
else {
//敌机死了而且没撞到飞机玩家
if (!_this.isLive && !isCrash)
//爆炸
_this.effect();
//敌机撞到飞机玩家
else {
//爆炸
_this.effect();
//游戏结束
setTimeout(function(){_this.gameover();}, 100);
}
}
}
//开始移动
process();
},
//敌机爆炸
effect : function(){
this.dom.className = 'bingo';
var _this = this;
setTimeout(function(){_this.onend()},50);
},
//外部接口,检测是否撞到飞机玩家
OnCheckCrash : function(){},
//敌机结束事件
onend : function(){},
//游戏结束
gameover:function(){}
}
//扩展数组方法,删除特定的值
Array.prototype.remove = function(obj){
for(var i=0,l=this.length;i < l;i++){
if(this[i] == obj){
this.splice(i,1);
return this;
}
}
throw "The Array has no this Obj";
}
//游戏控制类
var Game = {
//游戏背景dom
gamePanel : null,
//飞机玩家
flyer : null,
//敌机列表
enemyList : [],
//分数
score : 0,
//游戏是否结束
isGameOver : false,
//初始化
init : function(){
var _this = this;
//获取游戏背景
this.gamePanel = document.getElementById("gamePanel");
//游戏背景获得焦点
this.gamePanel.focus();
//启动飞机
this.startFlyer();
//启动 敌机
this.startEnemy();
//设置键盘按下与释放事件
document.body.onkeydown = function(e){_this.onkeydown(e);};
document.body.onkeyup = function(e){_this.onkeyup(e);}
},
//启动飞机
startFlyer : function(){
var _this = this;
//新建飞机对象
this.flyer = new Flyer();
//设置位置
this.flyer.setPosition(this.gamePanel,this.gamePanel.clientWidth,this.gamePanel.clientHeight);
//重写发弹函数
this.flyer.onSendBullet = function(){this.sendBullet(_this.enemyList);};
//重写修改分数
this.flyer.onChangeScore = function(){_this.changeScore();};
},
//启动敌机
startEnemy : function(){
//游戏结束,退出
if(this.isGameOver)return;
var _this = this;
//新建一个敌机对象
var enemy = new Enemy();
//将敌机添加进游戏背景
this.gamePanel.appendChild(enemy.dom);
//随机出敌机的x坐标位置
var randomX = parseInt(Math.random()* ((this.gamePanel.clientWidth - enemy.dom.clientWidth) / enemy.dom.clientWidth),10);
//设置位置
enemy.setPosition(randomX * enemy.dom.clientWidth,0);
//重写检测是否击中飞机玩家
enemy.OnCheckCrash = function(){
//游戏结束,退出
if(_this.isGameOver)return;
//判断是否击中
if(Math.sqrt(Math.pow(_this.flyer.dom.offsetLeft-this.dom.offsetLeft,2)+Math.pow(_this.flyer.dom.offsetTop-this.dom.offsetTop,2))
<= _this.flyer.dom.clientWidth/2 + this.dom.clientWidth/2){
//敌机死亡
this.isLive = false;
//飞机玩家爆炸
_this.flyer.burstFlyer();
return true;
}
return false;
}
//重写敌机结束事件
enemy.onend = function(){
_this.gamePanel.removeChild(this.dom);
_this.enemyList.remove(this);
}
//游戏结束函数
enemy.gameover = function(){_this.gameover();}
//敌机移动
enemy.animation(this.gamePanel.clientWidth,this.gamePanel.clientHeight);
//将敌机添加到列表中
this.enemyList.push(enemy);
//启动
setTimeout(function(){_this.startEnemy();},500);
},
//键盘按下事件
onkeydown : function(e){
e = e || window.event;
var keyCode = e.keyCode;
//阻止浏览器默认事件
if(keyCode == 32 || this.flyer.keyCodeAndDirection[keyCode]){
if(e.preventDefault)e.preventDefault();
else e.returnValue = false;
}
else return;
//回调飞机键盘按下事件
this.flyer.keydown(e);
},
//键盘释放事件
onkeyup : function(e){
e = e || window.event;
//回调飞机键盘释放事件
this.flyer.keyup(e);
},
//修改分数
changeScore : function(){
this.score += 100;
document.getElementById('score').innerHTML = this.score;
//分数级别
var scoreLevel = parseInt(this.score / 5000,10) + 1;
//判断是否升级飞机子弹级别
if(scoreLevel > 1){
this.flyer.bulletLevel = scoreLevel>4?4:scoreLevel;
//修改敌机移动速度
Enemy.prototype.movesp = Enemy.prototype.movespMap[this.flyer.bulletLevel];
}
},
//游戏结束
gameover : function(){
this.isGameOver = true;
document.getElementById('score').innerHTML = "The Game is Over...You Score:" + this.score;
for(var i=0,l=this.enemyList.length;i < l;i++){
this.gamePanel.removeChild(this.enemyList[0].dom);
this.enemyList.remove(this.enemyList[0]);
}
this.gamePanel.removeChild(this.flyer.dom);
this.flyer = null;
this.score = 0;
this.gamePanel = null;
document.body.onkeydown = null;
document.body.onkeyup = null;
document.getElementById('startBtn').style.display = 'block';
}
}
//游戏开始入口
function Start(){
Game.isGameOver = false;
Game.init();
document.getElementById('startBtn').style.display = 'none';
document.getElementById('score').innerHTML = 0;
}

#gamePanel{width:400px;height:500px;background:Black;position:absolute;}
#gamePanel .score{font-size:12px;color:White;position:absolute;left:0;top:0;z-index:9999;}
#gamePanel .bullet{width:5px;height:15px;position:absolute;background:url(http://images.cnblogs.com/cnblogs_com/floyd/266921/o_bullet.png);overflow:hidden;
_background:none;_filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(src="http://images.cnblogs.com/cnblogs_com/floyd/266921/o_bullet.png");}
#gamePanel .flyer{width:18px;height:18px;position:absolute;background:url(http://images.cnblogs.com/cnblogs_com/floyd/266921/o_flyer.png);
_background:none;_filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(src="ihttp://images.cnblogs.com/cnblogs_com/floyd/266921/o_flyer.png");}
#gamePanel .enemy{width:18px;height:18px;position:absolute;background:url(http://images.cnblogs.com/cnblogs_com/floyd/266921/o_enemy.png);
_background:none;_filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(src="http://images.cnblogs.com/cnblogs_com/floyd/266921/o_enemy.png");}
#gamePanel .bingo{width:18px;height:18px;position:absolute;background:url(http://images.cnblogs.com/cnblogs_com/floyd/266921/o_bingo.png);
_background:none;_filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(src="http://images.cnblogs.com/cnblogs_com/floyd/266921/o_bingo.png");}
#startBtn{border-width:20px;border-style:solid;border-color:Black Black Black Green;
position:absolute;left:190px;top:240px;cursor:pointer;width:0px;height:0px;overflow:hidden;}

分数:0

游戏目前的功能还是比较简单的。。。。貌似就贴个源码不太好,所以这次还是写写思路。。。

游戏主要分为4个js文件,4个js文件分别包含4个类。

1:飞机类---Flyer

//飞机对应的dom元素

this.dom = null;

//是否活着

this.isLive = true;

//是否移动中

this.isMove = false;

//移动的ID

this.moveId = null;

//是否发弹中

this.isSend = false;

//目前已经发了多少颗弹(存在屏幕显示)

this.nowBullet = 0;

//游戏背景Dom

gamePanel : null,

//游戏背景宽度

gameWidth : 0,

//游戏背景高度

gameHeight : 0,

//飞机移动速度

movepx : 10,

//飞机移动频率

movesp : 30,

//飞机子弹级别

bulletLevel : 1,

//最大发弹数(存在屏幕显示)

maxBullet : 12,

//方向键值对应

keyCodeAndDirection : {

37 : "left",

38 : "up",

39 : "right",

40 : "down"

},

以上是飞机应该有的属性。。。。

飞机除了有固定的一些属性之外,其实还应该有血量这些的,但这个是简陋版嘛,你可以自己添加。

更应该会有移动,发射子弹,爆炸等方法。

移动: 其实就是捕获键盘事件,如果是简单的按下键盘的左,然后飞机就向左移动几个像素,你会发觉,飞机移动起来很生硬,或者说是操作延迟,特别是你想按住键盘左的时候,它移动的时候,延迟得很严重,操作不流畅。所以一般都是:当你按下键盘时,调用一个setInterval函数来让飞机不断的移动,当释放键盘的时候,移动停止,这样移动就很流畅了。

发射子弹: 其实就是用户按了空格,然后触发一个键盘事件,此事件就是生成一个子弹Bullet类的对象,然后让它飞出去。此类后面会有说到。

爆炸: 当飞机撞到敌机的时候,飞机就会触发一个爆炸事件,结束游戏。当然,这个检测飞机是否撞到敌机,是在敌机那里检测。

这些是一些基本事件。还有扩展的事件。。可以自己添加

2:子弹类--Bullet

//子弹Dom元素

this.dom = null;

//子弹移动速度

movepx : 8,

//子弹移动频率

movesp : 10,

子弹最基本的两个方法:移动与检测是否打中敌机

移动:子弹的移动简单很多,就一直往上跑,top一直减就OK了。

检测是否打中敌机:将敌机的列表传进方法中,遍历敌机,检测子弹与敌机是否有碰撞,有则敌机爆炸,没有则跳过。

3:敌机类--Enemy

//敌机dom元素

this.dom = null;

//是否

this.isLive = true;

//敌机横向移动速度

movepx : 6,

//敌机纵向移动速度

movepy : 4,

//敌机移动频率

movesp : 75,

敌机的基本方法有:移动,是否撞到飞机Flyer玩家,爆炸

移动:就是敌机如何移动,我是设置成敌机从上到下飞,让后从左往又飞,撞到右边尽头,调头飞。

是否撞到飞机Flyer玩家:在敌机不断的移动过程中,不断的检测飞机Flyer与敌机是否有交集,有则两者爆炸,游戏结束,否则跳过。

爆炸:就是敌机被子弹打中或者撞到飞机Flyer时触发的事件。

4:游戏控制类--Game

其中包含一个扩展方法:从数组中删除指定元素

//扩展数组方法,删除特定的值

Array.prototype.remove = function(obj){

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

if(this[i] == obj){

this.splice(i,1);

return this;

}

}

throw "The Array has no this Obj";

}

其余的,都是些初始化敌机,飞机以及控制游戏流程的,还有一些修改分数,游戏结束之类的方法。这些没啥好讲。

大致就这样,游戏本身比较简单,下面的源码都有注释,这次写得比较详细。。。有兴趣的朋友,可以自己继续完善。。。有啥问题,欢迎拍砖。。。多多指教。

源码地址>>
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: