好家伙,本篇介绍敌机

好了,按照惯例我们来理一下思路:

 

我们有一个敌机类,第一步当然是实例一个敌机对象,

然后我们把这个敌机放入我们的敌机群(敌机数组)

然后是熟悉的移动和绘制

 

那我们回顾一下子弹的生成逻辑

变量: 子弹  bullet  弹夹(用来装子弹的东西)bulletList[] 

方法:装填子弹  绘制子弹 移动子弹

子弹发射的物理逻辑是很简单的:

生产第一个子弹,推入弹夹中,绘制弹夹(即绘制弹夹中的所有子弹),

生产第二个子弹,同样推入弹夹,移动第一颗子弹(应该说是改变第一颗子弹的y坐标),绘制弹夹中的所有子弹 

。。。。。。

生产第n个子弹,推入弹夹中,改变第n-1颗子弹的Y坐标,绘制弹夹中的所有子弹

 

有没有感觉到两者逻辑的相似之处

(像啊,太像了)

 

 

子弹和敌机的处理,本质上是用的是同一套逻辑

 

那么,开始干活:

1.配置项

这里我们会用到两种类型的配置项E1和E2

(因为我们有两种类型的敌人,大敌机和小敌机,其中e1为小敌机(血少),e2为大敌机(血厚))

先设置一个数组存放图片资源

//e1用于存放小敌机的图片素材const e1 = {live: [],death: [],}e1.live[0] = new Image();e1.live[0].src = "img/enemy1.jpg"e1.death[0] = new Image();e1.death[0].src = "img/enemy1_boom1.jpg"e1.death[1] = new Image();e1.death[1].src = "img/enemy1_boom2.jpg"e1.death[2] = new Image();e1.death[2].src = "img/enemy1_boom3.jpg"//e2用于存放小敌机的图片素材const e2 = {live: [],death: [],}e2.live[0] = new Image();e2.live[0].src = "img/enemy2.jpg"e2.death[0] = new Image();e2.death[0].src = "img/enemy2_boom1.jpg"

 

 

 

 (图片素材来自网络)

2.敌机配置项

//小敌机const E1 = {type: 1,width: 57,height: 51,life: 1, //少点血,一下打死score: 1,frame: e1,minSpeed: 20,maxSpeed: 10,}//大敌机const E2 = {type: 2,width: 69,height: 95,life: 2,frame: e2,minSpeed: 50,maxSpeed: 20,}

minSpeed: 50,
maxSpeed: 20,
值得说明一下,这两个玩意是为了弄敌机的随机速度(更刺激一点,但实际上好像没什么感觉)
关于如何弄到一个”随机速度“,接着往下看

3.敌机类

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));//这里我们让飞机从头部开始渲染,所以Y轴坐标自然是飞机高度的负值this.y = -config.height;//敌机生命this.life = config.life;//敌机分数this.score = config.score;//敌机图片库this.frame = config.frame;//此刻展示的图片this.img = null;//活着的证明this.live = true;// this.minSpeed = config.minSoeed;// this.maxSpeed = config.speed;//随机去生成一个速度this.speed = Math.floor(Math.random() * (config.minSpeed - config.maxSpeed + 1)) + config.maxSpeed;//最后渲染的时间this.lastTime = new Date().getTime();}//移动敌机move() {const currentTime = new Date().getTime();//if (currentTime - this.lastTime >= this.speed) {// console.log("此处为this.frame"+this.frame.live[0]);this.img = this.frame.live[0];this.y++;//时间修正this.lastTime = currentTime;}}//渲染敌机方法paint(context) {// console.log("此处为this.img"+this.img);if(this.img !=null){context.drawImage(this.img, this.x, this.y);  }}}

3.1.随机速度

先浅浅的说明一下

随机数方法 Math.random

这玩意会在[0,1)也就是在0到1之间取一个值

然后问题来了,这是一个半开半闭区间,也就是说它会取到0但是不会取到1

this.speed = Math.floor(Math.random() * (config.minSpeed - config.maxSpeed + 1)) + config.maxSpeed;

在这里我们要取的是一个10到20之间的速度由于我们向下取整

Math.floor(Math.random() * (config.minSpeed - config.maxSpeed )) + config.maxSpeed;

必然只能取得10-19之间的数

于是我们在(config.minSpeed - config.maxSpeed )中加一

变成(Math.random() * (config.minSpeed - config.maxSpeed +1))

(聪明的你一定能很快想明白,而愚蠢的我想了很久才想明白)

3.2.敌机的移动方法

move() {const currentTime = new Date().getTime();//if (currentTime - this.lastTime >= this.speed) {// console.log("此处为this.frame"+this.frame.live[0]);this.img = this.frame.live[0];this.y++;//时间修正this.lastTime = currentTime;}}

移动同样的用时间判定的方式去控制速率

现在和过去的时间差大于速度,更新地址

3.3.渲染方法

paint(context) {// console.log("此处为this.img"+this.img);if(this.img !=null){context.drawImage(this.img, this.x, this.y);  }}

嗯,非常好理解了,多加的一个if是为了防止出现空img导致报错

4.全局函数(生产敌机)

//以下三项均为全局变量const enemies = [];//敌机产生的速率const ENEMY_CREATE_INTERVAL = 2000;let ENEMY_LASTTIME = new Date().getTime();//全局函数 用于生产敌机function createComponent() {const currentTime = new Date().getTime();const forenemyTime = new Date().getTime();//一手经典判断if (currentTime - ENEMY_LASTTIME >= ENEMY_CREATE_INTERVAL) {//当时间满足 实例化一架敌机 放入敌机数组中// 小飞机 70% 中飞机30%//用随机数去弄概率//[0,99]//Math.random()=>[0,1)*100//EnemyTypeRandom产生的随机数用于判断产生不同的飞机let EnemyTypeRandom = Math.floor(Math.random() * 100);if (EnemyTypeRandom > 70) {enemies.push(new Enemy(E1));} else if (EnemyTypeRandom < 30) {enemies.push(new Enemy(E2));}console.log(enemies);//更新时间ENEMY_LASTTIME = currentTime;}}


这里同样的,我们用随机数去控制出现大/小敌机的概率

(E1,E2分别是大小敌机的配置项)


let EnemyTypeRandom = Math.floor(Math.random() * 100);if (EnemyTypeRandom > 70) {//产小敌机enemies.push(new Enemy(E1));} else if (EnemyTypeRandom < 30) {//产大敌机enemies.push(new Enemy(E2));}


你细品,这个控制得还是非常巧妙的

5.全局函数渲染

到这里就非常简单了

这里也揭开了前面的谜底

因为敌机生成和子弹生成的逻辑太过相似

所以我们把他们放到同一个全局函数是一个非常明智的选择

//全局函数 来移动所有的子弹/敌人组件function judgeComponent() {console.log("judge被触发");for (let i = 0; i < hero.bulletList.length; i++) {hero.bulletList[i].move();}for(let i=1;i<enemies.length;i++){enemies[i].move();}}//全局函数 来绘制所有的子弹/敌人组件function paintComponent() {for (let i = 0; i < hero.bulletList.length; i++) {hero.bulletList[i].paint(context);}for(let i=1;i<enemies.length;i++){enemies[i].paint(context);}}


6.方法调用


case RUNNING:sky.judge();sky.paint(context);//加载主角hero.paint(context);hero.shoot();createComponent();//子弹发射judgeComponent();paintComponent();deleteComponent();// context.drawImage(hero_frame.live[0], 0, 0);break;




ok,来看看效果吧:

 

 

确实是非常地nice啊

Html飞机大战(九): 使徒来袭 (设计敌机)相关推荐

  1. pygame飞机大战关于子弹的设计(一)(含源码)

    Exe如下,欢迎试玩! 链接:https://pan.baidu.com/s/1Hw-DP98Jayr-jmE3ZCe9NA 提取码:2xsq 先上图,终极子弹: 我方子弹共有三种模型:基础子弹.双发 ...

  2. 基于python的毕业论文-基于python的飞机大战小游戏毕业论文设计和代码

    python 飞机大战 论文 计说明: 完成敌机发射子弹功能(注意:子弹不是连发.移动速度不要太快) 实现敌机子弹和玩家飞机的碰撞检测实现敌机子弹和玩家飞机的碰撞检测 为消失的飞机添加爆炸效果为消失的 ...

  3. 基于python的游戏设计与实现-基于python的飞机大战小游戏毕业论文设计和代码

    python 飞机大战 论文 计说明: 完成敌机发射子弹功能(注意:子弹不是连发.移动速度不要太快) 实现敌机子弹和玩家飞机的碰撞检测实现敌机子弹和玩家飞机的碰撞检测 为消失的飞机添加爆炸效果为消失的 ...

  4. java飞机大战流程图_JAVA课程设计-飞机大战

    JAVA课程设计-飞机大战 1.团队名称.团队成员介绍 1.1 团队名称:做个飞机哦 1.2团队成员介绍: 余俊良(组长):编写博客.游戏主界面设计与实现.英雄机与子弹类的实现.场景设计 林祥涛:游戏 ...

  5. 飞机大战纯c课程设计报告(里面的本来有图的,但是我就懒得导入)

    源码连接:https://blog.csdn.net/weixin_44688297/article/details/94836698 目录 一.需求分析 2 二.概要设计 3 三.详细设计 5 四. ...

  6. java飞机大战流程图_JAVA课程设计——飞机大战(团队)

    1.团队名称.团队成员介绍 黄力强(组长) 带带带带...带佬 陈汉煜(组员) 划水.gif 2.Gitee部分 3.项目功能架构图与主要功能流程图 游戏流程图: 面向对象设计 包图: uml(关键类 ...

  7. java 中飞机大战碰撞检测,飞机大战开发04子弹与敌机的碰撞检测

    先是敌机与玩家子弹的碰撞检测: 代码: GameLayer.h void GameLayer::update(float dt) { for (int i = 0 ;i < m_pEnermyV ...

  8. 用pycharm写飞机大战

    用pycharm写飞机大战 以下是源代码 设置敌机图片库常量元组 创建所有显示的图形父类Model 背景类 玩家类 敌机类 子弹类 爆炸效果类 设置测试类入口操作 设置敌机图片库常量元组 创建所有显示 ...

  9. Python小游戏(并夕夕版飞机大战)

    源码分享: import sys import cfg import pygame from modules import *'''游戏界面''' def GamingInterface(num_pl ...

最新文章

  1. 为何Google将几十亿行源代码放在一个仓库?| CSDN博文精选
  2. 浅谈文献总结(2018.9.28)——坚恒勇毅论文课笔记
  3. matlab中的分类器使用小结(SVM、KNN、RF、AdaBoost、Naive Bayes、DAC)
  4. openfire(一):使用idea编译openfire4.2.3源码
  5. [html] html标签的属性值是否可以省略引号?为什么?
  6. Modularity(模块化-UMD通用模式)
  7. UI中国转的产品知识
  8. 设计模式(四)行为型模式
  9. 代码管理仓库项目任务计划
  10. Python 深度学习AI - 声音克隆、声音模仿、模拟特朗普声音唱《See You Again》,Real-Time-Voice-Cloning项目的安装与使用
  11. 什么是CDN加速技术?网站用CDN有什么好处
  12. iOS开发中的Web应用概述
  13. THREEJS辉光与景深特效
  14. 如何看懂Elastic解决方案与Gartner的魔力象限
  15. c语言打印数组中的汉字
  16. 笔记本计算机电池没有电,笔记本主板电池没电会影响开机吗
  17. 长期提供orkut / gmail 邀请
  18. 通过设置路由器DMZ主机ip,却还是没法通过外网访问
  19. 轻薄游戏本没性能?醒醒 外星人来了
  20. 南京农业大学计算机博士几年毕业,通知 | 南京农业大学关于调整博士研究生基本学制及增加博士生培养环节要求的通知...

热门文章

  1. 要过年了,换个发微信红包新姿势
  2. 关于执行力--程序员你有木有?
  3. 【笔记】_findnext x64报错解决办法:改为 intptr_t handle; //x64
  4. 第一次使用GIT,创建仓库并提交项目代码
  5. ASP.NET MVC3调用PartialView的几种方式
  6. python编写一个程序、输入一个数判断其是偶数还是奇数_编写程序,输入一个整数,判断后输出它是奇数还是偶数...
  7. x86Android平板电脑刷机方法,小白必看,安卓平板电脑刷机教程之一键刷机
  8. LeetCode 729. 我的日程安排表 I
  9. Verilog高级知识点
  10. i5 10400f配什么主板