这是挺早之前的代码了,当时刚接触到js的面向对象,觉得用面向对象写游戏巨简单,于是尝试着写了这个游戏,喜欢的朋友可以star一下,谢谢。
这里我稍微讲解一下实现的过程
- 界面切换就不详细说了,是基本的dom操作,相信大家也是非常的熟练了。
- 飞机基本类
// 飞机的类
var plane = function(){
this.stop = 0;
this.state = 1;
this.plane;
this.timmer;
this.x;
this.y;
this.width;
this.height;
this.score;
this.blood;
// 改变坐标的方法
this._init = function(){
this.createPlane();
this.setPos();
}
// 被摧毁
this.beDistoryed = function(){
this.plane.src = this.plane.getAttribute("boom");
this.stop = 1;
score+=this.score;
document.getElementById("score").innerHTML=score;
var _this = this
setTimeout(function(){
_this.removeIt();
_this.state = 0;
},800)
}
// 飞机出界后销毁的方法
this.removeIt = function(){
this.plane.parentNode.removeChild(this.plane);
}
// 被攻击
this.beAttacked = function(){
var oldPic = this.plane.src
var _this = this.plane;
this.plane.src = this.plane.getAttribute("attacked");
clearTimeout(this.timmer);
this.timmer = setTimeout(function(){
_this.src = oldPic;
},300)
}
this.setPos = function(){
this.plane.style.top = -this.height + "px";
this.plane.style.left = (box_W-this.width)*Math.random() + "px"
}
// 飞机移动的方法
this.move=function(user){
if(!this.stop){
this.plane.style.top = parseInt(this.plane.style.top) + this.speed + "px"
if(this.checkUserPlane(user)){
user.die();
}
}
}
// 判断是否出界
this.checkOut = function(){
if(parseInt(this.plane.style.top)>box.clientHeight){
return true;
}else{
return false;
}
}
// 检测是否与用户飞机相撞
this.checkUserPlane = function(user){
var u_T = parseInt(user.plane.style.top)
var u_L = parseInt(user.plane.style.left)
var u_W = parseInt(user.width)
var u_H = parseInt(user.height)
var p_T = parseInt(this.plane.style.top)
var p_L = parseInt(this.plane.style.left)
var p_W = parseInt(this.width)
var p_H = parseInt(this.height)
if(u_T+u_H>p_T && u_T<p_T+p_H && u_L+u_W>p_L && u_L < p_L+p_W){
return true;
}
return false;
}
}
上面这个类定义了所有的飞机所需要的基本方法,用户和敌机都将继承这个类,js由于es5对面向对象的的继承的概念不是非常的清晰,多以模拟类继承的方法也五花八门,作用各不同,想深入了解的同学可以自行百度或者谷歌。
- 用户飞机类,继承通用飞机类
// 用户飞机的类
var userPlane = function(){
this.createPlane=function(){
this.plane = document.createElement("img");
this.plane.src="./image/我的飞机.gif";
// 这边我直接将飞机爆炸的图片信息存入img中方便读取,其实直接存入对象的某个属性也是可以的
this.plane.setAttribute("attacked","");
this.plane.setAttribute("boom","./image/本方飞机爆炸.gif");
this.blood = 1;
this.width = 66;this.height=80;
box.appendChild(this.plane);
}
this.setPos = function(){
this.plane.style.top = box_H-this.height + "px"
this.plane.style.left = (box_W-this.width)/2 + "px"
}
this.moveTo = function(x,y){
if(x>this.width/2 && x<box.clientWidth-this.width/2){
this.plane.style.left = x-this.width/2 + "px"
}
if(y>this.height/2 && y<box.clientHeight-this.height/2){
this.plane.style.top = y-this.height/2 + "px"
}
}
this.die = function(){
state = 0;
this.beDistoryed();
box.onmousemove = null;
}
this.beDistoryed = function(){
this.plane.src = this.plane.getAttribute("boom");
document.getElementById("score2").innerHTML = score;
document.getElementById("board").style.display="block";
}
this._init();
}
以上是用户飞机类,用户想比较与敌机,不同的是,飞机的移动是有用户自己控制的,所以写了moveTo的方法,当然还要实现用户被摧毁的方法。
接下来是三个不同等级的飞机
1.敌机1,小飞机
// 敌机1的类
var dj1 = function(){
this.score = 10;
this.speed = 5+Math.floor(3*Math.random());
this.createPlane=function(){
this.plane = document.createElement("img");
this.plane.src="./image/enemy1_fly_1.png";
this.plane.setAttribute("attacked","");
this.plane.setAttribute("boom","./image/小飞机爆炸.gif");
this.blood = 1;
this.width = 34;this.height=24;
box.appendChild(this.plane);
}
this._init();
}
2.中型敌机
//敌机2的类
var dj2 = function(){
this.score = 30;
this.speed = 3+Math.floor(3*Math.random());
this.createPlane=function(){
this.plane = document.createElement("img");
this.plane.src="./image/enemy3_fly_1.png";
this.plane.setAttribute("attacked","./image/中飞机挨打.png");
this.plane.setAttribute("boom","./image/中飞机爆炸.gif");
this.blood = 8;
this.width = 46;this.height=60;
box.appendChild(this.plane);
}
this._init();
}
3.大型敌机
//敌机3的类
var dj3 = function(){
this.score = 100;
this.speed = 1+Math.floor(3*Math.random());
this.createPlane=function(){
this.plane = document.createElement("img");
this.plane.src="./image/enemy2_fly_1.png";
this.plane.setAttribute("attacked","./image/大飞机挨打.png");
this.plane.setAttribute("boom","./image/大飞机爆炸.gif");
this.blood = 20;
this.width = 110;this.height=164;
box.appendChild(this.plane);
}
this._init();
}
PS:三个敌机的不同点是,他们的血量与飞行速度都是不同的,虽然飞行速度都是随机的,但是是要基于一定速度的一定范围内的随机变化,不然会影响游戏性。
写完所有的飞机类,还需要补充写一个子弹类,每一个子弹都是一个对象,在循环遍历中去判断子弹与飞机是否重合(其实这个算法不对,应该是计算敌机是否经过子弹的相邻两次位移的弹道上,由于是很早之前写的了就不想去做修改了)
- 子弹的类
// 子弹的类
var zidan = function(plane){
this.state = 1;
this.zidan;
this.width=6;
this.height=14;
this.x;
this.y;
this.speed = 40;
// 子弹的构造方法
this._init = function(){
this.create();
this.setPos();
}
// 子弹创建的方法
this.create = function(){
this.zidan = document.createElement("img");
this.zidan.src="./image/bullet1.png";
}
// 给子弹定位的方法
this.setPos = function(){
this.zidan.style.left = parseInt(plane.plane.style.left)+plane.width/2-this.width/2 +"px";
this.zidan.style.top = parseInt(plane.plane.style.top)-this.height + "px";
box.appendChild(this.zidan)
}
// 子弹飞行的方法
this.move = function(){
this.zidan.style.top = parseInt(this.zidan.style.top)-this.speed + "px";
this.checkDj();
}
// 子弹检测出界的方法
this.checkOut = function(){
if(parseInt(this.zidan.style.top)<box.offsetTop-this.height){
return true
}else{
return false
}
}
// 子弹消失的方法
this.removeIt = function(){
this.zidan.parentNode.removeChild(this.zidan);
}
// 检测是否装机到敌机的方法
this.checkDj = function(){
if(!this.state)return
var djL,djT,djW,djH;
for(var i in djArr){
djL = parseInt(djArr[i].plane.style.left);
djT = parseInt(djArr[i].plane.style.top);
djW = parseInt(djArr[i].width);
djH = parseInt(djArr[i].height);
if(parseInt(this.zidan.style.left)>djL &&
parseInt(this.zidan.style.left)<djL+djW-this.width &&
parseInt(this.zidan.style.top)>djT &&
parseInt(this.zidan.style.top)<djT+djH){
if(djArr[i].blood<=1){
if(!djArr[i].stop){
djArr[i].beDistoryed();
this.removeIt()
this.state = 0;
break;
}
}else{
djArr[i].blood--;
djArr[i].beAttacked();
this.removeIt()
this.state = 0;
break;
}
}
}
}
this._init();
}
继承:这里使用的是
// 继承
userPlane.prototype =new plane();
dj1.prototype =new plane();
dj2.prototype =new plane();
dj3.prototype =new plane();
当然还有call和apply或者其他的方法,我这里就用一个能实现就行
接下来就是开始通过每一帧去改变子弹飞机的位置,实现动画的启动,一级判断飞机的各个事件。
效果图就是