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

 

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

项目已开源:

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;

最新文章

  1. 最近这两天看了关于H5游戏开发的一个教程,实践很短暂,看了很多理论的东西,现在呢也只是想回忆回忆关于EUI的部分知识吧
  2. Http的请求对象
  3. Django学习(二)
  4. css+div盒模型研究笔记
  5. jquery ajax php+mysql 无刷新分页 详细实例
  6. grep详解
  7. windows系统port监听
  8. win7 安装 vagrant + centos + virtualbox
  9. 如何用CropBox实现头像裁剪并与java后台交互
  10. C语言第三次作业总结
  11. .NET Core 开源工具 IPTools - 快速查询 IP 地理位置、经纬度信息
  12. Google - Find minimum number of coins that make a given value
  13. BeatifulSoup模块
  14. mysql sql执行慢 分析过程
  15. thinkphp去掉url中的.html后缀
  16. linux 第七周 总结及实验
  17. day 56 jQuery学习
  18. iTerm通过堡垒机自动登录服务器
  19. Hibernate5总结
  20. Python——thread

热门文章

  1. Flink的异步算子的原理及使用
  2. 利用FastReport传递图片参数,在报表上展示签名信息
  3. CQOI2015任务查询系统
  4. 抛砖系列之redis监控命令
  5. nrf9160做主控连接阿里云——(mqtt_simple例程)
  6. 用 VS Code 搞 Qt6:让信号和槽自动建立连接
  7. or、and表达式
  8. 洛谷P4168 蒲公英 分块处理区间众数模板
  9. WPF之lognet4的基本使用
  10. 【网络】https 轻解读