飞机大战小游戏的思路
游戏存在就会有准备阶段(控制游戏全局属性):
- 定义游戏状态
第一阶段:游戏欢迎状态 0 START
第二阶段:游戏加载状态 1 LOADING
第三阶段:游戏运行状态 2 RUNNING
第四阶段:游戏暂停阶段 3 PAUSE
第五阶段:游戏结束阶段 4 GAMEOVER - 定义游戏得分 score = 0
- 定义我方飞机的生命值 life = 3
- 定义游戏开关:
State=0
第一阶段
给页面添加一个动态的背景图
//1.游戏刚开始的阶段
//1.1加载背景图片
//1.1.1创建加载背景图片的对象
var bg=new Image();
bg.src="img/012.jpg";
//1.1.2初始化背景图片的数据
var BG={
imgs:bg,
width:480,
height:853
}
//1.1.3创建背景图片的构造函数(构造出一个对象)
//这里使用了创建对象的第二种方法:先使用函数来定义对象,然后创建新的对象实例
//构造函数的特点:
// ①构造函数的首字母必须要大写,用来区分与普通函数
// ②内部使用的this对象,来指向直接要生成的实例对象
// ③使用new来生成实例对象
function Bg(config){//这里的config是个形参,而BG就是后面要传进来的实参;
this.imgs=config.imgs;
this.width=config.width;
this.height=config.height;
//在这里定义了两张背景图,是为了第一张背景图移动完后第二张背景图接着移动
this.x1=0;
this.y1=0;
this.x2=0;
//第二张背景图的初始高度放在背景高度(固定)的上面
this.y2=-this.height;
//定义背景图片绘制的方法
this.paint=function(){
//分别绘制了两张背景图
context.drawImage(this.imgs,this.x1,this.y1);
context.drawImage(this.imgs,this.x2,this.y2);
}
//定义背景图片运动的方法
this.step=function(){
//背景图片位置向下移动一个,然后利用后面的定时器让背景图动起来
this.y1++;
this.y2++;
//判断图片高度的临界点,只要图片一和图片二的高度等于设置的背景高度时,就让他们的纵向位置变成背景高度的上面
if(this.y1 == this.height){
this.y1=-this.height;
}
if(this.y2 == this.height){
this.y2=-this.height;
}
}
}
// 1.1.4创建背景图片的对象
var sky=new Bg(BG);
// 1.2绘制游戏名
var logo=new Image();
logo.src="img/start.png";
点击开始时的进入游戏动画
2第二阶段游戏加载的过程
// 2.1游戏加载时的四个图片
var loadings = [];
loadings[0] = new Image();
loadings[0].src = "img/game_loading1.png";
loadings[1] = new Image();
loadings[1].src = "img/game_loading2.png";
loadings[2] = new Image();
loadings[2].src = "img/game_loading3.png";
loadings[3] = new Image();
loadings[3].src = "img/game_loading4.png";
// 2.2初始化图片数据
var LOADING={
imges:loadings,
length:loadings.length,
width:186,
height:38
}
// 2.3写构造函数
function Loading(config){
this.imges=config.imges;
this.length=config.length;
this.width=config.width;
this.height=config.height;
// 定义索引,判断要显示的图片是哪个
this.startIndex=0;
// 定义绘制方法
this.paint=function(){
context.drawImage(this.imges[this.startIndex],0,HEIGHT-this.height)
}
//定义游戏加载时的图片切换速度初始值
this.time=0;
//定义游戏加载时图片动态效果(其实是图片切换)的方法
this.step=function(){
this.time++;
//设置4步切换一张图
if(this.time % 4 == 0){
this.startIndex++;
}
if(this.startIndex == this.length){
state = RUNNING;
}
}
}
//创建游戏加载(第二阶段)的对象
var loading=new Loading(LOADING);
//获取鼠标点击事件
canvas.onclick = function(){
console.log(111);
if(state == START){
state = STARTING;
}
}
我方飞机与子弹
var heros=[];
heros[0]=new Image();
heros[0].src="img/hero1.png";
heros[1]=new Image();
heros[1].src="img/hero1.png";
heros[2]=new Image();
heros[2].src="img/hero_blowup_n4.png";
初始化图片数据
var HEROS={
imgs:heros,
length:heros.length,
width:99,
height:124,
frame:2
}
// 3.1.3构造我方飞机的函数
function Hero(config){
this.imgs=config.imgs;
this.length=config.length;
this.width=config.width;
this.height=config.height;
this.frame=config.frame;
this.startIndex=0;
this.x=WIDTH / 2 - this.width / 2;
this.y=HEIGHT - this.height;
this.down=false;
this.candel=false;
this.paint=function(){
context.drawImage(this.imgs[this.startIndex],this.x,this.y)
}
// 定义我方飞机运动的方法
this.step=function(){
if(!this.down){//表示飞机正常状态,此时只有两张图进行切换
if(this.startIndex == 0){
this.startIndex=1;
}
else{
this.startIndex=0;
}
}
else{//爆炸状态
this.startIndex++;//爆炸状态的图片持续增加
if(this.startIndex == this.length){//判断图片是最后一张的时候
life--;//我方飞机爆炸完后,生命值减一
//判断生命值为0时,游戏结束
if(life == 0){
state=GAMEOVER;
//虽然游戏结束了但是还停留在最后一张图的状态
this.startIndex=this.length-1;
}
// 想要开始新的生命时,直接给出创建的新的对象
else{
hero=new Hero(HEROS);
}
}
}
}
// 定义我方飞机碰撞的方法
this.bang=function(){
this.down=true;
}
// 增加我方飞机射击的方法
//定义射击速度初始值为0
this.time=0;
//我方飞机射击的时候,就会出现子弹,所以要调用子弹的数组中产生的子弹对象
this.shoot=function(){
this.time++;
//每3步射击一次
if(this.time % 3 == 0){
//这里把子弹每次创建好的新的实例增加到数组的末尾
bullets.push(new Bullet(BULLETS))
}
}
}
//创建我方飞机的对象实例
var hero=new Hero(HEROS);
//绑定移动我方飞机的事件
canvas.onmousemove = function(event){
var event=event || window.event;
if(state == RUNNING){
var x = event.offsetX;
var y = event.offsetY;
//修改我方飞机的坐标值
hero.x = x - hero.width/2;
hero.y = y - hero.height/2;
}
}
// 创建子弹
var bullet=new Image();
bullet.src="img/bullet111.png";
var BULLETS={
imgs:bullet,
width:9,
height:21
}
//子弹的构造函数
function Bullet(config){
this.imgs=config.imgs;
this.width=config.width;
this.height=config.height;
// 定义子弹的坐标
this.x=hero.x + hero.width / 2-this.width / 2 ;
this.y=hero.y - this.height;
this.paint=function(){
// context.drawImage(this.imgs,this.x-15,this.y)
context.drawImage(this.imgs,this.x+3,this.y)
};
this.step=function (){
this.y-=10;
};
// 定义子弹碰撞属性 ,false表示没有碰撞
this.candel=false;
// 定义子弹碰撞方法,碰撞之后他的碰撞属性为true
this.bang=function(){
this.candel=true;
}
}
// 让所有new的子弹对象放到一个数组中
var bullets=[];
// 通过遍历绘制子弹;最后在定时器中调用
function bulletdPaint(){
for(var i=0;i<bullets.length;i++){
//调用数组对象中的方法paint()
bullets[i].paint();
}
}
// 通过遍历调用子弹的运动;
function bulletdStep(){
for(var i=0;i<bullets.length;i++){
bullets[i].step();
}
}
// 增加子弹的删除函数
function bulletDel(){
for(var i=0;i<bullets.length;i++){
if(bullets[i].candel || bullets[i].y < -bullets[i].height){
//调用数组中的方法
bullets.splice(i,1)
}
}
}
敌方飞机
var enemy1=[];//小飞机
enemy1[0]=new Image();
enemy1[0].src="img/enemy1.png";
enemy1[1]=new Image();
enemy1[1].src='img/enemy1_down1.png';
enemy1[2]=new Image();
enemy1[2].src='img/enemy1_down2.png';
enemy1[3]=new Image();
enemy1[3].src='img/enemy1_down3.png';
enemy1[4]=new Image();
enemy1[4].src='img/enemy1_down4.png';
var enemy2=[];//中飞机
enemy2[0]=new Image();
enemy2[0].src="img/enemy2.png";
enemy2[1]=new Image();
enemy2[1].src="img/enemy2_down1.png";
enemy2[2]=new Image();
enemy2[2].src="img/enemy2_down2.png";
enemy2[3]=new Image();
enemy2[3].src="img/enemy2_down3.png";
enemy2[4]=new Image();
enemy2[4].src="img/enemy2_down4.png";
var enemy3 = []; //大飞机
enemy3[0] = new Image();
enemy3[0].src = "img/enemy3_n1.png"
enemy3[1] = new Image();
enemy3[1].src = "img/enemy3_n2.png"
enemy3[2] = new Image();
enemy3[2].src = "img/enemy3_down1.png"
enemy3[3] = new Image();
enemy3[3].src = "img/enemy3_down2.png"
enemy3[4] = new Image();
enemy3[4].src = "img/enemy3_down3.png"
enemy3[5] = new Image();
enemy3[5].src = "img/enemy3_down4.png"
enemy3[6] = new Image();
enemy3[6].src = "img/enemy3_down5.png"
enemy3[7] = new Image();
enemy3[7].src = "img/enemy3_down6.png"
// 敌方飞机的初始化数据
var ENEMY1={
imgs:enemy1,
length:enemy1.length,
width:57,
height:51,
type:1,
frame:1,
life:1,
score:1
}
var ENEMY2={
imgs:enemy2,
length:enemy2.length,
width:69,
height:95,
type:2,
frame:1,
life:5,
score:5
}
var ENEMY3={
imgs:enemy3,
length:enemy3.length,
width:165,
height:261,
type:3,
frame:2,
life:15,
score:20
}
// 敌方飞机的构造函数
function Enemy(config){
this.imgs=config.imgs;
this.length=config.length;
this.width=config.width;
this.height=config.height;
this.type=config.type;
this.frame=config.frame;
this.life=config.life;
this.score=config.score;
// 定义敌方飞机的坐标
this.x=Math.random()*(WIDTH-this.width);
this.y=-this.height;
//定义下标
this.startIndex=0;
//定义碰撞属性,没有碰撞为false
this.down=false;
//定义是否爆炸完成的属性
this.candel=false;
//定义绘制方法
this.paint=function(){
context.drawImage(this.imgs[this.startIndex],this.x,this.y);
};
//定义运动方法
this.step = function(){
if(!this.down){
// 大飞机的下标是在0和1之间进行切换
this.startIndex ++;
this.startIndex = this.startIndex % this.frame;
this.y += 2;
}
else{ //飞机发生碰撞以后
this.startIndex ++;
if(this.startIndex == this.length){
this.candel = true;
this.startIndex = this.length - 1;
}
}
}
//是否被碰撞的方法
this.checkHit=function(wo){//判断四个边
return wo.y + wo.height > this.y
&& wo.x + wo.width > this.x
&& wo.y < this.y + this.height
&& wo.x < this.x + this.width;
}
//敌方飞机碰撞以后的方法
this.bang=function(){
this.life--;
if(this.life == 0){
this.down=true;
score +=this.score;
document.getElementById("score02").innerHTML=score;
}
}
}
// 创建数组存放敌方飞机
var enemise=[];
// 创建函数,往数组中添加数据
function enterEnemise(){
//定义一个变量存放随机数
var rand=Math.floor(Math.random()*100)
if(rand < 10){
//添加小飞机
enemise.push(new Enemy(ENEMY1));
}else if(rand < 55 && rand > 50){
//添加中飞机
enemise.push(new Enemy(ENEMY2));
}else if(rand == 88){
//添加大飞机
//大飞机尤其只有一个
//并且把大飞机放在数组的第一位
if(enemise[0].type != 3 && enemise.length > 0){
enemise.splice(0,0,new Enemy(ENEMY3));
}
}
}
创建函数绘制敌方飞机(因为敌方飞机在数组中,所以要循环遍历画出)
function enemyPaint(){
for(var i=0;i<enemise.length;i++){
enemise[i].paint();
}
}
// 创建函数敌方飞机的运动
function enemyStep(){
for(var i=0;i<enemise.length;i++){
enemise[i].step();
}
}
// 创建函数删除敌方飞机
function delenemy(){
for(var i=0;i<enemise.length;i++){
if(enemise[i].y > HEIGHT || enemise[i].candel){
enemise.splice(i,1)
}
}
}
// 绘制碰撞以后的函数
function hitEnemise(){
for(var i = 0;i< enemise.length;i++){
// 如果我方飞机撞到了敌方飞机以后
if(enemise[i].checkHit(hero)){
enemise[i].bang();
hero.bang()
}
// 子弹如果碰到敌方飞机以后
for(var j = 0;j<bullets.length;j++){
if(enemise[i].checkHit(bullets[j])){
enemise[i].bang();
bullets[j].bang();
}
}
}
}
// 分数和生命值
function scoreText(){
context.font="30px bold"
context.fillText("score:"+score,10,30)
context.fillText("life:"+life,300,30)
}
游戏暂停与结束
//调用画布的鼠标移出事件,改变状态
canvas.οnmοuseοut=function(){
if(state == RUNNING){
state = PAUSE;
}
}
canvas.οnmοuseοver=function(){
if(state == PAUSE){
state = RUNNING;
}
}
暂停图片
var pause=new Image()
pause.src="img/game_pause_nor.png"
// 游戏结束
function gameover(){
context.font="50px bold"
context.fillText("GAME OVER !!!",80,300)
}
定时器调用方法
setInterval(function(){
//背景图片无论在哪个状态都有背景图片以及它的动态效果
sky.paint();
sky.step();
if(state==START){//第一阶段
context.drawImage(logo,35,0);
document.getElementById("game_over").style.display="none";
}else if(state == STARTING){//第二阶段
loading.paint();
loading.step();
}else if(state == RUNNING){//第三状态
//绘制我放飞机
hero.paint();
//我方飞机的运动
hero.step();
// 我方飞机的射击方法
hero.shoot();
//子弹的绘制
bulletdPaint();
//子弹的运动
bulletdStep();
//子弹的删除
bulletDel();
//创建敌方飞机
enterEnemise()
//绘制敌方飞机
enemyPaint();
//绘制敌方飞机的运动
enemyStep();
//删除敌方飞机
delenemy();
//判断是否撞击
hitEnemise();
//绘制分数和生命值
scoreText()
}else if(state == PAUSE){
sky.paint();
sky.step();
hero.paint();
bulletdPaint();
enemyPaint();
scoreText()
context.drawImage(pause,220,300)
}else if(state == GAMEOVER){
sky.paint();
sky.step();
hero.paint();
bulletdPaint();
enemyPaint();
scoreText();
gameover();
document.getElementById("game_over").style.display="block"; }
},50)
开始界面
游戏中与敌方飞机大战的界面
游戏结束时嘲讽重开界面~~