<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
canvas{
border: 1px solid pink;
/* margin: 0 auto; */
position: absolute;
left: 0;
right: 0;
margin: auto;
}
</style>
</head>
<body>
<canvas width="480" height="852"></canvas>
<script>
// 0. 数据初始化
var canvas = document.getElementsByTagName('canvas')[0];
var ctx = canvas.getContext('2d');
var ready = 0;
var loading = 1;
var running = 2;
var pause = 3;
var over = 4;
// 当前游戏阶段的判定
var state = ready;
// 游戏生命值
var life = 3;
// 游戏分数
var score = 0;
// 画布宽高
var width = 480;
var height = 852;
// 1. 准备阶段 ready
// 1. 绘制运动的背景图片
// 1.1 创建背景图片对象
var bg = new Image();
bg.src = 'img/background.png';
// 1.2 确定当前背景图片的绘制位置、绘制大小的信息
var bgParam = {
bg:bg,
x:0,
y:0,
width:480,
height:852
}
// 1.3创建一个构造函数 用来实例化背景图片对象
function Bg(param){
this.bg = param.bg;
this.x = param.x;
this.y = param.y;
this.width = param.width;
this.height = param.height;
// 交替图片的坐标位置
this.y1 = -this.height;
// 1. 绘制
this.paint = function(){
ctx.drawImage(this.bg,this.x,this.y,this.width,this.height);
ctx.drawImage(this.bg,this.x,this.y1,this.width,this.height);
}
// 2. 运动
this.sport = function(){
this.y += 5;
this.y1 += 5;
// 交换图片
if(this.y >= this.height){
this.y = - this.height;
}
if(this.y1 >= this.height){
this.y1 = -this.height;
}
}
}
var bgObj = new Bg(bgParam);
// 2. 绘制logo
// 2.1 创建logo图片
var logo = new Image();
logo.src = 'img/start.png';
// 2.2 定义logo初始化信息
var logoParam = {
logo:logo,
x:0,
y:0,
width:400,
height:654
}
// 2.3 创建构造函数
function Logo(param){
this.logo = param.logo;
this.x = param.x;
this.y = param.y;
this.width = param.width;
this.height = param.height;
// 绘制
this.paint = function(){
ctx.drawImage(this.logo,this.x,this.y,this.width,this.height);
}
}
var logoObj = new Logo(logoParam);
// 点击画布进入到下一个阶段 loading
canvas.onclick = function(){
if(state === ready){
state = loading;
}
}
// 暂停
canvas.onmouseleave=function(){
if(state==running){
state=pause;
pauseObj.paint()
}
}
var pauseImg='img/game_pause_nor.png'
pause=new Image()
pause.src=pauseImg
var pauseParam={
pause:pause,
x:230,
y:426,
width:60,
height:45
}
function Pause(param){
this.pause=param.pause;
this.width=param.width;
this.height=param.height;
this.x=param.x;
this.y=param.y
this.paint=function(){
ctx.drawImage(this.pause,this.x,this.y,this.width,this.height);
}
}
var pauseObj = new Pause(pauseParam);
// 开始
canvas.onmouseenter=function(){
if(state==pause){
state=running;
}
}
// 2. 游戏加载阶段 loading
// 2.1. 进场图片
var imgArr = ['img/game_loading1.png','img/game_loading2.png','img/game_loading3.png','img/game_loading4.png'];
var imgLoading = [];
for(var i = 0;i<imgArr.length;i++){
imgLoading[i] = new Image();
imgLoading[i].src = imgArr[i];
}
console.log(imgLoading);//
// 绘制完进场图片马上进入下一阶段 running
// 2.3 定义图片信息
var loadingParam = {
imgLoading:imgLoading,
width:186,
height:38
}
function Loading(param){
this.imgLoading = param.imgLoading;
this.width = param.width;
this.height = param.height;
this.x = 0;
this.y = height - param.height;
// 定义绘制图片的下标
this.index = 0;
// 定义一个属性 用来判断定时器的执行次数
this.time = 0;
this.paint = function(){
ctx.drawImage(this.imgLoading[this.index],this.x,this.y,this.width,this.height);
}
this.sport = function(){
this.time++;
if(this.time % 5 == 0){
this.index ++;
if(this.index === this.imgLoading.length){
// 绘制图片超过整体数量时 进入到下一个阶段
state = running;
}
}
}
}
var loadingObj = new Loading(loadingParam);
// 3. 游戏进行中 running
// 3.1 绘制我方飞机
var heroArr = ['img/hero1.png','img/hero2.png','img/hero_blowup_n1.png','img/hero_blowup_n2.png','img/hero_blowup_n3.png','img/hero_blowup_n4.png']
var heroPlane = [];
for(var i = 0;i<heroArr.length;i++){
heroPlane[i] = new Image();
heroPlane[i].src = heroArr[i];
}
var heroParam = {
heroPlane:heroPlane,
width:99,
height:124
}
function Hero(param){
this.heroPlane = param.heroPlane;
this.width = param.width;
this.height = param.height;
this.x = width/2 - this.width/2;
this.y = height - this.height;
// 切换图片的下标
this.index = 0;
// 判断飞机是否被撞击
this.down = false;
this.time = 0;
// 绘制
this.paint = function(){
ctx.drawImage(this.heroPlane[this.index],this.x,this.y,this.width,this.height);
}
this.sport = function(){
// 我方飞机是否被撞击了
// 1. 我方飞机没有被撞击
if(!this.down){
if(this.index === 0){
this.index = 1;
}else {
this.index = 0;
}
}else{
// 2. 我方飞机被撞击了
this.index ++;
if(this.index === this.heroPlane.length){
life --;
if(life == 0){
state = over;
// 游戏结束之后 让飞机停留在冒烟状态
this.index = this.heroPlane.length -1;
}else{
heroObj = new Hero(heroParam);
}
}
}
}
this.shoot = function(){
this.time ++;
if(this.time % 2 === 0){
bullets.push(new Bullet(bulletParam));
}
}
}
var heroObj = new Hero(heroParam);
// 3.1.1 给画布绑定移动事件 飞机跟着鼠标移动
canvas.onmousemove = function(e){
if(state === running){
// 获取鼠标移动后的位置
heroObj.x = e.offsetX - heroObj.width/2;
heroObj.y = e.offsetY - heroObj.height/2;
}
}
// 3.2 子弹
// 3.2.1 创建子弹图片
var bullet = new Image();
bullet.src = 'img/bullet1.png';
var bulletParam = {
bullet:bullet,
width:9,
height:21
}
function Bullet(param){
this.bullet = param.bullet;
this.width = param.width;
this.height = param.height;
this.x = heroObj.x + heroObj.width/2 - this.width/2;
this.y = heroObj.y - this.height - 10;
// 判断子弹是否碰撞到了敌机
this.down = false;
// 绘制
this.paint = function(){
ctx.drawImage(this.bullet,this.x,this.y,this.width,this.height);
}
// 运动
this.sport = function(){
// this.x = heroObj.x + heroObj.width/2 - this.width/2;
this.y -= 25;
}
}
// 只创建一个子弹对象 发射出去就没有了
// var bulletObj = new Bullet(bulletParam);
// 存储子弹对象
var bullets = [];
// 绘制子弹
function bulletsPaint(){
for(var i = 0;i<bullets.length;i++){
bullets[i].paint();
}
}
function bulletsSport(){
for(var i = 0;i<bullets.length;i++){
bullets[i].sport();
}
}
// 删除子弹
// 1. 子弹飞出屏幕外面
// 2. 子弹敌机碰撞了
function bulletsDelete(){
for(var i = 0;i<bullets.length;i++){
if(bullets[i].y < - this.height||bullets[i].down){
bullets.splice(i,1);
}
// if(bullets[i].down){
// bullets.splice(i,1);
// }
}
}
// 3.3 敌方飞机
// 3.3.1 小号飞机
var enemy1Arr = ['img/enemy1.png','img/enemy1_down1.png','img/enemy1_down2.png','img/enemy1_down3.png','img/enemy1_down4.png'] ;
// 3.3.2 中号飞机
var enemy2Arr=['img/enemy2.png','img/enemy2_down1.png','img/enemy2_down2.png','img/enemy2_down3.png','img/enemy2_down4.png'];
// 3.3.3 大号飞机
var enemy3Arr=['img/enemy3_n1.png','img/enemy3_n2.png','img/enemy3_hit.png','img/enemy3_down1.png','img/enemy3_down2.png','img/enemy3_down3.png','img/enemy3_down4.png','img/enemy3_down5.png','img/enemy3_down6.png']
var enemyPlane1 = [];
//小号飞机
for(var i=0;i<enemy1Arr.length;i++){
enemyPlane1[i] = new Image();
enemyPlane1[i].src = enemy1Arr[i];
}
// 小号飞机信息
var enemy1 = {
enemyPlane1:enemyPlane1,
width:57,
height:51,
life:3
}
var enemyPlane2 = [];
// 中号飞机
for(var j=0;j<enemy2Arr.length;j++){
enemyPlane2[j]=new Image();
enemyPlane2[j].src=enemy2Arr[j]
}
var enemy2={
enemyPlane2:enemyPlane2,
width:69,
height:95,
life:5
}
var enemyPlane3 = [];
// 大号飞机
for(var n=0;n<enemy3Arr.length;n++){
enemyPlane3[n]=new Image();
enemyPlane3[n].src=enemy3Arr[n]
}
var enemy3={
enemyPlane3:enemyPlane3,
width:169,
height:258,
life:10
}
// 小号敌机的构造函数
function Enemy1(param){
this.enemyPlane1 = param.enemyPlane1;
this.width = param.width;
this.height = param.height;
this.life = param.life;
this.x = Math.random()*(width - this.width);
this.y = - this.height;
this.index = 0;
// 判断敌机是否发生碰撞
this.down = false;
// 是否爆照完成
this.bang = false;
this.paint = function(){
ctx.drawImage(this.enemyPlane1[this.index],this.x,this.y,this.width,this.height);
}
this.sport = function(){
if(!this.down){
// 当前敌机未被碰撞时
this.y +=8;
}else{
this.y+=5;
if(this.life<=0){
this.index ++;
if(this.index === this.enemyPlane1.length){
this.index = this.enemyPlane1.length -1;
this.bang = true;
score+=3
}
}
}
}
// 判断是否被碰撞
this.hit = function(obj){
return obj.x + obj.width >= this.x && obj.x <= this.x + this.width &&
obj.y <= this.y + this.height && obj.y + obj.height >= this.y;
}
}
// 中号
function Enemy2(param){
this.enemyPlane2 = param.enemyPlane2;
this.width = param.width;
this.height = param.height;
this.life = param.life;
this.x = Math.random()*(width - this.width);
this.y = - this.height;
this.index = 0;
// 判断敌机是否发生碰撞
this.down = false;
// 是否爆照完成
this.bang = false;
this.paint = function(){
ctx.drawImage(this.enemyPlane2[this.index],this.x,this.y,this.width,this.height);
}
this.sport = function(){
if(!this.down){
// 当前敌机未被碰撞时
this.y +=8;
}else{
this.y+=5;
if(this.life<=0){
this.index ++;
if(this.index === this.enemyPlane2.length){
this.index = this.enemyPlane2.length -1;
this.bang = true;
score+=5
}
}
}
}
// 判断是否被碰撞
this.hit = function(obj){
return obj.x + obj.width >= this.x && obj.x <= this.x + this.width &&
obj.y <= this.y + this.height && obj.y + obj.height >= this.y;
}
}
// 大号
function Enemy3(param){
this.enemyPlane3 = param.enemyPlane3;
this.width = param.width;
this.height = param.height;
this.life = param.life;
this.x = Math.random()*(width - this.width);
this.y = - this.height;
this.index = 0;
// 判断敌机是否发生碰撞
this.down = false;
// 是否爆照完成
this.bang = false;
this.paint = function(){
ctx.drawImage(this.enemyPlane3[this.index],this.x,this.y,this.width,this.height);
}
this.sport = function(){
if(!this.down){
// 当前敌机未被碰撞时
this.y +=8;
}else{
this.y+=5;
if(this.life<=0){
this.index ++;
if(this.index === this.enemyPlane3.length){
this.index = this.enemyPlane3.length -1;
this.bang = true;
score+=10
}
}
}
}
// 判断是否被碰撞
this.hit = function(obj){
return obj.x + obj.width >= this.x && obj.x <= this.x + this.width &&
obj.y <= this.y + this.height && obj.y + obj.height >= this.y;
}
}
//
var enemies = [];
var time=0
function pushEnemy (){
time++;
var random = Math.random();
if(random < 0.5){
if(time%8==0){
enemies.push(new Enemy1(enemy1));
}
}else if(random < 0.8&&random>=0.5){
// 中号飞机
if(time%9==0){
enemies.push(new Enemy2(enemy2))
}
}else{
// 大号飞机
if(time%10==0){
enemies.push(new Enemy3(enemy3))
}
}
}
// 绘制、运动飞机对象
function enemyPaint(){
for(var i=0;i<enemies.length;i++){
enemies[i].paint();
}
}
function enemySport(){
for(var i=0;i<enemies.length;i++){
enemies[i].sport();
}
}
function enemyDelete(){
for(var i = 0;i<enemies.length;i++){
if(enemies[i].y >= height||enemies[i].bang){
enemies.splice(i,1);
}
}
}
// 如何检测每一个敌机是否被(每一个子弹 hero)碰撞
function checkHit() {
this.down=false
for(var i = 0;i<enemies.length;i++){
// 子弹和敌机撞击
for(var j = 0;j<bullets.length;j++){
if(enemies[i].hit(bullets[j])){
bullets[j].down = true;
enemies[i].life--;
}
if(enemies[i].life==0){
enemies[i].down = true;
}
}
// 敌机和hero
if(enemies[i].hit(heroObj)){
enemies[i].down= true;
heroObj.down = true;
}
}
}
// 分数,生命值
function scoreText() {
ctx.font = "30px bold"
ctx.fillText("score:" + score, 10, 30);
ctx.fillText("life:" + life, 300, 30);
};
// 结束
function gameoverfn() {
ctx.font = "50px bold"
ctx.fillText("GAME OVER !!!", 80, 300);
};
var timer=null
// 在定时器中绘制图像
timer = setInterval(function(){
bgObj.paint();
bgObj.sport();
// logoObj.paint();
if(state == ready){
ctx.drawImage(logo,0,0,480,852);
}else if(state === loading){
// 绘制进场图片
loadingObj.paint();
loadingObj.sport();
}else if(state===pause){
bulletsPaint();
heroObj.paint();
enemyPaint();
pauseObj.paint()
} else if(state === running){
heroObj.paint();
heroObj.sport();
heroObj.shoot();
// 绘制子弹
// bulletObj.paint();
// bulletObj.sport();
bulletsPaint();
bulletsSport();
// 绘制敌机
pushEnemy();
enemyPaint();
enemySport();
bulletsDelete();
enemyDelete();
checkHit();
scoreText();
}else if(state === over){
heroObj.paint();
gameoverfn()
}
},60)
</script>
</body>
</html>