Html飞机大战(十八): 模块化+项目开源

好家伙,好久好久没有更新这个系列了

 

 

 

 

 

 

 

 

为了使文档更方便阅读,使代码更容易维护,来把这个飞机大战模块化

项目已开源:

https://gitee.com/tang-and-han-dynasties/airplane-battle---h.git

 

项目结构如下:

 

 

最大的改动是主启动类进行了修改:

我们将曾经部分的全局方法,和循环计时器封装到类的方法中

main.js文件如下:

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" // } } } let main_1 = new Main() // main_1.stateControl(); main_1.maingame();

 

并将配置项分开来:

以下配置归到config.js文件中

// 初始化画布对象
const canvas = document.getElementById("canvas");
const context = canvas.getContext("2d");

// 定义游戏的状态
// 开始
const START = 0;
// 开始时
const STARTING = 1;
// 运行时
const RUNNING = 2;
// 暂停时
const PAUSE = 3;
// 结束时
const END = 4;

//state表示游戏的状态 取值必须是以上的五种状态
let state = START;
//score 分数变量 life 变量
let score = 0;
let life = 3;

 

posted @ 2023-01-05 20:43  养肥胖虎  阅读(121)  评论(0编辑  收藏  举报