# Conflicts:
#	demo/libs/framework/framework.d.ts
#	demo/libs/framework/framework.min.js
#	demo/src/game/MainScene.ts
#	source/bin/framework.d.ts
#	source/bin/framework.min.js
This commit is contained in:
YHH
2020-07-12 09:46:07 +08:00
53 changed files with 2656 additions and 1222 deletions

View File

@@ -1,11 +1,12 @@
///<reference path="../Component.ts"/>
class Camera extends Component {
class Camera extends Component implements IUpdatable {
private _zoom;
private _origin: Vector2 = Vector2.zero;
private _minimumZoom = 0.3;
private _maximumZoom = 3;
private _position: Vector2 = Vector2.zero;
/**
* 如果相机模式为cameraWindow 则会进行缓动移动
* 该值为移动速度
@@ -67,11 +68,24 @@ class Camera extends Component {
}
public get position(){
return this.entity.position;
return this._position;
}
public set position(value: Vector2){
this.entity.position = value;
this._position = value;
}
public get x(){
return this._position.x;
}
public set x(value: number){
this._position.x = value;
}
public get y(){
return this._position.y;
}
public set y(value: number){
this._position.y = value;
}
constructor() {

View File

@@ -8,12 +8,16 @@ class BoxCollider extends Collider {
this.setWidth(value);
}
/**
* 设置BoxCollider的宽度
* @param width
*/
public setWidth(width: number): BoxCollider{
this._colliderRequiresAutoSizing = false;
let box = this.shape as Box;
if (width != box.width){
// 更新框,改变边界,如果我们需要更新物理系统中的边界
box.updateBox(width, box.height);
this._isPositionDirty = true;
if (this.entity && this._isParentEntityAddedToScene)
Physics.updateCollider(this);
}
@@ -29,20 +33,28 @@ class BoxCollider extends Collider {
this.setHeight(value);
}
/**
* 设置BoxCollider的高度
* @param height
*/
public setHeight(height: number){
this._colliderRequiresAutoSizing = false;
let box = this.shape as Box;
if (height != box.height){
// 更新框,改变边界,如果我们需要更新物理系统中的边界
box.updateBox(box.width, height);
this._isPositionDirty = true;
if (this.entity && this._isParentEntityAddedToScene)
Physics.updateCollider(this);
}
}
/**
* 零参数构造函数要求RenderableComponent在实体上这样碰撞器可以在实体被添加到场景时调整自身的大小。
*/
constructor(){
super();
// 我们在这里插入一个1x1框作为占位符直到碰撞器在下一阵被添加到实体并可以获得更精确的自动调整大小数据
this.shape = new Box(1, 1);
this._colliderRequiresAutoSizing = true;
}
@@ -51,8 +63,8 @@ class BoxCollider extends Collider {
this._colliderRequiresAutoSizing = false;
let box = this.shape as Box;
if (width != box.width || height != box.height){
// 更新框,改变边界,如果我们需要更新物理系统中的边界
box.updateBox(width, height);
this._isPositionDirty = true;
if (this.entity && this._isParentEntityAddedToScene)
Physics.updateCollider(this);
}

View File

@@ -0,0 +1,41 @@
class CircleCollider extends Collider {
public get radius(): number{
return (this.shape as Circle).radius;
}
public set radius(value: number){
this.setRadius(value);
}
/**
* 创建一个有半径的圆
*
* @param radius
*/
constructor(radius?: number){
super();
if (radius)
this._colliderRequiresAutoSizing = true;
// 我们在这里插入一个1px的圆圈作为占位符
// 直到碰撞器被添加到实体并可以获得更精确的自动调整大小数据的下一帧
this.shape = new Circle(radius ? radius : 1);
}
/**
* 设置圆的半径
* @param radius
*/
public setRadius(radius: number): CircleCollider{
this._colliderRequiresAutoSizing = false;
let circle = this.shape as Circle;
if (radius != circle.radius){
circle.radius = radius;
circle._originalRadius = radius;
if (this.entity && this._isParentEntityAddedToScene)
Physics.updateCollider(this);
}
return this;
}
}

View File

@@ -1,65 +1,89 @@
abstract class Collider extends Component{
abstract class Collider extends Component implements IUpdatable {
/** 对撞机的基本形状 */
public shape: Shape;
/** 在处理冲突时physicsLayer可以用作过滤器。Flags类有帮助位掩码的方法。 */
public physicsLayer = 1 << 0;
/** 如果这个碰撞器是一个触发器,它将不会引起碰撞,但它仍然会触发事件 */
public isTrigger: boolean;
public registeredPhysicsBounds: Rectangle;
public shouldColliderScaleAndRotationWithTransform = true;
/**
* 这个对撞机在物理系统注册时的边界。
* 存储这个允许我们始终能够安全地从物理系统中移除对撞机,即使它在试图移除它之前已经被移动了。
*/
public registeredPhysicsBounds: Rectangle = new Rectangle();
/** 如果为true碰撞器将根据附加的变换缩放和旋转 */
public shouldColliderScaleAndRotateWithTransform = true;
/** 默认为所有层。 */
public collidesWithLayers = Physics.allLayers;
public _localOffsetLength: number;
public _isPositionDirty = true;
public _isRotationDirty = true;
/** 标记来跟踪我们的实体是否被添加到场景中 */
protected _isParentEntityAddedToScene;
protected _colliderRequiresAutoSizing;
protected _localOffset: Vector2 = new Vector2(0, 0);
/** 标记来记录我们是否注册了物理系统 */
protected _isColliderRegistered;
public get bounds(): Rectangle {
if (this._isPositionDirty || this._isRotationDirty){
this.shape.recalculateBounds(this);
this._isPositionDirty = this._isRotationDirty = false;
}
this.shape.recalculateBounds(this);
return this.shape.bounds;
}
public get localOffset(){
public get localOffset() {
return this._localOffset;
}
public set localOffset(value: Vector2){
/**
* 将localOffset添加到实体。获取碰撞器的最终位置。这允许您向一个实体添加多个碰撞器并分别定位它们。
*/
public set localOffset(value: Vector2) {
this.setLocalOffset(value);
}
public setLocalOffset(offset: Vector2){
if (this._localOffset != offset){
public setLocalOffset(offset: Vector2) {
if (this._localOffset != offset) {
this.unregisterColliderWithPhysicsSystem();
this._localOffset = offset;
this._localOffsetLength = this._localOffset.length();
this._isPositionDirty = true;
this.registerColliderWithPhysicsSystem();
}
}
public registerColliderWithPhysicsSystem(){
if (this._isParentEntityAddedToScene && !this._isColliderRegistered){
/**
* 父实体会在不同的时间调用它(当添加到场景,启用,等等)
*/
public registerColliderWithPhysicsSystem() {
// 如果在将我们添加到实体之前更改了origin等属性则实体可以为null
if (this._isParentEntityAddedToScene && !this._isColliderRegistered) {
Physics.addCollider(this);
this._isColliderRegistered = true;
}
}
public unregisterColliderWithPhysicsSystem(){
if (this._isParentEntityAddedToScene && this._isColliderRegistered){
/**
* 父实体会在不同的时候调用它(从场景中移除,禁用,等等)
*/
public unregisterColliderWithPhysicsSystem() {
if (this._isParentEntityAddedToScene && this._isColliderRegistered) {
Physics.removeCollider(this);
}
this._isColliderRegistered = false;
}
public overlaps(other: Collider){
/**
* 检查这个形状是否与物理系统中的其他对撞机重叠
* @param other
*/
public overlaps(other: Collider) {
return this.shape.overlaps(other.shape);
}
public collidesWith(collider: Collider, motion: Vector2){
/**
* 检查这个与运动应用的碰撞器(移动向量)是否与碰撞器碰撞。如果是这样将返回true并且结果将填充碰撞数据。
* @param collider
* @param motion
*/
public collidesWith(collider: Collider, motion: Vector2) {
// 改变形状的位置,使它在移动后的位置,这样我们可以检查重叠
let oldPosition = this.shape.position;
this.shape.position = Vector2.add(this.shape.position, motion);
@@ -67,49 +91,71 @@ abstract class Collider extends Component{
if (result)
result.collider = collider;
// 将图形位置返回到检查前的位置
this.shape.position = oldPosition;
return result;
}
public onAddedToEntity(){
if (this._colliderRequiresAutoSizing){
if (!(this instanceof BoxCollider)){
public onAddedToEntity() {
if (this._colliderRequiresAutoSizing) {
if (!(this instanceof BoxCollider || this instanceof CircleCollider)) {
console.error("Only box and circle colliders can be created automatically");
}
let renderable = this.entity.getComponent<RenderableComponent>(RenderableComponent);
if (renderable){
let renderbaleBounds = renderable.bounds;
if (renderable) {
let bounds = renderable.bounds;
let width = renderbaleBounds.width / this.entity.scale.x;
let height = renderbaleBounds.height / this.entity.scale.y;
// 这里我们需要大小*反尺度,因为当我们自动调整碰撞器的大小时,它需要没有缩放的渲染
let width = bounds.width / this.entity.scale.x;
let height = bounds.height / this.entity.scale.y;
if (this instanceof BoxCollider){
let boxCollider = this as BoxCollider;
// 圆碰撞器需要特别注意原点
if (this instanceof CircleCollider){
let circleCollider = this as CircleCollider;
circleCollider.radius = Math.max(width, height) * 0.5;
this.localOffset = bounds.location;
} else {
let boxCollider = this;
boxCollider.width = width;
boxCollider.height = height;
this.localOffset = Vector2.subtract(renderbaleBounds.center, this.entity.position);
this.localOffset = bounds.location;
}
} else {
console.warn("Collider has no shape and no RenderableComponent. Can't figure out how to size it.");
}
}
this._isParentEntityAddedToScene = true;
this.registerColliderWithPhysicsSystem();
}
public onRemovedFromEntity(){
public onRemovedFromEntity() {
this.unregisterColliderWithPhysicsSystem();
this._isParentEntityAddedToScene = false;
}
public onEnabled(){
public onEnabled() {
this.registerColliderWithPhysicsSystem();
this._isPositionDirty = this._isRotationDirty = true;
}
public onDisabled(){
public onDisabled() {
this.unregisterColliderWithPhysicsSystem();
}
public onEntityTransformChanged(comp: TransformComponent) {
if (this._isColliderRegistered)
Physics.updateCollider(this);
}
public update(){
let renderable = this.entity.getComponent<RenderableComponent>(RenderableComponent);
if (renderable){
this.$setX(renderable.x + this.localOffset.x);
this.$setY(renderable.y + this.localOffset.y);
}
}
}

View File

@@ -0,0 +1,24 @@
/**
* 多边形应该以顺时针方式定义
*/
class PolygonCollider extends Collider {
/**
* 如果这些点没有居中它们将以localOffset的差异为居中。
* @param points
*/
constructor(points: Vector2[]){
super();
// 第一点和最后一点决不能相同。我们想要一个开放的多边形
let isPolygonClosed = points[0] == points[points.length - 1];
// 最后一个移除
if (isPolygonClosed)
points.splice(points.length - 1, 1);
let center = Polygon.findPolygonCenter(points);
this.setLocalOffset(center);
Polygon.recenterPolygonVerts(points);
this.shape = new Polygon(points);
}
}

View File

@@ -1,3 +1,10 @@
/**
* 辅助类说明了一种处理移动的方法,它考虑了包括触发器在内的所有冲突。
* ITriggerListener接口用于管理对移动过程中违反的任何触发器的回调。
* 一个物体只能通过移动器移动。要正确报告触发器的move方法。
*
* 请注意多个移动者相互交互将多次调用ITriggerListener。
*/
class Mover extends Component {
private _triggerHelper: ColliderTriggerHelper;
@@ -5,6 +12,10 @@ class Mover extends Component {
this._triggerHelper = new ColliderTriggerHelper(this.entity);
}
/**
* 计算修改运动矢量的运动,以考虑移动时可能发生的碰撞
* @param motion
*/
public calculateMovement(motion: Vector2){
let collisionResult = new CollisionResult();
@@ -16,23 +27,30 @@ class Mover extends Component {
for (let i = 0; i < colliders.length; i ++){
let collider = colliders[i];
// 不检测触发器
if (collider.isTrigger)
continue;
// 获取我们在新位置可能发生碰撞的任何东西
let bounds = collider.bounds;
bounds.x += motion.x;
bounds.y += motion.y;
let neighbors = Physics.boxcastBroadphaseExcludingSelf(collider, bounds, collider.collidesWithLayers);
let boxcastResult = Physics.boxcastBroadphaseExcludingSelf(collider, bounds, collider.collidesWithLayers);
bounds = boxcastResult.bounds;
let neighbors = boxcastResult.tempHashSet;
for (let j = 0; j < neighbors.length; j ++){
let neighbor = neighbors[j];
// 不检测触发器
if (neighbor.isTrigger)
continue;
let _internalcollisionResult = collider.collidesWith(neighbor, motion);
if (_internalcollisionResult){
// 如果碰撞 则退回之前的移动量
motion = Vector2.subtract(motion, _internalcollisionResult.minimumTranslationVector);
// 如果我们碰到多个对象,为了简单起见,只取第一个。
if (_internalcollisionResult.collider){
collisionResult = _internalcollisionResult;
}
@@ -42,7 +60,7 @@ class Mover extends Component {
ListPool.free(colliders);
return collisionResult;
return {collisionResult: collisionResult, motion: motion};
}
public applyMovement(motion: Vector2){
@@ -53,7 +71,9 @@ class Mover extends Component {
}
public move(motion: Vector2){
let collisionResult = this.calculateMovement(motion);
let movementResult = this.calculateMovement(motion);
let collisionResult = movementResult.collisionResult;
motion = movementResult.motion;
this.applyMovement(motion);

View File

@@ -1,5 +1,5 @@
///<reference path="./SpriteRenderer.ts" />
class SpriteAnimator extends SpriteRenderer {
class SpriteAnimator extends SpriteRenderer implements IUpdatable {
/** 在动画完成时触发,包括动画名称; */
public onAnimationCompletedEvent: Function;
/** 动画播放速度 */

View File

@@ -1,25 +1,12 @@
class SpriteRenderer extends RenderableComponent {
private _origin: Vector2;
private _sprite: Sprite;
protected bitmap: egret.Bitmap;
public get origin(){
return this._origin;
}
public set origin(value: Vector2){
this.setOrigin(value);
}
public setOrigin(origin: Vector2){
if (this._origin != origin){
this._origin = origin;
}
return this;
}
/** 应该由这个精灵显示的精灵。当设置时,精灵的原点也被设置为匹配精灵.origin。 */
/** 应该由这个精灵显示的精灵 */
public get sprite(): Sprite{
return this._sprite;
}
/** 应该由这个精灵显示的精灵。当设置时,精灵的原点也被设置为匹配精灵.origin。 */
/** 应该由这个精灵显示的精灵 */
public set sprite(value: Sprite){
this.setSprite(value);
}
@@ -27,7 +14,10 @@ class SpriteRenderer extends RenderableComponent {
public setSprite(sprite: Sprite): SpriteRenderer{
this.removeChildren();
this._sprite = sprite;
if (this._sprite) this._origin = this._sprite.origin;
if (this._sprite) {
this.anchorOffsetX = this._sprite.origin.x / this._sprite.sourceRect.width;
this.anchorOffsetY = this._sprite.origin.y / this._sprite.sourceRect.height;
}
this.bitmap = new egret.Bitmap(sprite.texture2D);
this.addChild(this.bitmap);
@@ -58,8 +48,8 @@ class SpriteRenderer extends RenderableComponent {
/** 渲染处理 在每个模块中处理各自的渲染逻辑 */
public render(camera: Camera){
this.x = this.entity.position.x - this.origin.x - camera.position.x + camera.origin.x;
this.y = this.entity.position.y - this.origin.y - camera.position.y + camera.origin.y;
this.x = -camera.position.x + camera.origin.x;
this.y = -camera.position.y + camera.origin.y;
}
public onRemovedFromEntity(){