我的第一个项目 :飞机大战Vue版本塞到主页

Posted 养肥胖虎

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了我的第一个项目 :飞机大战Vue版本塞到主页相关的知识,希望对你有一定的参考价值。

好家伙,

 

这是未进行分包的vue版本的飞机大战

效果如下:

 

 

这里说明一下,大概使用逻辑是提供一个<div>

然后在这<div>中渲染游戏

 

游戏主界面代码如下:

 <template>
     <div>
     <h1>欢迎来到主页面</h1>
       <div ref="stage"></div>
     </div>
   </template>
   
   <script>
   export default 
     mounted() 
         //canvas初始化
         console.log("我被执行啦")
         let canvas = document.createElement(\'canvas\');
         this.$refs.stage.appendChild(canvas);
         canvas.width = 480;
         canvas.height = 650;
         canvas.ref = canvas;
         canvas.style = "border: 1px solid red;"
         const context = canvas.getContext("2d");
   
         //图片初始化方法
         function createImage(src) 
           let img;
           if (typeof src === "string") 
             img = new Image();
             img.src = require(\'./img/\' + src);
            else 
             img = [];
             for (let i = 0; i < src.length; i++) 
               img[i] = new Image();
               img[i].src = require(\'./img/\' + src[i]);
             
           
           return img;
         
         //createImage()方法测试样例
         // let bg = createImage("4.jpg")
         // bg.onload = function () 
         //   console.log("img加载完毕")
         //   context.drawImage(bg, 0, 0, 480, 650)
         // 
         const IMAGES = 
           b: "bullet1.png",
           bg: "4.png",
           copyright: "shoot_copyright.png",
           pause: "game_pause.png",
           loading_frame: ["game_loading1.png", "game_loading2.png", "game_loading3.png",
             "game_loading4.png"
           ],
           hero_frame_live: ["hero1.png", "hero2.png"],
           hero_frame_death: ["hero_blowup_n1.png", "hero_blowup_n2.png", "hero_blowup_n3.png",
             "hero_blowup_n4.png"
           ],
           e1_live: ["enemy1.png"],
           e1_death: ["enemy1_down1.png", "enemy1_down2.png", "enemy1_down3.png", "enemy1_down4.png"],
           e2_live: ["enemy2.png"],
           e2_death: ["enemy2_down1.png", "enemy2_down2.png", "enemy2_down3.png", "enemy2_down4.png"],
           e3_live: ["enemy3_n1.png", "enemy3_n2.png"],
           e3_death: ["enemy3_down1.png", "enemy3_down2.png", "enemy3_down3.png", "enemy3_down4.png",
             "enemy3_down5.png", "enemy3_down6.png"
           ],
           c1: "lanqiu.png"
         ;
         //初始化各个图片
         const b = createImage(IMAGES.b);
         const bg = createImage(IMAGES.bg);
         const copyright = createImage(IMAGES.copyright);
         const pause = createImage(IMAGES.pause);
         const loading_frame = createImage(IMAGES.loading_frame);
         const hero_frame = 
           live: createImage(IMAGES.hero_frame_live),
           death: createImage(IMAGES.hero_frame_death),
         ;
         const e1 = 
           live: createImage(IMAGES.e1_live),
           death: createImage(IMAGES.e1_death),
         ;
         const e2 = 
           live: createImage(IMAGES.e2_live),
           death: createImage(IMAGES.e2_death),
         ;
         const e3 = 
           live: createImage(IMAGES.e3_live),
           death: createImage(IMAGES.e3_death),
         ;
         const c1 = createImage(IMAGES.c1);
   
         //配置项:
         // 定义游戏的状态
         // 开始
         const START = 0;
         // 开始时
         const STARTING = 1;
         // 运行时
         const RUNNING = 2;
         // 暂停时
         const PAUSE = 3;
         // 结束时
         const END = 4;
         // 加载中
         const LOADINGING = 5;
   
         //state表示游戏的状态 取值必须是以上的五种状态
         let state = LOADINGING;
         // hero_frame.addEventListener("load", () => 
         //   state = START;
         // )
   
         pause.onload = function () 
           state = START;
           console.log(state)
         
   
         //score 分数变量 life 变量
         let score = 0;
         let life = 3;
   
         //天空类的配置项
         const SKY = 
           bg: bg,
           width: 480,
           height: 650,
           speed: 10,
         ;
   
         // 飞机加载界面的配置项
         const LOADING = 
           frame: loading_frame,
           width: 186,
           height: 38,
           x: 0,
           y: 650 - 38,
           speed: 400,
         ;
   
         // 英雄配置项
         const HERO = 
           frame: hero_frame,
           width: 99,
           height: 124,
           speed: 100,
         ;
   
         // 子弹配置项
         const BULLET = 
           img: b,
           width: 9,
           height: 21,
         ;
   
         //小敌机配置项
         const E1 = 
           type: 1,
           width: 57,
           height: 51,
           life: 10,
           score: 1,
           frame: e1,
           minSpeed: 20,
           maxSpeed: 10
         ;
         //中敌机配置项
         const E2 = 
           type: 2,
           width: 69,
           height: 95,
           life: 50,
           score: 5,
           frame: e2,
           minSpeed: 50,
           maxSpeed: 20
         ;
         //打敌机配置项
         const E3 = 
           type: 3,
           width: 169,
           height: 258,
           life: 100,
           score: 20,
           frame: e3,
           minSpeed: 100,
           maxSpeed: 100
         ;
         //奖励类配置项
         const C1 = 
           type: 4,
           width: 75,
           height: 75,
           life: 1,
           score: 1,
           img: c1,
           minSpeed: 5,
           maxSpeed: 10
         ;
         //正式代码
   
         //初始化奖励类
         class Award 
           constructor(config) 
             this.type = config.type;
             this.width = config.width;
             this.height = config.height;
             this.x = Math.floor(Math.random() * (480 - config.width));
             this.y = -config.height;
             this.life = config.life;
             this.score = config.score;
             this.img = config.img;
             this.live = true;
             this.speed = Math.floor(Math.random() * (config.minSpeed - config.maxSpeed + 1)) + config.maxSpeed;
             this.lastTime = new Date().getTime();
             this.deathIndex = 0;
             this.destory = false;
           
           move() 
             const currentTime = new Date().getTime();
             if (currentTime - this.lastTime >= this.speed) 
               if (this.live) 
                 this.y = this.y + 6;
                 this.lastTime = currentTime;
                else 
                 this.destory = true;
   
               
             
           
           paint(context) 
             context.drawImage(this.img, this.x, this.y, this.width, this.height);
           
           outOfBounds() 
             if (this.y > 650) 
               return true;
             
           
           hit(o) 
             let ol = o.x;
             let or = o.x + o.width;
             let ot = o.y;
             let ob = o.y + o.height;
             let el = this.x;
             let er = this.x + this.width;
             let et = this.y;
             let eb = this.y + this.height;
             if (ol > er || or < el || ot > eb || ob < et) 
               return false;
              else 
               return true;
             
           
           // collide() 
           //   this.life--;
           //   if (this.life === 0) 
           //     this.live = false;
           //     score += this.score;
           //   
           // 
         
   
         //
         //初始化一个子弹类
         class Bullet 
           constructor(config, x, y) 
             this.img = config.img;
             this.width = config.width;
             this.height = config.height;
             this.x = x;
             this.y = y;
             this.destory = false;
           
           //子弹绘制方法
           paint(context) 
             context.drawImage(this.img, this.x, this.y);
           
           //移动子弹 this.y--
           move() 
             this.y -= 8;
           
           outOfBounds() 
             //如果返回的是真的话 那么我们应该销毁掉这个子弹
             return this.y < -this.height;
           
           collide() 
             //让这颗子弹变成可销毁状态
             this.destory = true;
           
         
         //
   
         // 初始化一个敌机类
         class Enemy 
   
   
   
   
   
           
           constructor(config) 
             this.type = config.type;
             this.width = config.width;
             this.height = config.height;
             this.x = Math.floor(Math.random() * (480 - config.width));
             this.y = -config.height;
             this.life = config.life;
             this.score = config.score;
             this.frame = config.frame;
             this.img = this.frame.live[0];
             this.live = true;
             this.speed = Math.floor(Math.random() * (config.minSpeed - config.maxSpeed + 1)) + config.maxSpeed;
             this.lastTime = new Date().getTime();
             this.deathIndex = 0;
             this.destory = false;
           
           move() 
             const currentTime = new Date().getTime();
             if (currentTime - this.lastTime >= this.speed) 
               if (this.live) 
                 this.img = this.frame.live[0];
                 this.y++;
                 this.lastTime = currentTime;
                else 
                 this.img = this.frame.death[this.deathIndex++];
                 if (this.deathIndex === this.frame.death.length) 
                   this.destory = true;
                 
               
             
           
           paint(context) 
             context.drawImage(this.img, this.x, this.y);
           
           outOfBounds() 
             if (this.y > 650) 
               return true;
             
           
           hit(o) 
             let ol = o.x;
             let or = o.x + o.width;
             let ot = o.y;
             let ob = o.y + o.height;
             let el = this.x;
             let er = this.x + this.width;
             let et = this.y;
             let eb = this.y + this.height;
             if (ol > er || or < el || ot > eb || ob < et) 
               return false;
              else 
               return true;
             
           
           collide() 
             this.life--;
             if (this.life === 0) 
               this.live = false;
               score += this.score;
             
           
         
   
         //
         // 初始化一个英雄类
         class Hero 
           constructor(config) 
             this.width = config.width;
             this.height = config.height;
             this.x = (480 - config.width) / 2;
             this.y = 650 - config.height;
             this.frame = config.frame;
             this.frameLiveIndex = 0;
             this.frameDeathIndex = 0;
             this.lastTime = new Date().getTime();
             this.speed = config.speed;
             //当前展示的图片
             this.img = null;
             this.live = true;
             //子弹上次射击的时间
             this.lastShootTime = new Date().getTime();
             //子弹射击的间隔
             this.shootInterval = 50;
             //子弹夹数组
             this.bulletList = [];
             this.destory = false;
           
           judge() 
             const currentTime = new Date().getTime();
             if (currentTime - this.lastTime > this.speed) 
               if (this.live) 
                 this.img = this.frame.live[this.frameLiveIndex++ % this.frame.live.length];
                else 
                 //0 1 2 3 4
                 this.img = this.frame.death[this.frameDeathIndex++];
                 //到4的时候英雄死了
                 if (this.frameDeathIndex === this.frame.death.length) 
                   this.destory = true;
                 
               
               this.lastTime = currentTime;
             
           
           paint(context) 
             context.drawImage(this.img, this.x, this.y, this.width, this.height);
           
           //英雄可以射击子弹
           shoot() 
             //获取当前时间
             const currentTime = new Date().getTime();
             //飞机的位置
             if (currentTime - this.lastShootTime > this.shootInterval) 
               //在飞机的头部初始化一个子弹对象
               let bullet = new Bullet(BULLET, this.x + this.width / 2 - BULLET.width / 2, this.y - BULLET.height);
               //英雄飞机要认领这个子弹
               this.bulletList.push(bullet);
               //在网页上绘制一个子弹对象
               bullet.paint(context);
               //更新英雄射击时间
               this.lastShootTime = currentTime;
             
           
           collide() 
             //将活着标识符切换为false
             //活着 -> 爆炸中 -> 死亡(销毁)
             this.live = false;
           
         
         //
         // 初始化一个飞机界面加载类
         class Loading 
           constructor(config) 
             this.frame = config.frame;
             this.frameIndex = 0;
             this.width = config.width;
             this.height = config.height;
             this.x = config.x;
             this.y = config.y;
             this.speed = config.speed;
             this.lastTime = new Date().getTime();
           
           judge() 
             const currentTime = new Date().getTime();
             if (currentTime - this.lastTime > this.speed) 
               this.frameIndex++;
               if (this.frameIndex === 4) 
                 state = RUNNING;
               
               this.lastTime = currentTime;
             
           
           paint(context) 
             context.drawImage(this.frame[this.frameIndex], this.x, this.y);
           
         
   
   
         class Main 
           //一下全为全局变量或方法 (全局的!!)
           //初始化一个天空实例
           //主启动方法
           maingame() 
             const sky = new Sky(SKY);
             //初始化一个飞机界面加载实例
             const loading = new Loading(LOADING);
             //初始化一个英雄实例 英雄是会变的
             let hero = new Hero(HERO);
             //该变量中有所有的敌机实例
             let enemies = [];
             //该变量中存放所有的奖励实例
   
             let awards = [];
             //敌机产生的速率
             let ENEMY_CREATE_INTERVAL = 800;
             let ENEMY_LASTTIME = new Date().getTime();
   
             function stateControl() 
               //为canvas绑定一个点击事件 且他如果是START状态的时候需要修改成STARTING状态
               canvas.addEventListener("click", () => 
                 if (state === START) 
                   state = STARTING;
                 
               );
               // 为canvas绑定一个鼠标移动事件 鼠标正好在飞机图片的正中心
               canvas.addEventListener("mousemove", (e) => 
                 let x = e.offsetX;
                 let y = e.offsetY;
                 hero.x = x - hero.width / 2;
                 hero.y = y - hero.height / 2;
               );
               // 为canvas绑定一个鼠标离开事件 鼠标离开时 RUNNING -> PAUSE
               canvas.addEventListener("mouseleave", () => 
                 if (state === RUNNING) 
                   state = PAUSE;
                 
               );
               // 为canvas绑定一个鼠标进入事件 鼠标进入时 PAUSE => RUNNING
               canvas.addEventListener("mouseenter", () => 
                 if (state === PAUSE) 
                   state = RUNNING;
                 
               );
               //为canvas绑定一个屏幕移动触摸点事件 触碰点正好在飞机图片的正中心
               canvas.addEventListener("touchmove", (e) => 
                 // let x = e.pageX;
                 // let y = e.pageY;
                 console.log(e);
                 // let x = e.touches[0].clientX;
                 // let y = e.touches[0].clinetY;
                 let x = e.touches[0].pageX;
                 let y = e.touches[0].pageY;
                 // let x = e.touches[0].screenX;
                 // let y = e.touches[0].screenY;
                 let write1 = (document.body.clientWidth - 480) / 2;
                 let write2 = (document.body.clientHeight - 650) / 2;
                 hero.x = x - write1 - hero.width / 2;
                 hero.y = y - write2 - hero.height / 2;
   
                 // hero.x = x - hero.width / 2;
                 // hero.y = y - hero.height / 2;
                 console.log(x, y);
                 console.log(document.body.clientWidth, document.body.clientHeight);
                 e.preventDefault(); // 阻止屏幕滚动的默认行为
   
               )
             
             stateControl();
             // 碰撞检测函数
             //此处的碰撞检测包括 
             //1.子弹与敌机的碰撞
             //2.英雄与敌机的碰撞
             //3.英雄与随机奖励的碰撞
             function checkHit() 
               // 遍历所有的敌机
               for (let i = 0; i < awards.length; i++) 
                 //检测英雄是否碰到奖励类
                 if (awards[i].hit(hero)) 
                   //当然了,这个随机奖励的样式也要删了
                   awards.splice(i, 1);
                   //清除所有的敌机
                   // for (let i = 0; i < enemies.length; i++) 
                   //   enemies.splice(i, 1);
                   // 
                   enemies.length = 0;
   
                 
               
               for (let i = 0; i < enemies.length; i++) 
                 //检测英雄是否撞到敌机
                 if (enemies[i].hit(hero)) 
                   //将敌机和英雄的destory属性改为true
                   enemies[i].collide();
                   hero.collide();
                 
                 for (let j = 0; j < hero.bulletList.length; j++) 
                   enemies[i].hit(hero.bulletList[j]);
                   //检测子弹是否撞到敌机
                   if (enemies[i].hit(hero.bulletList[j])) 
                     //将敌机和子弹的destory属性改为true
                     enemies[i].collide();
                     hero.bulletList[j].collide();
                   
                 
               
             
             // 全局函数 隔一段时间就来初始化一架敌机/奖励
             function createComponent() 
               const currentTime = new Date().getTime();
               if (currentTime - ENEMY_LASTTIME >= ENEMY_CREATE_INTERVAL) 
                 let ran = Math.floor(Math.random() * 100);
                 if (ran < 55) 
                   enemies.push(new Enemy(E1));
                  else if (ran < 85 && ran > 55) 
                   enemies.push(new Enemy(E2));
                  else if (ran < 95 && ran > 85) 
                   enemies.push(new Enemy(E3));
                  else if (ran > 95) 
                   awards.push(new award(C1));
   
                 
   
                 ENEMY_LASTTIME = currentTime;
               
             
             // 全局函数 来判断所有的子弹/敌人组件 "负责移动"
             function judgeComponent() 
               for (let i = 0; i < hero.bulletList.length; i++) 
                 hero.bulletList[i].move();
               
               for (let i = 0; i < enemies.length; i++) 
                 enemies[i].move();
               
               for (let i = 0; i < awards.length; i++) 
                 awards[i].move();
               
             
             // 全局函数 来绘制所有的子弹/敌人组件 绘制score&life面板
             function paintComponent() 
               for (let i = 0; i < hero.bulletList.length; i++) 
                 hero.bulletList[i].paint(context);
               
               for (let i = 0; i < enemies.length; i++) 
                 enemies[i].paint(context);
               
               for (let i = 0; i < awards.length; i++) 
                 awards[i].paint(context);
               
               context.font = "20px 微软雅黑";
               context.fillStyle = "green";
               context.textAlign = "left";
               context.fillText("score: " + score, 10, 20);
               context.textAlign = "right";
               context.fillText("life: " + life, 480 - 10, 20);
               //重置样式
               context.fillStyle = "black";
               context.textAlign = "left";
             
             // 全局函数 来销毁所有的子弹/敌人组件 销毁掉英雄
             function deleteComponent() 
               if (hero.destory) 
                 life--;
                 hero.destory = false;
                 if (life === 0) 
                   state = END;
                  else 
                   hero = new Hero(HERO);
                 
               
               for (let i = 0; i < hero.bulletList.length; i++) 
                 if (hero.bulletList[i].outOfBounds() || hero.bulletList[i].destory) 
                   hero.bulletList.splice(i, 1);
                 
               
               for (let i = 0; i < enemies.length; i++) 
                 if (enemies[i].outOfBounds() || enemies[i].destory) 
                   enemies.splice(i, 1);
                 
               
             
   
             //当图片加载完毕时,需要做某些事情
             bg.addEventListener("load", () => 
               setInterval(() => 
                 switch (state) 
                   case START:
                     sky.judge();
                     sky.paint(context);
                     let logo_x = (480 - copyright.naturalWidth) / 2;
                     let logo_y = (650 - copyright.naturalHeight) / 2;
                     context.drawImage(copyright, logo_x, logo_y);
                     break;
                   case STARTING:
                     sky.judge();
                     sky.paint(context);
                     loading.judge();
                     loading.paint(context);
                     break;
                   case RUNNING:
                     sky.judge();
                     sky.paint(context);
                     hero.judge();
                     hero.paint(context);
                     hero.shoot();
                     createComponent();
                     judgeComponent();
                     deleteComponent();
                     paintComponent();
                     checkHit();
                     break;
                   case PAUSE:
                     let pause_x = (480 - pause.naturalWidth) / 2;
                     let pause_y = (650 - pause.naturalHeight) / 2;
                     context.drawImage(pause, pause_x, pause_y);
                     break;
                   case END:
                     //给我的画笔设置一个字的样式
                     //后面写出来的字都是这个样式的
                     context.font = "bold 24px 微软雅黑";
                     context.textAlign = "center";
                     context.textBaseline = "middle";
                     context.fillText("GAME_OVER", 480 / 2, 650 / 2);
                     break;
                 
               , 10);
             );
   
   
             //背景切换方法
             // function changebg() 
             //     console.log("changebg方法被触发")
             //     bg.src = "img/background.png"
             // 
           
         
         //
   
         //初始化一个天空类
         class Sky 
           constructor(config) 
             this.bg = config.bg;
             this.width = config.width;
             this.height = config.height;
             this.x1 = 0;
             this.y1 = 0;
             this.x2 = 0;
             this.y2 = -this.height;
             this.speed = config.speed;
             this.lastTime = new Date().getTime();
           
           //判断方法
           judge() 
             let currentTime = new Date().getTime();
             if (currentTime - this.lastTime > this.speed) 
               this.y1++;
               this.y2++;
               this.lastTime = currentTime;
             
             if (this.y2 === 0) 
               this.y1 = 0;
               this.y2 = -this.height;
             
           
           //绘图方法
           paint(context) 
             context.drawImage(this.bg, this.x1, this.y1, this.width, this.height);
             context.drawImage(this.bg, this.x2, this.y2, this.width, this.height);
           
         
         let main_1 = new Main()
         main_1.maingame();
       
     
   
   
   </script>
   
   <style>
   #stage 
     width: 480px;
     height: 650px;
     margin: 0 auto;
   
   </style>
   
   

 

雷电飞机大战游戏|基于Java开发实现雷电飞机大战游戏

作者主页:编程指南针

作者简介:Java领域优质创作者、CSDN博客专家 、掘金特邀作者、多年架构师设计经验、腾讯课堂常驻讲师

主要内容:Java项目、毕业设计、简历模板、学习资料、面试题库、技术互助

收藏点赞不迷路  关注作者有好处

文末获取源码 

项目编号:KS-034

前言:

 电脑游戏,是指在计算机上能够运转的游戏软件。这种软件具有较强的娱乐性。电脑游戏的创新和发展与硬件、软件的发展紧密相关。它能够给玩家提供一个虚拟的环境,使游戏带给了人们很多的享受和欢乐。雷电游戏因为操作简单,节奏明快,一直是纵轴射击游戏的经典之作。经常能够在手机或者计算机中见到这款游戏,深得广大玩家的喜爱,可以说是妇孺皆知的一款益智类游戏。

   本游戏基于Eclipse开发工具,以java作为编程语言,整个项目开发旨在模拟雷电游戏的飞机射击游戏。游戏界面的下部是玩家的飞机,可以根据按键控制子弹的发射,上部为敌方飞机,在界面中随机出现。在游戏过程当中,用户飞机的移动是被电脑键盘的方向键所控制的,在整个游戏过程当中,如果用户飞机的子弹与敌方飞机发生相撞时,敌方飞机就会有爆炸的效果产生。游戏中使用到的飞机、子弹均采用对应的类实现。

一,项目简介

我们在小时候都拥有属于自己的一台游戏机,里面形形色色大概有十来款游戏。像 “扫雷”、“推箱子”、“俄罗斯方块”等等,我们的童年有这些游戏陪伴我们是幸福的,令许多小伙伴都为之痴迷,即使现在,这些都是随处可见的休闲游戏。我之选择“雷电”游戏作为我的毕业设计,因为它可以代表一代人青春的回忆。

Java语言,实际上就是面向对象的编程语言。对于计算机编程者来说,使用Java最大的好处有两方面,一是就编写程序而言,非常的简单也容易使用,二是它的功能很强大。与此同时,面向对象理论得以很好的实现。“雷电”游戏的毕业设计使我对本科期间所学知识进行了巩固。

    目前常见的电脑游戏的类型有动作游戏、传统益智游戏、体育游戏、策略游戏、休闲游戏和角色扮演类游戏等。不同的类型的游戏有着自身的特点,每一种类型的游戏都有一定的支持人群。开发出一款良好的游戏,了解各种类型的基本特点是很有必要的。而“雷电”游戏就属于上述类型中的STG(射击类)游戏,STG(Shooting Game)类型游戏主要凭借远程武器与敌方开展模拟对抗,拥有绚丽的射击画面。

这个项目使我第一次全流程地独立完成整条链路的开发,对于我自己而言,是0-1的突破。万事开头难,有了这次完整项目开发的经历,以后再做游戏或者其它项目时就对全局有所把控,能够做到游刃有余。假如自己没有亲自动手设计这些,哪怕一次,就不能够真正的领会一个完整项目体系中的每个元素。在以后做一些大的项目时,就更不能对整体进行宏观思考,也就不能对具体项目中每一个细分的小模块进行合适的时间估计,导致项目开发超过预期时间,更有甚,不能完成。

大部分的射击类游戏都存在一定的相似性,雷电游戏也不存在特殊。其实就是一个周而复始的情形,一直到游戏结束才能够停止。游戏开始阶段接受玩家的输入并对这个输入办理,如果没有结束就会不断产生飞机,通过检查我方飞机的血条判断游戏是不是最终结束。

该雷电主要就是我方飞机与敌方飞机的射击比拼,首先需要有界面来装载整个项目,通过键盘的上、下、左、右键遥控自己的飞机,z、x键进行子弹发射的选择,然后是敌方飞机的出现方式,敌机子弹的生成,通过各个关卡,最后得出比赛的结果。

雷电游戏主要包括以下功能:

  1. 雷电游戏状态调整功能 :在游戏启动时,游戏会自动进行初始化的验证,若初始化成功后,界面会自动进行跳转,跳转到游戏开始界面,有开始、暂停、恢复游戏等选项。

    (2)雷电游戏难度的升级:当进入游戏后,随着时间越来越长,游戏难度会越来越大,界面中敌机增多,对飞机造成伤害的子弹增多,游戏难度增加,最后会遇到一个血条较长的怪兽,攻击其至血条为0时,自动过关跳转到下一关卡。

    (3)玩家对飞机的控制功能:玩家可以对飞机进行操控,通过前后左右键来控制飞机的飞行路线。

    (4)游戏界面绘画功能。

 关键技术

  1. 游戏美工。游戏中需要使用的游戏素材有自己控制的飞机、敌方飞机、游戏过程当中飞机所产生的子弹、飞机被命中的爆炸图片等。这些素材的选择尤为重要,游戏中清新亮丽的画面可以给玩家带来充足的美感和游戏体验。所以,在这个“雷电”游戏的素材选择中,应挑选一些立体感强的图片,给玩家更大的视觉冲击。
  2. 多线程技术的实现。多线程编程能够提供程序两个或两个以上并发执行任务的能力,极大改善程序的响应性能,有效提高资源的利用效率。采取Runnable接口的方法达到定义用户线程的功能,这样既不会对继承其他类有所变化,也不会改变实现其它接口。
  3. 用户飞机子弹与敌方飞机的相撞测试。包括自己控制的飞机与敌方飞机或子弹的相撞等。在这一过程中,将所有子弹对象的矩形区域与敌机对象的矩形区域逐个以此进行检测,如果出现重叠则说明子弹与敌机发生了碰撞。

(4)游戏地图滚动原理的实现。我们在坐火车时都产生过一种错觉:自己乘坐的火车没有发生移动,但如果旁边有其他火车发生移动,我们就会感到是自己的火车在移动。这种现象与飞机射击类游戏的地图原理类似,即通过背景图片的来回滚动,给游戏玩家一种是自己操纵的飞机向前飞行的感觉。

二,环境介绍

语言环境:Java:  jdk1.8

数据库:Mysql: mysql5.7

应用服务器:Tomcat:  tomcat8.5.31

开发工具:IDEA或eclipse

开发技术:JavaSwing 及多线程

三,系统展示

 

四,核心代码展示

package com.ideabobo.game.leidian;

import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Image;

import com.ideabobo.game.leidian.Boss;

public class Battle extends Role 
	private static Battle battle = new Battle();

	private int tamaIntCount;

	private float speed;

	private float oldx;

	private float oldy;

	public static float vx;

	public static float vy;
	
	public static boolean keygo = false;

	private float tv[] =  -1F, -7F, 0.0F, -8F, 1.0F, -7F ;

	public int power;

	public int powerMax;
	


	public Battle() 
		super(GamePanel.heroImage);
		speed = 3F;
		tamaIntCount = 0;
		x = ((float) app.getWidth() - WIDTH) / 2.0F;
		y = (float) app.getHeight() - HEIGHT * 2.0F;
		power = 600;
		powerMax = power;
	

	public static Battle getInstance() 
		return battle;
	

	public void move() 
		oldx = x;
		oldy = y;
		if (Key.left) 
			if (Key.xkey)
				x -= (double) speed / 4D;
			else
				x -= speed;
			if (x <= 0.0F)
				x = 0.0F;
		
		if (Key.right) 
			if (Key.xkey)
				x += (double) speed / 4D;
			else
				x += speed;
			if (x + WIDTH >= (float) app.getWidth())
				x = (float) app.getWidth() - WIDTH;
		
		if (Key.down) 
			if (Key.xkey)
				y += (double) speed / 4D;
			else
				y += speed;
			if (y + HEIGHT >= (float) app.getHeight())
				y = (float) app.getHeight() - HEIGHT;
		
		if (Key.up) 
			if (Key.xkey)
				y -= (double) speed / 4D;
			else
				y -= speed;
			if (y <= 0.0F)
				y = 0.0F;
		
		//**//--///loonframewrk提供
		vx = x - oldx;
		vy = y - oldy;
		if (tamaIntCount > 0)
			tamaIntCount--;
		if (Key.zkey && tamaIntCount <= 0) 
			for (int i = 0; i < tv.length; i += 2) 
				GamePanel.addList(new BattleBasic(x + WIDTH / 2.0F, y, tv[i],
						tv[i + 1]));
				tamaIntCount = 8;
			
		
		if (Key.xkey && !Key.zkey && tamaIntCount <= 0) 
			GamePanel.addList(new BattleBeam(x + WIDTH / 2.0F, y, 0.0F, -8F));
			tamaIntCount = 2;
		
		if(Key.space)
			if(!keygo)
				GamePanel.skillCount--;
			
			app.skillAnime();
			
			if(GamePanel.skillCount < 0)
				GamePanel.skillCount = 0;
			
			if(GamePanel.skillCount>0)
				for (int i = 0; i < GamePanel.list.size(); i++) 
					Role chara1 = (Role) GamePanel.list.get(i);
					if(!(chara1 instanceof Battle) && chara1.x>0 && chara1.y>0 && !(chara1 instanceof BossA)  && !(chara1 instanceof BossB)  && !(chara1 instanceof BossC))
						GamePanel.list.remove(i);
					else if((chara1 instanceof BossA)  || (chara1 instanceof BossB)  || (chara1 instanceof BossC))
						Boss cb = (Boss)chara1;
						cb.power-=50;
					
				
			
			keygo = true;
		
		
		if(!Key.space)
			keygo = false;
		
	

	public boolean checkHit(Role chara) 
		if ((chara instanceof EnemyA) || (chara instanceof EnemyB)|| (chara instanceof EnemyC) || (chara instanceof EnemyShot)) 
			
			if ((x + WIDTH) - 14F > chara.x && x + 14F < chara.x + chara.WIDTH
					&& (y + HEIGHT) - 12F > chara.y
					&& y + 12F < chara.y + chara.HEIGHT) 
				//如果碰到敌人,敌人死亡
				chara.dead();
				//如果碰到子弹血量减少
				if (chara instanceof EnemyBeam)
					power--;
				
					
				power -= 50;
				if (power <= 0) 
					dead();
					//绘制爆炸图片
					GamePanel.burst = new Burst(x, y);
				
				return true;
			
		 else if ((chara instanceof Boss) && (x + WIDTH) - 14F > chara.x + 50F
				&& x + 14F < (chara.x + chara.WIDTH) - 50F
				&& (y + HEIGHT) - 12F > chara.y + 50F
				&& y + 12F < (chara.y + chara.HEIGHT) - 80F) 
			power--;
			if (power <= 0) 
				dead();
				GamePanel.burst = new Burst(x, y);
			
			return true;
		
		return false;
	

	public void setX(float x) 
		this.x = x;
	

	public void setY(float y) 
		this.y = y;
	

	public float getWidth() 
		return WIDTH;
	

	public float getHeight() 
		return HEIGHT;
	

	public float getX() 
		return x;
	

	public float getY() 
		return y;
	

	public Image getImage() 
		return img;
	

	public int getPower() 
		return power;
	

	public int getPowerMax() 
		return powerMax;
	

	public void setPower(int power) 
		this.power = power;
	

	public void drawPower(Graphics g) 
		g.setColor(Color.white);
		g.drawRect(380, 450, 50, 15);
		g.setColor(Color.red);
		g.fillRect(381, 451,
				(int) ((50D / (double) (float) powerMax) * (double) power) - 1,
				14);
	
	
	public void drawSkillCount(Graphics g)
		g.setColor(Color.white);
		Font font = new Font("宋体", 1, 20);
		g.setFont(font);
		g.drawString("全屏爆破:" + GamePanel.skillCount, 0, 450);
	


package com.ideabobo.game.leidian;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Image;

abstract class Boss extends Enemy 

	protected int powerMax;

	public Boss(Battle battle, Image enemyImage) 
		super(battle, enemyImage);
	

	public abstract void move();

	public float getX() 
		return x;
	

	public float getY() 
		return y;
	

	public float getWidth() 
		return WIDTH;
	

	public float getHeight() 
		return HEIGHT;
	

	public int getPower() 
		return power;
	

	public Image getImage() 
		return img;
	

	public void drawPower(Graphics g) 
		g.setColor(Color.white);
		g.drawRect(200, 20, 150, 15);
		g.setColor(Color.green);
		g
				.fillRect(
						201,
						21,
						(int) ((150D / (double) (float) powerMax) * (double) power) - 1,
						14);
	

	public int getPowerMax() 
		return powerMax;
	


五,项目总结

本次项目开发是基于JAVA的雷电游戏。

此雷电游戏通俗来说就是我方飞机和敌方之间的对决,先要做的应该是通过一个界面来达到装载整个游戏,然后就是我方飞机的移动方式(也就是通过键盘来移动),接着就是生成我方飞机的子弹(依据子弹类型的不同有不同的实现形式),准备就绪后会有敌方飞机的出现,每一个飞机会对应发射不同种类的子弹,最后是我方飞机通过键盘进行移动、射击,显示出游戏结果,然后结束游戏。

该雷电应该满足以下一些要求:

(1)游戏状态控制功能

在进行游戏的设计时,我们应该考虑到,如何进行游戏状态的划分。简单来说,我们需要设置开始,并且要考虑到游戏中断,以及中断后回到游戏中。玩家点击开始之后,程序会调用启动页面的代码,然后进入游戏,在游戏的过程中,玩家如果由于其它工作需要离开时,可以将其中断,比如单击空格键,当需要恢复游戏现场时,再单击空格键,就可以继续游戏,当自己控制的飞机被击毁时,会有游戏结束的显现。

(2)游戏难度的调整

    随着游戏的进行、关卡的提高,敌机的速度会越来越快、敌方飞机的数目会越来越多、子弹数量也会越快且越多。此时,带给游戏玩家的视觉冲击变得更强,需要玩家更加冷静地去躲闪以及攻击敌机。

(3)游戏界面绘画功能

游戏主屏主要用来输出用户对我方的控制与敌方的动作显示。在游戏屏幕的左下角有全屏爆破次数的显示,这相当于游戏玩家的特殊技能,可以瞬间清除当前屏幕上的所有敌机以及子弹,在游戏屏幕的右下角会呈现玩家飞机血条,代表着当前我方飞机的状态。当血条格为空时,表示我方飞机已经被击毁,整个雷电游戏也将结束。

  1. 玩家游戏控制功能

对于我方飞机的移动和子弹的发射,游戏用户可以通过控制键盘来控制。飞机的左右移动通过键盘的上、下、左、右键来实现,而我方飞机子弹的释放方式有两种,z键会释放出点状子弹,而x键会释放出线状子弹,可供游戏玩家依据需要自行选择。

以上是关于我的第一个项目 :飞机大战Vue版本塞到主页的主要内容,如果未能解决你的问题,请参考以下文章

雷电飞机大战游戏|基于Java开发实现雷电飞机大战游戏

雷电飞机大战游戏|基于Java开发实现雷电飞机大战游戏

我的第一个项目 :处理全局变量(解决模块化后变量无法获取的问题)

python(pygame)滑稽大战(类似飞机大战) 教程

Vue+Websocket实现多人在线王者飞机

飞机大战项目