用画布写飞机大战
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>飞机大战</title>
</head>
<body>
<div style="margin: 0 auto; width: 480px; height: 852px; text-align:center;vertical-align:middle">
<canvas id="canvas" width="480px" height="852px"></canvas>
</div>
<script type="text/javascript">
var canvas = document.getElementById('canvas');
var context = canvas.getContext('2d');
// 获取canvas元素的高宽
const WIDTH = canvas.width;
const HEIGHT = canvas.height;
// 定义阶段
const START = 0;
const STARTTING = 1;
const RUNNING = 2;
const PAUSED = 3;
const GAMEOVER = 4;
//定义当前阶段变量
var state = 0;
var score = 0; // 游戏得分
var life = 3; //我方飞机的生命值
// 游戏开始
// 绘制背景图片
// 加载背景图片
var bg = new Image();
bg.src = 'img/background.png';
var BG = {
imgs:bg,
width : 480,
height : 852
}
// 创造一个背景的构造函数,动态效果创建两张
function Bg(config){
this.imgs = config.imgs;
this.width = config.width ;
this.height = config.height;
this.y1 = 0;
this.y2 = -this.height;
// 绘制图片
this.paint = function (ctx){
ctx.drawImage(this.imgs,0,this.y1);
ctx.drawImage(this.imgs,0,this.y2);
}
// 运动
this.step = function(){
this.y1++;
this.y2++;
if(this.y2 == 0){
this.y1 = -this.height;
}
if(this.y1 == 0 ){
this.y2 = - this.height;
}
}
}
// 创建背景对象
var sky = new Bg(BG);
// 创建logo
var logo = new Image();
logo.src = 'img/start.png';
//点击画布游戏进入加载
canvas.onclick = function(){
if(state == START){
state = STARTTING;
}
}
// 加载阶段
// 加载图片
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';
var LOADING = {
imgs : loadings,
width : 186,
height : 38,
sum : loadings.length
}
function Loading(config){
this.imgs = config.imgs;
this.width = config.width;
this.height = config.height;
this.sum = config.sum;
// 定义索引
this.frameIndex = 0;
// 绘制图片
this.paint = function(ctx){
ctx.drawImage(this.imgs[this.frameIndex],0,HEIGHT-this.height);
}
// 定义速度
this.speed = 0;
// 运动
this.step = function(){
this.speed++;
if(this.speed % 3 == 0){
this.frameIndex++;
}
if(this.frameIndex == 4){
state = RUNNING;
}
}
}
var loading = new Loading(LOADING);
// 游戏运行
// 我方飞机
// 加载我方
var heros = [];
heros[0] = new Image();
heros[0].src = 'img/hero1.png';
heros[1] = new Image();
heros[1].src = 'img/hero2.png';
heros[2] = new Image();
heros[2].src = 'img/hero_blowup_n1.png';
heros[3] = new Image();
heros[3].src = 'img/hero_blowup_n2.png';
heros[4] = new Image();
heros[4].src = 'img/hero_blowup_n3.png';
heros[5] = new Image();
heros[5].src = 'img/hero_blowup_n4.png';
// 我方飞机的数据
var HERO = {
imgs : heros,
width : 99,
height : 124,
sum : heros.length
}
// 创建我方飞机
function Hero(config){
this.imgs = config.imgs;
this.width = config.width;
this.height = config.height;
this.sum = config.sum;
// 定义索引
this.frameIndex = 0;
// 定义飞机坐标值
this.x = (WIDTH - this.width)/2;
this.y = HEIGHT - this.height - 30;
// 是否爆炸
this.down = false;
// 绘制
this.paint = function(ctx){
ctx.drawImage(this.imgs[this.frameIndex],this.x,this.y);
}
// 运动
this.step = function(){
if(this.down){//爆炸了
this.frameIndex ++;
if(this.frameIndex == this.sum){
this.frameIndex = this.sum - 1;
life --;
if(life == 0){
state = GAMEOVER;
}else{
hero = new Hero(HERO);
}
}
}else{
this.frameIndex = (++this.frameIndex) % 2;
}
}
// 射击
this.shoot = function(){
bullets[bullets.length] = new Bullet(BULLET);
}
// 撞击
this.canDown = function(){
this.down = true;
this.frameIndex = 2;
}
}
// 创建我方飞机对象
var hero = new Hero(HERO);
// canvas绑定mousemove事件
canvas.onmousemove = function(event){
if(state == RUNNING){
hero.x = event.offsetX - hero.width / 2;
hero.y = event.offsetY - hero.height / 2;
}
}
// 子弹
// 加载图片
var bullet = new Image();
bullet.src = 'img/bullet1.png';
// 子弹初始化数据
var BULLET = {
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 - 10;
// 子弹是否消失
this.del = false;
// 绘制
this.paint = function(ctx){
ctx.drawImage(this.imgs,this.x,this.y);
}
//移动
this.step = function(){
this.y -= 25;
}
}
// 存储子弹
var bullets = [];
// 绘制
function paintBullets(){
for(var i = 0; i < bullets.length; i++){
bullets[i].paint(context);
}
}
// 移动所有子弹
function stepBullets(){
for(var i = 0; i < bullets.length;i++){
bullets[i].step();
}
}
// 删除子弹
function delBullets(){
for(var i = 0; i < bullets.length;i++){
if(bullets[i].y <= -bullets[i].height || bullets[i].del){
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,
width : 57,
height : 51,
sum : enemy1.length,
type : 1,
life : 1,
score : 1
}
var ENEMY2 = {
imgs : enemy2,
width : 69,
height : 95,
sum : enemy2.length,
type : 2,
life : 5,
score : 3
}
var ENEMY3 = {
imgs : enemy3,
width : 169,
height : 258,
sum : enemy3.length,
type : 3,
life : 20,
score : 10
}
function Enemy(config){
this.imgs = config.imgs;
this.width = config.width;
this.height = config.height;
this.sum = config.sum;
this.type = config.type;
this.life = config.life;
this.score = config.score;
this.x = Math.random()* (WIDTH - this.width);
this.y = - this.height;
// 定义索引
this.frameIndex = 0;
// 是否爆炸
this.down = false;
// 是否删除
this.del = false;
// 绘制
this.paint = function(ctx){
ctx.drawImage(this.imgs[this.frameIndex],this.x,this.y);
}
this.step = function(){
if(this.down){
this.frameIndex++;
if(this.frameIndex == this.sum){
this.del = true;
score += this.score;
this.frameIndex = this.sum - 1;
}
}else{
switch (this.type) {
case 1: //小飞机
this.frameIndex = 0;
this.y += 10;
break;
case 2:
this.frameIndex = 0;
this.y += 5;
break;
case 3:
this.frameIndex = (this.frameIndex == 0) ? 1 : 0;
this.y ++;
break;
}
}
}
// 撞敌机
this.hit = function(compont){
return compont.y + compont.height >= this.y && compont.x + compont.width >= this.x && compont.y <= this.y + this.height && compont.x <= this.x + this.width;
}
this.canDown = function(){
this.life -- ;
if(this.life == 0){
this.down = true;
if(this.type == 3){
this.frameIndex = 2;
}else{
this.frameIndex = 1;
}
}
}
}
//创建敌机数组
var enemies = [];
function createEnemy(){
var num = Math.random()*50;
if(num <= 5){
enemies[enemies.length] = new Enemy(ENEMY1);
}else if (num <= 8) {
enemies[enemies.length] = new Enemy(ENEMY2);
}else if (num <= 10) {
if(enemies.length > 0 && enemies[0].type != 3){
enemies.splice(0,0,new Enemy(ENEMY3));
}
}
}
// 绘制敌机
function paintEnemies(){
for(var i = 0; i < enemies.length; i++){
enemies[i].paint(context);
}
}
// 移动敌机
function stepEnemies(){
for(var i = 0; i < enemies.length; i++){
enemies[i].step();
}
}
//移除飞出画布的敌机
function delEnemies() {
for(var i = 0; i < enemies.length; i++){
if(enemies[i].y == HEIGHT || enemies[i].del){
enemies.splice(i,1);
}
}
}
// 判断是否被撞击
function checkHit(){
for(var i = 0; i < enemies.length; i++){
if(enemies[i].hit(hero) && !hero.down && !enemies[i].down){
hero.canDown();
enemies[i].canDown();
}
// 被子弹打
for(var j = 0; j < bullets.length;j++){
if(enemies[i].hit(bullets[j])&& !enemies[i].down){
bullets[j].del = true;
enemies[i].canDown();
}
}
}
}
// 绘制得分和生命
function paintText(){
context.font = 'bold 24px 微软雅黑';
context.fillText('分数:'+score,10,30);
context.fillText('生命值:' + life,380,30);
}
// 鼠标离开画布
canvas.onmouseout = function(){
if(state ==RUNNING){
state = PAUSED;
}
}
// 回到画布
canvas.onmouseover = function(){
if(state == PAUSED){
state = RUNNING;
}
}
// 绘制暂停
var paused = new Image();
paused.src = 'img/game_pause_nor.png';
paused.width = 60;
paused.height = 45;
// 绘制GAMEOVWE
function paintOver(){
context.font = 'bold 48px 微软雅黑';
context.fillText('GAME OVER!',WIDTH/2-150,HEIGHT/2);
}
// 控制器
setInterval(function(){
sky.paint(context);
sky.step();
switch (state) {
case START:
context.drawImage(logo,20,0);
break;
case STARTTING:
loading.paint(context);
loading.step();
break;
case RUNNING:
hero.paint(context);
hero.step();
hero.shoot();
paintBullets();
stepBullets();
delBullets();
createEnemy();
paintEnemies();
stepEnemies();
delEnemies();
checkHit();
paintText();
break;
case PAUSED:
hero.paint(context);
paintBullets();
paintEnemies();
paintText();
context.drawImage(paused,WIDTH/2-paused.width/2,HEIGHT/2-paused.height/2);
break;
case GAMEOVER:
hero.paint(context);
paintBullets();
paintEnemies();
paintText();
paintOver();
break;
}
},30);
</script>
</body>
</html>