js实现飞机大战游戏


Posted in Javascript onAugust 26, 2020

本文实例为大家分享了js实现飞机大战游戏的具体代码,供大家参考,具体内容如下

CSS部分的代码:

<style>
  * {
    margin: 0px;
    padding: 0px;
  }
 canvas{
 border: 1px solid #000;
 display: block;
 margin: auto;
 }
</style>

JavaScript代码:

<!-- 先创建一个画布 -->
<canvas id="canvas" width="480" height="640"></canvas>

<script>
 var canvas = document.getElementById("canvas");
  var context = canvas.getContext("2d");

  // 0游戏初始化
  // 0.1定义游戏开始的五个阶段
  var START = 0;
  var STARTING = 1;
  var RUNNING = 2;
  var PAUSE = 3;
  var GAMEOVER = 4;

  // 0.2 定义一个自己的状态,时刻去和上面的五个状态作比较

  // 0.3 页面加载时
  var state = START;
  // 0.4 背景图片的宽和高
  var WIDTH = 480;
  var HEIGHT = 640;
  // 0.5 定义分数
  var score = 0;
  // 0.6 定义生命条数 
  var life = 3;


  // 1 游戏开始前
  // 1.1 加载背景图片
  // 1.1.1 背景图片的对象
  var bg = new Image();// 创建一个背景图片
  bg.src = "images/background.png";
  // 1.1.2 背景图片的数据
  var BG = {
    imgs: bg,
    width: 480,
    height: 852
  }

  // 1.1.3 背景图片的构造函数
  function Bg(config) {
    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);
  // console.log(sky);

  // 1.2 创建页面加载时的飞机大战图片
  var logo = new Image();
  logo.src = "images/start.png";


  // 2.游戏开始前
  // 2.1 开始前动画的对象
  var loadings = [];
  loadings[0] = new Image();
  loadings[0].src = "images/game_loading1.png";
  loadings[1] = new Image();
  loadings[1].src = "images/game_loading2.png";
  loadings[2] = new Image();
  loadings[2].src = "images/game_loading3.png";
  loadings[3] = new Image();
  loadings[3].src = "images/game_loading4.png";
  // 2.2 开始前加载的动画图片的数据
  var LOADINGS = {
    imgs: loadings,
    length: loadings.length,
    width: 186,
    height: 38
  }
  // 2.3 开始前动画的构造函数
  function Loading(config) {
    this.imgs = config.imgs;
    this.length = config.length;
    this.width = config.width;
    this.height = config.height;
    // 定义一个索引
    this.startIndex = 0;
    // 绘制
    this.paint = function () {
      context.drawImage(this.imgs[this.startIndex], 0, HEIGHT - this.height);
    }

    // 定义一个速度
    this.time = 0;
    this.step = function () {
      this.time++;
      if (this.time % 3 == 0) { 
        // 页面加载时下面小飞机运行的速度
        this.startIndex++;
      }

      // 当动画运行完成进入下一个阶段
      if (this.startIndex == this.length) {
        state = RUNNING;
      }
    }
  }
  // 2.4创建对象
  var loading = new Loading(LOADINGS);
  // 2.5绑定时间
  canvas.onclick = function () {
    if (state == START) {
      state = STARTING;
    }
  }

  // 3.1.1游戏开始时的图片
  var heros = [];
  heros[0] = new Image();
  heros[0].src = "images/hero1.png";
  heros[1] = new Image();
  heros[1].src = "images/hero2.png";

  heros[2] = new Image();
  heros[2].src = "images/hero_blowup_n1.png";
  heros[3] = new Image();
  heros[3].src = "images/hero_blowup_n2.png";
  heros[4] = new Image();
  heros[4].src = "images/hero_blowup_n3.png";
  heros[5] = new Image();
  heros[5].src = "images/hero_blowup_n4.png";
  // 3.1.2游戏开始时加载数据
  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 - 150;

    // 增加标识符
    this.down = false;  //表示一直没有撞击
    // 增加标识符
    this.candel = false; //表示撞击以后的动画是否运行完成,完成以后的恢复运行的状态

    // 定义绘制方法
    this.paint = function () {
      context.drawImage(this.imgs[this.startIndex], this.x, this.y)
    }
    // 定义运动的方法
    this.step = function () {
      // 两个状态
      // 1.正常运动状态
      // 2.碰撞以后的状态
      if (!this.down) {//正常运动状态
        // 没有发生撞击的时候 一直在0和1之间切换
        this.startIndex++;
        this.startIndex = this.startIndex % 2;
      }
      else {//撞击以后的状态
        // 脚标就要不停的加1,模拟出从碰撞到爆炸完成的动画
        this.startIndex++;
        // 判断是否完成撞击
        if (this.startIndex == this.length) {
          life--//爆炸一次生命值减1;
          if (life == 0) {
            state = GAMEOVER;
            // 如果死了,动画保存最后一张爆破的照片
            this.startIndex = this.length - 1;
          }
          else {
            hero = new Hero(HEROS);
          }
        }
      }
    }

    // 我方飞机增加射击方法
    this.time = 0;
    this.shoot = function () {
      this.time++;
      if (this.time % 2 == 0) {
        bullets.push(new Bullet(BULLET));
      }
    }
    // 撞击以后触发
    this.bang = function () {
      this.down = true;
    }
  }

  // 3.1.4我方飞机的对象 
  var hero = new Hero(HEROS);
  // 3.1.5绑定鼠标移动事件
  canvas.onmousemove = function (e) {
    if (state == RUNNING) {
      var x = e.offsetX;
      var y = e.offsetY;
      hero.x = x - hero.width / 2;
      hero.y = y - hero.height / 2;
    }
  }

  // 3.2 绘制子弹
  // 3.2.1 图片
  var bullet = new Image();
  bullet.src = "images/bullet1.png";
  // 3.2.2数据
  var BULLET = {
    imgs: bullet,
    width: 9,
    height: 21
  }
  // 3.2.3 子弹的构造函数
  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, this.y);
    }
    // 运动 往上运动
    this.step = function () {
      this.y -= 10;
    }
    this.candel = false;//表示撞击以后的动画是否运行完成,完成以后的恢复运行的状态
    this.bang = function () {
      this.candel = true;
    }
  }
  // 3.2.4 存放所有子弹
  var bullets = [];
  // 3.2.5 绘制所有子弹
  function bulletsPaint() {
    for (var i = 0; i < bullets.length; i++) {
      bullets[i].paint();
    }
  }
  // 3.2.6 绘制所有子弹的运动
  function bulletsStep() {
    for (var i = 0; i < bullets.length; i++) {
      bullets[i].step();
    }
  }
 // 3.2.7 删除子弹
 function bulletsDel(){
 for(var i = 0; i < bullets.length;i++){
  if(bullets[i].y < -bullets[i].height || bullets[i].candel){
  bullets.splice(i,1)
  }
 }
 // console.log(bullets)
 }
  // 3.3 敌方飞机
  // 3.3.1 敌方飞机的图片(3种)
  // 小号
  var enemy1 = [];
  enemy1[0] = new Image();
  enemy1[0].src = "images/enemy1.png";

  enemy1[1] = new Image();
  enemy1[1].src = "images/enemy1_down1.png";
  enemy1[2] = new Image();
  enemy1[2].src = "images/enemy1_down2.png";
  enemy1[3] = new Image();
  enemy1[3].src = "images/enemy1_down3.png";
  enemy1[4] = new Image();
  enemy1[4].src = "images/enemy1_down4.png";
  // 中号
  var enemy2 = [];
  enemy2[0] = new Image();
  enemy2[0].src = "images/enemy2.png";

  enemy2[1] = new Image();
  enemy2[1].src = "images/enemy2_down1.png";
  enemy2[2] = new Image();
  enemy2[2].src = "images/enemy2_down2.png";
  enemy2[3] = new Image();
  enemy2[3].src = "images/enemy2_down3.png";
  enemy2[4] = new Image();
  enemy2[4].src = "images/enemy2_down4.png";
  // 大号
  var enemy3 = [];
  enemy3[0] = new Image();
  enemy3[0].src = "images/enemy3_n1.png";
  enemy3[1] = new Image();
  enemy3[1].src = "images/enemy3_n2.png";

  enemy3[2] = new Image();
  enemy3[2].src = "images/enemy3_down1.png";
  enemy3[3] = new Image();
  enemy3[3].src = "images/enemy3_down2.png";
  enemy3[4] = new Image();
  enemy3[4].src = "images/enemy3_down3.png";
  enemy3[5] = new Image();
  enemy3[5].src = "images/enemy3_down4.png";
  enemy3[6] = new Image();
  enemy3[6].src = "images/enemy3_down5.png";
  enemy3[7] = new Image();
  enemy3[7].src = "images/enemy3_down6.png";

  // 3.2.2 数据
  var ENEMY1 = {
    imgs: enemy1,
    length: enemy1.length,
    width: 57,
    height: 51,
    type: 1, //增加标识符,区分飞机的种类。小号的设置成1
    frame: 1, //增加标识符,1种状态就为1,2种状态就为2
    life: 1, //增加标识符,被子弹打击的次数
    score: 1  //打倒一只的得分
  }
  var ENEMY2 = {
    imgs: enemy2,
    length: enemy2.length,
    width: 69,
    height: 95,
    type: 2, //增加标识符,区分飞机的种类。中号的设置成2
    frame: 1, //增加标识符,1种状态就为1,2种状态就为2
    life: 3, //增加标识符,被子弹打击的次数
    score: 5 //打倒一只的得分
  }
  var ENEMY3 = {
    imgs: enemy3,
    length: enemy3.length,
    width: 169,
    height: 258,
    type: 3, //增加标识符,区分飞机的种类。大号的设置成3
    frame: 2, //增加标识符,,1种状态就为1,2种状态就为2
    life: 10, //增加标识符,被子弹打击的次数
    score: 15  //打倒一只的得分
  }
  // 3.3.3 构造函数
  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.startIndex = 0
    this.down = false;  //表示一直没有撞击
    this.candel = false; //表示撞击以后的动画是否运行完成,完成以后的恢复运行的状态

    // 绘制坐标
    this.x = Math.random() * (WIDTH - this.width);
    this.y = -this.height;
    // 绘制的方法
    this.paint = function () {
      context.drawImage(this.imgs[this.startIndex], this.x, this.y);
    }
    // 运动方法
 this.step = function(){
  if(!this.down){  //正常
  // 小号的,中号 角标始终是0
  // 大号的是在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.bang = function(){
  this.life -- ;
  if(this.life == 0){
  this.down = true;
  score += this.score;
  }
 }
    // 检测是否撞击
 this.checkHit = function(wo){
  // 1.撞击到子弹
  // 2.撞击到我方飞机
  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;
 }
  }

  // 3.3.4 创建数组 存储敌方飞机
  var enemies = [];
  // 3.3.5 创建飞机
  function enterEnemies() {
    var num = Math.random();
    if (num < 0.1) {
      enemies.push(new Enemy(ENEMY1))
    } else if (num < 0.15) {
      enemies.push(new Enemy(ENEMY2))
    } else if (num < 0.16) {
      enemies.push(new Enemy(ENEMY3))
    }
  }
  // 3.3.6 绘制
  function paintEnemies() {
    for (var i = 0; i < enemies.length; i++) {
      enemies[i].paint();
    }
  }
  // 3.3.7 运动
  function stepEnemies() {
    for (var i = 0; i < enemies.length; i++) {
      enemies[i].step();
    }
  }
  // 3.3.8 删除
 function delEnemies(){
 for(var i = 0;i < enemies.length;i++){
  if(enemies[i].y > HEIGHT || enemies[i].candel){
  enemies.splice(i,1)
  }
 }
 }
  // 3.4 检测撞击
  function hitEnemies() {
    for (var i = 0; i < enemies.length; i++) {
      if (enemies[i].checkHit(hero)) {
        enemies[i].bang();
        hero.bang();
      }
      for (var j = 0; j < bullets.length; j++) {
        if (enemies[i].checkHit(bullets[j])) {
          enemies[i].bang();
          bullets[j].bang();
        }
      }
    }
  }
 // 3.5 我方飞机的生命和得分
 function paintText(){
 context.font = "bold 30px 微软雅黑";
 context.fillText("SCORE:" + score,10,30);
 context.fillText("LIFE:" + life,380,30)
 }

  // 4.暂停阶段
  canvas.onmouseover=function(){
    if(state==PAUSE){
      state=RUNNING;
    }
  }
  canvas.onmouseout=function(){
    if(state==RUNNING){
      state=PAUSE;
    }
  }
  var pause=new Image();
  pause.src="images/game_pause_nor.png"
  function paintdown(){
    context.drawImage(pause,220,300)
  }

  // 5.gameover阶段
  function paintOver(){
    context.font="bold 50px 微软雅黑";
    context.fillText("GAME OVER",110,300);
  }


  // 定时器加载,使图片缓慢往下面移动
  setInterval(function () {
    sky.paint();
    sky.step();
    if (state == START) {
      context.drawImage(logo, 40, 0);//绘制在正中间
    } else if (state == STARTING) {
      loading.paint();
      loading.step();
    } else if (state == RUNNING) {
      hero.paint();
      hero.step();
      hero.shoot();

      bulletsPaint();
      bulletsStep();
      bulletsDel();

      enterEnemies();
      paintEnemies();
      stepEnemies();
      delEnemies();
      hitEnemies();

      paintText();
    }else if(state==PAUSE){
      hero.paint();
      bulletsPaint();
      paintEnemies();
      paintText();
      paintdown();
    }else if(state==GAMEOVER){
      hero.paint();
      bulletsPaint();
      paintEnemies();
      paintText();
      paintdown();
      paintOver();
    }
  }, 100)
</script>

更多有趣的经典小游戏实现专题,分享给大家:

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
数组Array进行原型prototype扩展后带来的for in遍历问题
Feb 07 Javascript
js 操作select和option常用代码整理
Dec 13 Javascript
JS获取页面input控件中所有text控件并追加样式属性
Feb 25 Javascript
javascript实现颜色渐变的方法
Oct 30 Javascript
Jquery弹出层插件ThickBox的使用方法
Dec 09 Javascript
JavaScript文本框脚本编写的注意事项
Jan 25 Javascript
手机图片预览插件photoswipe.js使用总结
Aug 25 Javascript
基于Vue实例对象的数据选项
Aug 09 Javascript
详解Web使用webpack构建前端项目
Sep 23 Javascript
浅析从vue源码看观察者模式
Jan 29 Javascript
使用node搭建自动发图文微博机器人的方法
Mar 22 Javascript
js+canvas实现简单扫雷小游戏
Jan 22 Javascript
JS+Canvas实现五子棋游戏
Aug 26 #Javascript
Js Snowflake(雪花算法)生成随机ID的实现方法
Aug 26 #Javascript
uin-app+mockjs实现本地数据模拟
Aug 26 #Javascript
一篇文章带你搞懂Vue虚拟Dom与diff算法
Aug 25 #Javascript
微信小程序换肤功能实现代码(思路详解)
Aug 25 #Javascript
prettier自动格式化去换行的实现代码
Aug 25 #Javascript
Vue中 axios delete请求参数操作
Aug 25 #Javascript
You might like
CodeIgniter图像处理类的深入解析
2013/06/17 PHP
PHP对象相互引用的内存溢出实例分析
2014/08/28 PHP
php 运算符与表达式详细介绍
2016/11/30 PHP
PHP使用OB缓存实现静态化功能示例
2019/03/23 PHP
jquery ajax 登录验证实现代码
2009/09/23 Javascript
jQuery基础知识filter()和find()实例说明
2010/07/06 Javascript
Jquery选中或取消radio示例
2013/09/29 Javascript
Jquery创建一个层当鼠标移动到层上面不消失效果
2013/12/12 Javascript
浅析jquery的js图表组件highcharts
2014/03/06 Javascript
JQuery中ajax方法访问web服务实例
2015/07/18 Javascript
微信小程序获取手机系统信息的方法【附源码下载】
2017/12/07 Javascript
JS实现为动态创建的元素添加事件操作示例
2018/03/17 Javascript
详解iframe跨域的几种常用方法(小结)
2019/04/29 Javascript
简谈创建React Component的几种方式
2019/06/15 Javascript
javascript二维数组和对象的深拷贝与浅拷贝实例分析
2019/10/26 Javascript
2020京东618叠蛋糕js脚本(亲测好用)
2020/06/02 Javascript
python实现自动登录人人网并访问最近来访者实例
2014/09/26 Python
使用Python编写基于DHT协议的BT资源爬虫
2016/03/19 Python
如何在Python函数执行前后增加额外的行为
2016/10/20 Python
Python Socket编程详细介绍
2017/03/23 Python
Python类的继承和多态代码详解
2017/12/27 Python
python pandas获取csv指定行 列的操作方法
2019/07/12 Python
python GUI库图形界面开发之PyQt5窗口类QMainWindow详细使用方法
2020/02/26 Python
python/golang实现循环链表的示例代码
2020/09/14 Python
amazeui页面校验功能的实现代码
2020/08/24 HTML / CSS
Java的类可以定义为Protected或者Private得吗
2015/09/25 面试题
工厂厂长岗位职责
2013/11/08 职场文书
个人授权委托书范本
2014/09/14 职场文书
工作检讨书500字
2014/10/19 职场文书
放假通知范文
2015/04/14 职场文书
运动会通讯稿300字
2015/07/20 职场文书
2015年社区反邪教工作总结
2015/10/14 职场文书
JavaScript实现贪吃蛇游戏
2021/06/16 Javascript
动漫APP软件排行榜前十名,半次元上榜,第一款由腾讯公司推出
2022/03/18 杂记
微信告警的zabbix监控系统 监控整个NGINX集群
2022/04/18 Servers
python神经网络 tf.name_scope 和 tf.variable_scope 的区别
2022/05/04 Python