环球热头条丨我的第一个项目(九) :飞机大战Vue版本塞到主页
来源:博客园
(相关资料图)
好家伙,
这是未进行分包的vue版本的飞机大战
效果如下:
这里说明一下,大概使用逻辑是提供一个然后在这中渲染游戏
游戏主界面代码如下:
1 2 6 7 8 <script> 9 export default { 10 mounted() { 11 //canvas初始化 12 console.log("我被执行啦") 13 let canvas = document.createElement("canvas"); 14 this.$refs.stage.appendChild(canvas); 15 canvas.width = 480; 16 canvas.height = 650; 17 canvas.ref = canvas; 18 canvas.style = "border: 1px solid red;" 19 const context = canvas.getContext("2d"); 20 21 //图片初始化方法 22 function createImage(src) { 23 let img; 24 if (typeof src === "string") { 25 img = new Image(); 26 img.src = require("./img/" + src); 27 } else { 28 img = []; 29 for (let i = 0; i < src.length; i++) { 30 img[i] = new Image(); 31 img[i].src = require("./img/" + src[i]); 32 } 33 } 34 return img; 35 } 36 //createImage()方法测试样例 37 // let bg = createImage("4.jpg") 38 // bg.onload = function () { 39 // console.log("img加载完毕") 40 // context.drawImage(bg, 0, 0, 480, 650) 41 // } 42 const IMAGES = { 43 b: "bullet1.png", 44 bg: "4.png", 45 copyright: "shoot_copyright.png", 46 pause: "game_pause.png", 47 loading_frame: ["game_loading1.png", "game_loading2.png", "game_loading3.png", 48 "game_loading4.png" 49 ], 50 hero_frame_live: ["hero1.png", "hero2.png"], 51 hero_frame_death: ["hero_blowup_n1.png", "hero_blowup_n2.png", "hero_blowup_n3.png", 52 "hero_blowup_n4.png" 53 ], 54 e1_live: ["enemy1.png"], 55 e1_death: ["enemy1_down1.png", "enemy1_down2.png", "enemy1_down3.png", "enemy1_down4.png"], 56 e2_live: ["enemy2.png"], 57 e2_death: ["enemy2_down1.png", "enemy2_down2.png", "enemy2_down3.png", "enemy2_down4.png"], 58 e3_live: ["enemy3_n1.png", "enemy3_n2.png"], 59 e3_death: ["enemy3_down1.png", "enemy3_down2.png", "enemy3_down3.png", "enemy3_down4.png", 60 "enemy3_down5.png", "enemy3_down6.png" 61 ], 62 c1: "lanqiu.png" 63 }; 64 //初始化各个图片 65 const b = createImage(IMAGES.b); 66 const bg = createImage(IMAGES.bg); 67 const copyright = createImage(IMAGES.copyright); 68 const pause = createImage(IMAGES.pause); 69 const loading_frame = createImage(IMAGES.loading_frame); 70 const hero_frame = { 71 live: createImage(IMAGES.hero_frame_live), 72 death: createImage(IMAGES.hero_frame_death), 73 }; 74 const e1 = { 75 live: createImage(IMAGES.e1_live), 76 death: createImage(IMAGES.e1_death), 77 }; 78 const e2 = { 79 live: createImage(IMAGES.e2_live), 80 death: createImage(IMAGES.e2_death), 81 }; 82 const e3 = { 83 live: createImage(IMAGES.e3_live), 84 death: createImage(IMAGES.e3_death), 85 }; 86 const c1 = createImage(IMAGES.c1); 87 88 //配置项: 89 // 定义游戏的状态 90 // 开始 91 const START = 0; 92 // 开始时 93 const STARTING = 1; 94 // 运行时 95 const RUNNING = 2; 96 // 暂停时 97 const PAUSE = 3; 98 // 结束时 99 const END = 4;100 // 加载中101 const LOADINGING = 5;102 103 //state表示游戏的状态 取值必须是以上的五种状态104 let state = LOADINGING;105 // hero_frame.addEventListener("load", () => {106 // state = START;107 // })108 109 pause.onload = function () {110 state = START;111 console.log(state)112 }113 114 //score 分数变量 life 变量115 let score = 0;116 let life = 3;117 118 //天空类的配置项119 const SKY = {120 bg: bg,121 width: 480,122 height: 650,123 speed: 10,124 };125 126 // 飞机加载界面的配置项127 const LOADING = {128 frame: loading_frame,129 width: 186,130 height: 38,131 x: 0,132 y: 650 - 38,133 speed: 400,134 };135 136 // 英雄配置项137 const HERO = {138 frame: hero_frame,139 width: 99,140 height: 124,141 speed: 100,142 };143 144 // 子弹配置项145 const BULLET = {146 img: b,147 width: 9,148 height: 21,149 };150 151 //小敌机配置项152 const E1 = {153 type: 1,154 width: 57,155 height: 51,156 life: 10,157 score: 1,158 frame: e1,159 minSpeed: 20,160 maxSpeed: 10161 };162 //中敌机配置项163 const E2 = {164 type: 2,165 width: 69,166 height: 95,167 life: 50,168 score: 5,169 frame: e2,170 minSpeed: 50,171 maxSpeed: 20172 };173 //打敌机配置项174 const E3 = {175 type: 3,176 width: 169,177 height: 258,178 life: 100,179 score: 20,180 frame: e3,181 minSpeed: 100,182 maxSpeed: 100183 };184 //奖励类配置项185 const C1 = {186 type: 4,187 width: 75,188 height: 75,189 life: 1,190 score: 1,191 img: c1,192 minSpeed: 5,193 maxSpeed: 10194 };195 //正式代码196 197 //初始化奖励类198 class Award {199 constructor(config) {200 this.type = config.type;201 this.width = config.width;202 this.height = config.height;203 this.x = Math.floor(Math.random() * (480 - config.width));204 this.y = -config.height;205 this.life = config.life;206 this.score = config.score;207 this.img = config.img;208 this.live = true;209 this.speed = Math.floor(Math.random() * (config.minSpeed - config.maxSpeed + 1)) + config.maxSpeed;210 this.lastTime = new Date().getTime();211 this.deathIndex = 0;212 this.destory = false;213 }214 move() {215 const currentTime = new Date().getTime();216 if (currentTime - this.lastTime >= this.speed) {217 if (this.live) {218 this.y = this.y + 6;219 this.lastTime = currentTime;220 } else {221 this.destory = true;222 223 }224 }225 }226 paint(context) {227 context.drawImage(this.img, this.x, this.y, this.width, this.height);228 }229 outOfBounds() {230 if (this.y > 650) {231 return true;232 }233 }234 hit(o) {235 let ol = o.x;236 let or = o.x + o.width;237 let ot = o.y;238 let ob = o.y + o.height;239 let el = this.x;240 let er = this.x + this.width;241 let et = this.y;242 let eb = this.y + this.height;243 if (ol > er || or < el || ot > eb || ob < et) {244 return false;245 } else {246 return true;247 }248 }249 // collide() {250 // this.life--;251 // if (this.life === 0) {252 // this.live = false;253 // score += this.score;254 // }255 // }256 }257 258 //259 //初始化一个子弹类260 class Bullet {261 constructor(config, x, y) {262 this.img = config.img;263 this.width = config.width;264 this.height = config.height;265 this.x = x;266 this.y = y;267 this.destory = false;268 }269 //子弹绘制方法270 paint(context) {271 context.drawImage(this.img, this.x, this.y);272 }273 //移动子弹 this.y--274 move() {275 this.y -= 8;276 }277 outOfBounds() {278 //如果返回的是真的话 那么我们应该销毁掉这个子弹279 return this.y < -this.height;280 }281 collide() {282 //让这颗子弹变成可销毁状态283 this.destory = true;284 }285 }286 //287 288 // 初始化一个敌机类289 class Enemy {290 291 292 293 294 295 296 constructor(config) {297 this.type = config.type;298 this.width = config.width;299 this.height = config.height;300 this.x = Math.floor(Math.random() * (480 - config.width));301 this.y = -config.height;302 this.life = config.life;303 this.score = config.score;304 this.frame = config.frame;305 this.img = this.frame.live[0];306 this.live = true;307 this.speed = Math.floor(Math.random() * (config.minSpeed - config.maxSpeed + 1)) + config.maxSpeed;308 this.lastTime = new Date().getTime();309 this.deathIndex = 0;310 this.destory = false;311 }312 move() {313 const currentTime = new Date().getTime();314 if (currentTime - this.lastTime >= this.speed) {315 if (this.live) {316 this.img = this.frame.live[0];317 this.y++;318 this.lastTime = currentTime;319 } else {320 this.img = this.frame.death[this.deathIndex++];321 if (this.deathIndex === this.frame.death.length) {322 this.destory = true;323 }324 }325 }326 }327 paint(context) {328 context.drawImage(this.img, this.x, this.y);329 }330 outOfBounds() {331 if (this.y > 650) {332 return true;333 }334 }335 hit(o) {336 let ol = o.x;337 let or = o.x + o.width;338 let ot = o.y;339 let ob = o.y + o.height;340 let el = this.x;341 let er = this.x + this.width;342 let et = this.y;343 let eb = this.y + this.height;344 if (ol > er || or < el || ot > eb || ob < et) {345 return false;346 } else {347 return true;348 }349 }350 collide() {351 this.life--;352 if (this.life === 0) {353 this.live = false;354 score += this.score;355 }356 }357 }358 359 //360 // 初始化一个英雄类361 class Hero {362 constructor(config) {363 this.width = config.width;364 this.height = config.height;365 this.x = (480 - config.width) / 2;366 this.y = 650 - config.height;367 this.frame = config.frame;368 this.frameLiveIndex = 0;369 this.frameDeathIndex = 0;370 this.lastTime = new Date().getTime();371 this.speed = config.speed;372 //当前展示的图片373 this.img = null;374 this.live = true;375 //子弹上次射击的时间376 this.lastShootTime = new Date().getTime();377 //子弹射击的间隔378 this.shootInterval = 50;379 //子弹夹数组380 this.bulletList = [];381 this.destory = false;382 }383 judge() {384 const currentTime = new Date().getTime();385 if (currentTime - this.lastTime > this.speed) {386 if (this.live) {387 this.img = this.frame.live[this.frameLiveIndex++ % this.frame.live.length];388 } else {389 //0 1 2 3 4390 this.img = this.frame.death[this.frameDeathIndex++];391 //到4的时候英雄死了392 if (this.frameDeathIndex === this.frame.death.length) {393 this.destory = true;394 }395 }396 this.lastTime = currentTime;397 }398 }399 paint(context) {400 context.drawImage(this.img, this.x, this.y, this.width, this.height);401 }402 //英雄可以射击子弹403 shoot() {404 //获取当前时间405 const currentTime = new Date().getTime();406 //飞机的位置407 if (currentTime - this.lastShootTime > this.shootInterval) {408 //在飞机的头部初始化一个子弹对象409 let bullet = new Bullet(BULLET, this.x + this.width / 2 - BULLET.width / 2, this.y - BULLET.height);410 //英雄飞机要认领这个子弹411 this.bulletList.push(bullet);412 //在网页上绘制一个子弹对象413 bullet.paint(context);414 //更新英雄射击时间415 this.lastShootTime = currentTime;416 }417 }418 collide() {419 //将活着标识符切换为false420 //活着 -> 爆炸中 -> 死亡(销毁)421 this.live = false;422 }423 }424 //425 // 初始化一个飞机界面加载类426 class Loading {427 constructor(config) {428 this.frame = config.frame;429 this.frameIndex = 0;430 this.width = config.width;431 this.height = config.height;432 this.x = config.x;433 this.y = config.y;434 this.speed = config.speed;435 this.lastTime = new Date().getTime();436 }437 judge() {438 const currentTime = new Date().getTime();439 if (currentTime - this.lastTime > this.speed) {440 this.frameIndex++;441 if (this.frameIndex === 4) {442 state = RUNNING;443 }444 this.lastTime = currentTime;445 }446 }447 paint(context) {448 context.drawImage(this.frame[this.frameIndex], this.x, this.y);449 }450 }451 452 453 class Main {454 //一下全为全局变量或方法 (全局的!!)455 //初始化一个天空实例456 //主启动方法457 maingame() {458 const sky = new Sky(SKY);459 //初始化一个飞机界面加载实例460 const loading = new Loading(LOADING);461 //初始化一个英雄实例 英雄是会变的462 let hero = new Hero(HERO);463 //该变量中有所有的敌机实例464 let enemies = [];465 //该变量中存放所有的奖励实例466 467 let awards = [];468 //敌机产生的速率469 let ENEMY_CREATE_INTERVAL = 800;470 let ENEMY_LASTTIME = new Date().getTime();471 472 function stateControl() {473 //为canvas绑定一个点击事件 且他如果是START状态的时候需要修改成STARTING状态474 canvas.addEventListener("click", () => {475 if (state === START) {476 state = STARTING;477 }478 });479 // 为canvas绑定一个鼠标移动事件 鼠标正好在飞机图片的正中心480 canvas.addEventListener("mousemove", (e) => {481 let x = e.offsetX;482 let y = e.offsetY;483 hero.x = x - hero.width / 2;484 hero.y = y - hero.height / 2;485 });486 // 为canvas绑定一个鼠标离开事件 鼠标离开时 RUNNING -> PAUSE487 canvas.addEventListener("mouseleave", () => {488 if (state === RUNNING) {489 state = PAUSE;490 }491 });492 // 为canvas绑定一个鼠标进入事件 鼠标进入时 PAUSE => RUNNING493 canvas.addEventListener("mouseenter", () => {494 if (state === PAUSE) {495 state = RUNNING;496 }497 });498 //为canvas绑定一个屏幕移动触摸点事件 触碰点正好在飞机图片的正中心499 canvas.addEventListener("touchmove", (e) => {500 // let x = e.pageX;501 // let y = e.pageY;502 console.log(e);503 // let x = e.touches[0].clientX;504 // let y = e.touches[0].clinetY;505 let x = e.touches[0].pageX;506 let y = e.touches[0].pageY;507 // let x = e.touches[0].screenX;508 // let y = e.touches[0].screenY;509 let write1 = (document.body.clientWidth - 480) / 2;510 let write2 = (document.body.clientHeight - 650) / 2;511 hero.x = x - write1 - hero.width / 2;512 hero.y = y - write2 - hero.height / 2;513 514 // hero.x = x - hero.width / 2;515 // hero.y = y - hero.height / 2;516 console.log(x, y);517 console.log(document.body.clientWidth, document.body.clientHeight);518 e.preventDefault(); // 阻止屏幕滚动的默认行为519 520 })521 }522 stateControl();523 // 碰撞检测函数524 //此处的碰撞检测包括 525 //1.子弹与敌机的碰撞526 //2.英雄与敌机的碰撞527 //3.英雄与随机奖励的碰撞528 function checkHit() {529 // 遍历所有的敌机530 for (let i = 0; i < awards.length; i++) {531 //检测英雄是否碰到奖励类532 if (awards[i].hit(hero)) {533 //当然了,这个随机奖励的样式也要删了534 awards.splice(i, 1);535 //清除所有的敌机536 // for (let i = 0; i < enemies.length; i++) {537 // enemies.splice(i, 1);538 // }539 enemies.length = 0;540 541 }542 }543 for (let i = 0; i < enemies.length; i++) {544 //检测英雄是否撞到敌机545 if (enemies[i].hit(hero)) {546 //将敌机和英雄的destory属性改为true547 enemies[i].collide();548 hero.collide();549 }550 for (let j = 0; j < hero.bulletList.length; j++) {551 enemies[i].hit(hero.bulletList[j]);552 //检测子弹是否撞到敌机553 if (enemies[i].hit(hero.bulletList[j])) {554 //将敌机和子弹的destory属性改为true555 enemies[i].collide();556 hero.bulletList[j].collide();557 }558 }559 }560 }561 // 全局函数 隔一段时间就来初始化一架敌机/奖励562 function createComponent() {563 const currentTime = new Date().getTime();564 if (currentTime - ENEMY_LASTTIME >= ENEMY_CREATE_INTERVAL) {565 let ran = Math.floor(Math.random() * 100);566 if (ran < 55) {567 enemies.push(new Enemy(E1));568 } else if (ran < 85 && ran > 55) {569 enemies.push(new Enemy(E2));570 } else if (ran < 95 && ran > 85) {571 enemies.push(new Enemy(E3));572 } else if (ran > 95) {573 awards.push(new award(C1));574 575 }576 577 ENEMY_LASTTIME = currentTime;578 }579 }580 // 全局函数 来判断所有的子弹/敌人组件 "负责移动"581 function judgeComponent() {582 for (let i = 0; i < hero.bulletList.length; i++) {583 hero.bulletList[i].move();584 }585 for (let i = 0; i < enemies.length; i++) {586 enemies[i].move();587 }588 for (let i = 0; i < awards.length; i++) {589 awards[i].move();590 }591 }592 // 全局函数 来绘制所有的子弹/敌人组件 绘制score&life面板593 function paintComponent() {594 for (let i = 0; i < hero.bulletList.length; i++) {595 hero.bulletList[i].paint(context);596 }597 for (let i = 0; i < enemies.length; i++) {598 enemies[i].paint(context);599 }600 for (let i = 0; i < awards.length; i++) {601 awards[i].paint(context);602 }603 context.font = "20px 微软雅黑";604 context.fillStyle = "green";605 context.textAlign = "left";606 context.fillText("score: " + score, 10, 20);607 context.textAlign = "right";608 context.fillText("life: " + life, 480 - 10, 20);609 //重置样式610 context.fillStyle = "black";611 context.textAlign = "left";612 }613 // 全局函数 来销毁所有的子弹/敌人组件 销毁掉英雄614 function deleteComponent() {615 if (hero.destory) {616 life--;617 hero.destory = false;618 if (life === 0) {619 state = END;620 } else {621 hero = new Hero(HERO);622 }623 }624 for (let i = 0; i < hero.bulletList.length; i++) {625 if (hero.bulletList[i].outOfBounds() || hero.bulletList[i].destory) {626 hero.bulletList.splice(i, 1);627 }628 }629 for (let i = 0; i < enemies.length; i++) {630 if (enemies[i].outOfBounds() || enemies[i].destory) {631 enemies.splice(i, 1);632 }633 }634 }635 636 //当图片加载完毕时,需要做某些事情637 bg.addEventListener("load", () => {638 setInterval(() => {639 switch (state) {640 case START:641 sky.judge();642 sky.paint(context);643 let logo_x = (480 - copyright.naturalWidth) / 2;644 let logo_y = (650 - copyright.naturalHeight) / 2;645 context.drawImage(copyright, logo_x, logo_y);646 break;647 case STARTING:648 sky.judge();649 sky.paint(context);650 loading.judge();651 loading.paint(context);652 break;653 case RUNNING:654 sky.judge();655 sky.paint(context);656 hero.judge();657 hero.paint(context);658 hero.shoot();659 createComponent();660 judgeComponent();661 deleteComponent();662 paintComponent();663 checkHit();664 break;665 case PAUSE:666 let pause_x = (480 - pause.naturalWidth) / 2;667 let pause_y = (650 - pause.naturalHeight) / 2;668 context.drawImage(pause, pause_x, pause_y);669 break;670 case END:671 //给我的画笔设置一个字的样式672 //后面写出来的字都是这个样式的673 context.font = "bold 24px 微软雅黑";674 context.textAlign = "center";675 context.textBaseline = "middle";676 context.fillText("GAME_OVER", 480 / 2, 650 / 2);677 break;678 }679 }, 10);680 });681 682 683 //背景切换方法684 // function changebg() {685 // console.log("changebg方法被触发")686 // bg.src = "img/background.png"687 // }688 }689 }690 //691 692 //初始化一个天空类693 class Sky {694 constructor(config) {695 this.bg = config.bg;696 this.width = config.width;697 this.height = config.height;698 this.x1 = 0;699 this.y1 = 0;700 this.x2 = 0;701 this.y2 = -this.height;702 this.speed = config.speed;703 this.lastTime = new Date().getTime();704 }705 //判断方法706 judge() {707 let currentTime = new Date().getTime();708 if (currentTime - this.lastTime > this.speed) {709 this.y1++;710 this.y2++;711 this.lastTime = currentTime;712 }713 if (this.y2 === 0) {714 this.y1 = 0;715 this.y2 = -this.height;716 }717 }718 //绘图方法719 paint(context) {720 context.drawImage(this.bg, this.x1, this.y1, this.width, this.height);721 context.drawImage(this.bg, this.x2, this.y2, this.width, this.height);722 }723 }724 let main_1 = new Main()725 main_1.maingame();726 }727 }728 729 730 </script>731 732 739 740
关键词:
-
好家伙,这是未进行分包的vue版本的飞机大战效果如下:这里说明一下,大概使用逻辑是提供一个<div>然后在这...
-
Unity开发Hololens2—环境配置配置如下:win11专业版Unity2018 4 26f1Hololens2VS2019参考链接:1、(https: blog csdn n
-
1自定义SpringIOC总结1 1使用到的设计模式工厂模式。这个使用工厂模式+配置文件的方式。单例模式。Spri...
-
Week3ExceptionsFuelGauge题目描述:输入分数字符串,判断并输出相应的百分数;特例不足1%输出E,超出99%...