/dom_plane

Primary LanguageHTMLMIT LicenseMIT

  1. 什么时候用that,什么时候用this

分析问题: 面向Player类进行开发

this预期:指向我们Player对象

谁调用函数,this就指向谁

当我们去到回调函数时候 函数作用域发生了改变

A.prototype.init=function(){ this指向A对象 this.age = 18 let that = this; let box = this.box box.addEventListener("type",function(){ 当前this对象不再指向A对象

	如果要修改A对象的age属性
	that.age = 20;
})

}

  1. 实例化子弹类的时机 如果一开始,在game的init方法里面,实例化子弹类 我们无法获取到,实例玩家飞机的坐标

解决方法,子弹类的默认位置,单独设置,与飞机坐标一致。

  1. 碰撞检测

一:采用最小最大顶点法描述AABB包围盒

上图中使用了最小最大顶点法来描述包围盒信息,由于是在屏幕坐标系中,y轴是向下延伸的,所以只需要保留矩形中坐标的最小值和最大值即可,即矩形的左上角和右下角的顶点,其他的点都在这两个点范围内。

在这种情况下要判断两个矩形是否碰撞只需要比较两个矩形顶点的坐标即可, 假设矩形 A用(x1, y1)表示左上角,(x2, y2)表示右下角, 矩形B用(x3, y3)表示左上角,(x4, y4)表示右下角, 则满足下列条件则表示没有碰撞,反之则碰撞。

没碰撞:x1>x4 或者x2<x3。

没碰撞:y1>y4 或者y2<y3。

所以,在程序中做二维游戏的AABB碰撞检测时,只需验证物体A与物体B是否满足如下条件:

(1)物体A的Y轴方向最小值大于物体B的Y轴方向最大值;

(2)物体A的X轴方向最小值大于物体B的X轴方向最大值;

(3)物体B的Y轴方向最小值大于物体A的Y轴方向最大值;

(4)物体B的X轴方向最小值大于物体A的X轴方向最大值;

若满足上述条件,则证明物体A与物体B并未发生重合,反之,则证明物体A与物体B重合

function hitTest(source, target) { /* 源物体和目标物体都包含 x, y 以及 width, height */ return !( ((source.y + source.r) < (target.y)) || (source.y > (target.y + target.r)) || ((source.x + source.r) < target.x) || (source.x > (target.x + target.r)) ); }

  1. 做这么项目的意义

  2. 大家收获了面向对象的开发模式 减少了全局变量的产生, 大家代码质量,从"杂乱无章"到 "稍微整洁"

  3. 编写逻辑代码之前

先把需求列出来, 针对需求,细化功能点

培养大家的条理性 流程图分析---编写成逻辑代码

调试代码习惯----debugger/console.log 大家后续也是会多用的

资料的查阅(帮助大家解决问题手段之一) ---- 结合自身自考----开发的过程

没有概念-如何查资料--使用--类似的关键词

第一次接触新事物,都会有蒙圈的过程,随着学习的沉淀,最终认清 事物的本质

除了收获知识点以外,更重要的是,大家从小白的无从下手,到熟练的开发习惯

结合项目

没有面向对象概念 ---- 前置知识点(创建对象的方法--工厂函数,构造函数,原型模式,原型+构造函数) ---- 资料来源 "红宝石书"--第6章第3节 ---- 原型,原型对象,实例的关系(前置知识,js基本数据类型与引用类型的区别)

飞机的及时坐标 如何 告诉给 子弹类 (快递) (收货人) 快递员 与 收货人 的故事 plane bullet 收货人 提供了 联系方式 bullet Bullet.prototype.setPos 快递员 调用 收货人的联系方式 --- 拿到最新快递 plane 可以调用 Bullet.prototype.setPos(x,y);

function setPos(x,y){ 拿到最新的坐标后, 更新到bullet的坐标属性 this.pos_x = x; 这个this是挂在 Bullet.prototype }

弯路---属性的所在地 Bullet.prototype.setPos(x,y) 最新的坐标是在Bullet.prorotype "优化过程"-一开始,设置 子弹的起始坐标---- this.pos_x = (Stage.width - this.bullet.width) / 2; 这就是bug所在的地方----靠理论来支撑

	bullet = new Bullet()----(new 操作符具体做了什么)
	
	bullet.pos_x = x;
	
	Bullet.prototype.pos_x = 最新的坐标值

当实例化对象 与 原型对象属性,同名时, JS选择实例化对象的同名属性,屏蔽,原型对象上的属性 (就近原则)

例子: function Boy(){} Boy.prototype.money = 100;

var boy = new Boy(); boy.money = 10;

console.log(boy.money)

解决方法 实例化对象 bullet里面,不要写pos_x属性,让他通过"原型链"去找

Bullet.prototype.setPos = function(pos_x,pos_y){ 兼容处理; this.pos_x = pos_x || (Stage.width - this.width) /2; }

plane_v0.7优化需求点

  1. 一颗子弹只能击落一架飞机
  2. 被击落的飞机,没必要参与下一帧的绘制
  3. 添加辅助功能---开始功能-重新功能---vip充值,飞机子弹换肤
  4. 批量产生子弹
  5. 分数显示,游戏结束的提醒

分析 一颗子弹只能击落一架飞机(已完成) 被击落的飞机,没必要参与下一帧的绘制(已完成) 解决方案: 把飞机移除数组外(逻辑层),飞机dom移除文档外(视图层)

原理 敌机/子弹 ----由一个数组来管理 击落飞机,子弹击落飞机的功能---- 触发----数组操作的条件(js逻辑层)

子弹的移动,敌机的移动-------- 触发-----html+css(视图层)

实际上,本质就是,

数组对象的curd(逻辑层)

dom节点的curd(视图层)

笔记 移除节点后,肯定会有各式各样的报错, 因为当前引用的对象,没有了

收尾部分 大家,自己尝试实现,批量产生"子弹"

(给大家大概15-20分钟完成,6点后讲)

修改"子弹与敌机的碰撞逻辑"

优化手段 数组( 别称: 对象池,队列)

·····关于数组知识的拓展 服务端的基本优化原因 1.减轻服务器的压力 2.防止机器程序的混入

队列----秒杀活动逻辑 ---- 来自四面八方对象 摇号---- 在数组里面产生一个随机数- 028[1,2,3,4] ·····

针对飞出屏幕的子弹,使用一个数组outBullet(对象池)进行回收 下一帧,不需要"从零创建子弹",直接使用outBullet里面的对象 达到,节省资源,提升性能的效果

这就是js设计模式中------享元模式

用户体验上提升 当我们的项目,部署到线上时,网络图片是需要时间去下载的 假如图片,没加载完,游戏就开始了,导致大量的子弹,会突然 闪现出来

解决方案---- 资源 "预加载" loading界面 如何实现 图片预加载

在js里面通过 new Image对象, 真正图片地址赋值给src属性 监听Image对象 onload事件(图片加载完成后会立刻执行)

一般来说,预加载会放在页面的"头部"运行

为什么图片打印的下标不是 0123? 0号图片 大小10K 1号图片 大小1K
每张图片的大小都无法保证一样

开发项目的一些细节

  1. 每次修改一行代码,不要着急上线 需要本地运行过,没问题了,再上传
  2. 上传代码,一般是上传到测试服务器,也没问题了 再更新到正式环境(如果公司经费有限,则测试服务器===正式环境)
  3. 提升用户体验----例如:添加一个预加载页面
  4. 提升程序的性能----例如:适当使用js设计模式(享元模式)