新增mover移动器组件 用于处理itriggerListener接口碰撞信息

This commit is contained in:
yhh
2020-06-16 11:22:37 +08:00
parent 75301f7776
commit 8b21edc65f
22 changed files with 671 additions and 46 deletions

View File

@@ -20,8 +20,8 @@
- [ ] ECS - [ ] ECS
- [ ] 组件列表 - [ ] 组件列表
- [ ] 碰撞组件 - [x] 碰撞组件
- [ ] 移动组件 - [x] 移动组件
- [ ] 刚体组件 - [ ] 刚体组件
- [ ] 点光源/灯光组件 - [ ] 点光源/灯光组件
- [ ] 阴影组件 - [ ] 阴影组件

View File

@@ -194,7 +194,7 @@ declare class Entity {
hasComponent<T extends Component>(type: any): boolean; hasComponent<T extends Component>(type: any): boolean;
getOrCreateComponent<T extends Component>(type: T): T; getOrCreateComponent<T extends Component>(type: T): T;
getComponent<T extends Component>(type: any): T; getComponent<T extends Component>(type: any): T;
getComponents(typeName: string, componentList?: any): any; getComponents(typeName: string | any, componentList?: any): any;
removeComponentForType<T extends Component>(type: any): boolean; removeComponentForType<T extends Component>(type: any): boolean;
removeComponent(component: Component): void; removeComponent(component: Component): void;
removeAllComponents(): void; removeAllComponents(): void;
@@ -381,6 +381,13 @@ interface ITriggerListener {
onTriggerEnter(other: Collider, local: Collider): any; onTriggerEnter(other: Collider, local: Collider): any;
onTriggerExit(other: Collider, local: Collider): any; onTriggerExit(other: Collider, local: Collider): any;
} }
declare class Mover extends Component {
private _triggerHelper;
onAddedToEntity(): void;
calculateMovement(motion: Vector2): CollisionResult;
applyMovement(motion: Vector2): void;
move(motion: Vector2): CollisionResult;
}
declare abstract class Collider extends Component { declare abstract class Collider extends Component {
shape: Shape; shape: Shape;
physicsLayer: number; physicsLayer: number;
@@ -389,9 +396,9 @@ declare abstract class Collider extends Component {
shouldColliderScaleAndRotationWithTransform: boolean; shouldColliderScaleAndRotationWithTransform: boolean;
collidesWithLayers: number; collidesWithLayers: number;
_localOffsetLength: number; _localOffsetLength: number;
_isPositionDirty: boolean;
_isRotationDirty: boolean;
protected _isParentEntityAddedToScene: any; protected _isParentEntityAddedToScene: any;
protected _isPositionDirty: boolean;
protected _isRotationDirty: boolean;
protected _colliderRequiresAutoSizing: any; protected _colliderRequiresAutoSizing: any;
protected _localOffset: Vector2; protected _localOffset: Vector2;
protected _isColliderRegisterd: any; protected _isColliderRegisterd: any;
@@ -401,6 +408,8 @@ declare abstract class Collider extends Component {
registerColliderWithPhysicsSystem(): void; registerColliderWithPhysicsSystem(): void;
unregisterColliderWithPhysicsSystem(): void; unregisterColliderWithPhysicsSystem(): void;
overlaps(other: Collider): any; overlaps(other: Collider): any;
collidesWith(collider: Collider, motion: Vector2): CollisionResult;
onAddedToEntity(): void;
onEntityTransformChanged(comp: ComponentTransform): void; onEntityTransformChanged(comp: ComponentTransform): void;
onEnabled(): void; onEnabled(): void;
onDisabled(): void; onDisabled(): void;
@@ -471,7 +480,7 @@ declare class ComponentList {
updateLists(): void; updateLists(): void;
private handleRemove; private handleRemove;
getComponent<T extends Component>(type: any, onlyReturnInitializedComponents: boolean): T; getComponent<T extends Component>(type: any, onlyReturnInitializedComponents: boolean): T;
getComponents(typeName: string, components?: any): any; getComponents(typeName: string | any, components?: any): any;
update(): void; update(): void;
onEntityTransformChanged(comp: any): void; onEntityTransformChanged(comp: any): void;
} }
@@ -588,6 +597,7 @@ declare class Rectangle {
readonly right: number; readonly right: number;
readonly top: number; readonly top: number;
readonly bottom: number; readonly bottom: number;
readonly center: Vector2;
location: Vector2; location: Vector2;
constructor(x?: number, y?: number, width?: number, height?: number); constructor(x?: number, y?: number, width?: number, height?: number);
intersects(value: Rectangle): boolean; intersects(value: Rectangle): boolean;
@@ -598,6 +608,7 @@ declare class Rectangle {
edgeNormal: Vector2; edgeNormal: Vector2;
}; };
calculateBounds(parentPosition: Vector2, position: Vector2, origin: Vector2, scale: Vector2, rotation: number, width: number, height: number): void; calculateBounds(parentPosition: Vector2, position: Vector2, origin: Vector2, scale: Vector2, rotation: number, width: number, height: number): void;
static rectEncompassingPoints(points: Vector2[]): Rectangle;
} }
declare class Vector2 { declare class Vector2 {
x: number; x: number;
@@ -663,6 +674,7 @@ declare class Physics {
static readonly allLayers: number; static readonly allLayers: number;
static overlapCircleAll(center: Vector2, randius: number, results: any[], layerMask?: number): number; static overlapCircleAll(center: Vector2, randius: number, results: any[], layerMask?: number): number;
static boxcastBroadphase(rect: Rectangle, layerMask?: number): Collider[]; static boxcastBroadphase(rect: Rectangle, layerMask?: number): Collider[];
static boxcastBroadphaseExcludingSelf(collider: Collider, rect: Rectangle, layerMask?: number): Collider[];
static addCollider(collider: Collider): void; static addCollider(collider: Collider): void;
static removeCollider(collider: Collider): void; static removeCollider(collider: Collider): void;
static updateCollider(collider: Collider): void; static updateCollider(collider: Collider): void;
@@ -674,6 +686,7 @@ declare abstract class Shape {
abstract recalculateBounds(collider: Collider): any; abstract recalculateBounds(collider: Collider): any;
abstract pointCollidesWithShape(point: Vector2): CollisionResult; abstract pointCollidesWithShape(point: Vector2): CollisionResult;
abstract overlaps(other: Shape): any; abstract overlaps(other: Shape): any;
abstract collidesWithShape(other: Shape): CollisionResult;
} }
declare class Polygon extends Shape { declare class Polygon extends Shape {
points: Vector2[]; points: Vector2[];
@@ -717,6 +730,7 @@ declare class Circle extends Shape {
overlaps(other: Shape): any; overlaps(other: Shape): any;
} }
declare class CollisionResult { declare class CollisionResult {
collider: Collider;
minimumTranslationVector: Vector2; minimumTranslationVector: Vector2;
normal: Vector2; normal: Vector2;
point: Vector2; point: Vector2;
@@ -798,6 +812,8 @@ declare class Vector2Ext {
static cross(u: Vector2, v: Vector2): number; static cross(u: Vector2, v: Vector2): number;
static perpendicular(first: Vector2, second: Vector2): Vector2; static perpendicular(first: Vector2, second: Vector2): Vector2;
static normalize(vec: Vector2): Vector2; static normalize(vec: Vector2): Vector2;
static transformA(sourceArray: Vector2[], sourceIndex: number, matrix: Matrix2D, destinationArray: Vector2[], destinationIndex: number, length: number): void;
static transform(sourceArray: Vector2[], matrix: Matrix2D, destinationArray: Vector2[]): void;
} }
declare class WebGLUtils { declare class WebGLUtils {
static getWebGL(): WebGLRenderingContext; static getWebGL(): WebGLRenderingContext;

View File

@@ -1786,6 +1786,56 @@ var SpriteRenderer = (function (_super) {
}; };
return SpriteRenderer; return SpriteRenderer;
}(RenderableComponent)); }(RenderableComponent));
var Mover = (function (_super) {
__extends(Mover, _super);
function Mover() {
return _super !== null && _super.apply(this, arguments) || this;
}
Mover.prototype.onAddedToEntity = function () {
this._triggerHelper = new ColliderTriggerHelper(this.entity);
};
Mover.prototype.calculateMovement = function (motion) {
var collisionResult = new CollisionResult();
if (!this.entity.getComponent(Collider) || !this._triggerHelper) {
return null;
}
var colliders = this.entity.getComponents(Collider);
for (var i = 0; i < colliders.length; i++) {
var collider = colliders[i];
if (collider.isTrigger)
continue;
var bounds = collider.bounds;
bounds.x += motion.x;
bounds.y += motion.y;
var neighbors = Physics.boxcastBroadphaseExcludingSelf(collider, bounds, collider.collidesWithLayers);
for (var j = 0; j < neighbors.length; j++) {
var neighbor = neighbors[j];
if (neighbor.isTrigger)
continue;
var _internalcollisionResult = collider.collidesWith(neighbor, motion);
if (_internalcollisionResult) {
motion = Vector2.subtract(motion, _internalcollisionResult.minimumTranslationVector);
if (_internalcollisionResult.collider) {
collisionResult = _internalcollisionResult;
}
}
}
}
ListPool.free(colliders);
return collisionResult;
};
Mover.prototype.applyMovement = function (motion) {
this.entity.transform.position = Vector2.add(this.entity.transform.position, motion);
if (this._triggerHelper)
this._triggerHelper.update();
};
Mover.prototype.move = function (motion) {
var collisionResult = this.calculateMovement(motion);
this.applyMovement(motion);
return collisionResult;
};
return Mover;
}(Component));
var Collider = (function (_super) { var Collider = (function (_super) {
__extends(Collider, _super); __extends(Collider, _super);
function Collider() { function Collider() {
@@ -1842,6 +1892,36 @@ var Collider = (function (_super) {
Collider.prototype.overlaps = function (other) { Collider.prototype.overlaps = function (other) {
return this.shape.overlaps(other.shape); return this.shape.overlaps(other.shape);
}; };
Collider.prototype.collidesWith = function (collider, motion) {
var oldPosition = this.shape.position;
this.shape.position = Vector2.add(this.shape.position, motion);
var result = this.shape.collidesWithShape(collider.shape);
if (result)
result.collider = collider;
this.shape.position = oldPosition;
return result;
};
Collider.prototype.onAddedToEntity = function () {
if (this._colliderRequiresAutoSizing) {
if (!(this instanceof BoxCollider)) {
console.error("Only box and circle colliders can be created automatically");
}
var renderable = this.entity.getComponent(RenderableComponent);
if (!renderable) {
var renderbaleBounds = renderable.bounds;
var width = renderbaleBounds.width / this.entity.transform.scale.x;
var height = renderbaleBounds.height / this.entity.transform.scale.y;
if (this instanceof BoxCollider) {
var boxCollider = this;
boxCollider.width = width;
boxCollider.height = height;
this.localOffset = Vector2.subtract(renderbaleBounds.center, this.entity.transform.position);
}
}
}
this._isParentEntityAddedToScene = true;
this.registerColliderWithPhysicsSystem();
};
Collider.prototype.onEntityTransformChanged = function (comp) { Collider.prototype.onEntityTransformChanged = function (comp) {
switch (comp) { switch (comp) {
case ComponentTransform.position: case ComponentTransform.position:
@@ -2213,13 +2293,19 @@ var ComponentList = (function () {
components = []; components = [];
for (var i = 0; i < this._components.length; i++) { for (var i = 0; i < this._components.length; i++) {
var component = this._components[i]; var component = this._components[i];
if (egret.is(component, typeName)) if (typeof (typeName) == "string" && egret.is(component, typeName))
components.push(component); components.push(component);
else if (component instanceof typeName) {
components.push(component);
}
} }
for (var i = 0; i < this._componentsToAdd.length; i++) { for (var i = 0; i < this._componentsToAdd.length; i++) {
var component = this._componentsToAdd[i]; var component = this._componentsToAdd[i];
if (egret.is(component, typeName)) if (typeof (typeName) == "string" && egret.is(component, typeName))
components.push(component); components.push(component);
else if (component instanceof typeName) {
components.push(component);
}
} }
return components; return components;
}; };
@@ -2721,6 +2807,13 @@ var Rectangle = (function () {
enumerable: true, enumerable: true,
configurable: true configurable: true
}); });
Object.defineProperty(Rectangle.prototype, "center", {
get: function () {
return new Vector2(this.x + (this.width / 2), this.y + (this.height / 2));
},
enumerable: true,
configurable: true
});
Object.defineProperty(Rectangle.prototype, "location", { Object.defineProperty(Rectangle.prototype, "location", {
get: function () { get: function () {
return new Vector2(this.x, this.y); return new Vector2(this.x, this.y);
@@ -2824,6 +2917,28 @@ var Rectangle = (function () {
this.height = maxY - minY; this.height = maxY - minY;
} }
}; };
Rectangle.rectEncompassingPoints = function (points) {
var minX = Number.POSITIVE_INFINITY;
var minY = Number.POSITIVE_INFINITY;
var maxX = Number.NEGATIVE_INFINITY;
var maxY = Number.NEGATIVE_INFINITY;
for (var i = 0; i < points.length; i++) {
var pt = points[i];
if (pt.x < minX) {
minX = pt.x;
}
if (pt.x > maxX) {
maxX = pt.x;
}
if (pt.y < minY) {
minY = pt.y;
}
if (pt.y > maxY) {
maxY = pt.y;
}
}
return this.fromMinMax(minX, minY, maxX, maxY);
};
return Rectangle; return Rectangle;
}()); }());
var Vector2 = (function () { var Vector2 = (function () {
@@ -2936,7 +3051,7 @@ var ColliderTriggerHelper = (function () {
this._entity = entity; this._entity = entity;
} }
ColliderTriggerHelper.prototype.update = function () { ColliderTriggerHelper.prototype.update = function () {
var colliders = this._entity.getComponents("Collider"); var colliders = this._entity.getComponents(Collider);
for (var i = 0; i < colliders.length; i++) { for (var i = 0; i < colliders.length; i++) {
var collider = colliders[i]; var collider = colliders[i];
var neighbors = Physics.boxcastBroadphase(collider.bounds, collider.collidesWithLayers); var neighbors = Physics.boxcastBroadphase(collider.bounds, collider.collidesWithLayers);
@@ -3138,6 +3253,10 @@ var Physics = (function () {
if (layerMask === void 0) { layerMask = this.allLayers; } if (layerMask === void 0) { layerMask = this.allLayers; }
return this._spatialHash.aabbBroadphase(rect, null, layerMask); return this._spatialHash.aabbBroadphase(rect, null, layerMask);
}; };
Physics.boxcastBroadphaseExcludingSelf = function (collider, rect, layerMask) {
if (layerMask === void 0) { layerMask = this.allLayers; }
return this._spatialHash.aabbBroadphase(rect, collider, layerMask);
};
Physics.addCollider = function (collider) { Physics.addCollider = function (collider) {
Physics._spatialHash.register(collider); Physics._spatialHash.register(collider);
}; };
@@ -3191,14 +3310,27 @@ var Polygon = (function (_super) {
} }
}; };
Polygon.prototype.setPoints = function (points) { Polygon.prototype.setPoints = function (points) {
var _this = this;
this.points = points; this.points = points;
this.recalculateCenterAndEdgeNormals(); this.recalculateCenterAndEdgeNormals();
this._originalPoints = new Array(points.length); this._originalPoints = new Array(this.points.length);
this._originalPoints = points; this.points.forEach(function (point) { return _this._originalPoints.push(point); });
}; };
Polygon.prototype.collidesWithShape = function (other) { Polygon.prototype.collidesWithShape = function (other) {
if (other instanceof Polygon) var result = new CollisionResult();
return ShapeCollisions.polygonToPolygon(this, other); if (other instanceof Polygon) {
result = ShapeCollisions.polygonToPolygon(this, other);
return result;
}
if (other instanceof Circle) {
result = ShapeCollisions.circleToPolygon(other, this);
if (result) {
result.invertResult();
return result;
}
return null;
}
throw new Error("overlaps of Polygon to " + other + " are not supported");
}; };
Polygon.prototype.recalculateCenterAndEdgeNormals = function () { Polygon.prototype.recalculateCenterAndEdgeNormals = function () {
this._polygonCenter = Polygon.findPolygonCenter(this.points); this._polygonCenter = Polygon.findPolygonCenter(this.points);
@@ -3273,6 +3405,34 @@ var Polygon = (function (_super) {
}; };
Polygon.prototype.recalculateBounds = function (collider) { Polygon.prototype.recalculateBounds = function (collider) {
this.center = collider.localOffset; this.center = collider.localOffset;
if (collider.shouldColliderScaleAndRotationWithTransform) {
var hasUnitScale = true;
var tempMat = void 0;
var combinedMatrix = Matrix2D.createTranslation(-this._polygonCenter.x, -this._polygonCenter.y);
if (collider.entity.transform.scale != Vector2.one) {
tempMat = Matrix2D.createScale(collider.entity.transform.scale.x, collider.entity.transform.scale.y);
combinedMatrix = Matrix2D.multiply(combinedMatrix, tempMat);
hasUnitScale = false;
var scaledOffset = Vector2.multiply(collider.localOffset, collider.entity.transform.scale);
this.center = scaledOffset;
}
if (collider.entity.transform.rotation != 0) {
tempMat = Matrix2D.createRotation(collider.entity.transform.rotation);
combinedMatrix = Matrix2D.multiply(combinedMatrix, tempMat);
var offsetAngle = Math.atan2(collider.localOffset.y, collider.localOffset.x) * MathHelper.Rad2Deg;
var offsetLength = hasUnitScale ? collider._localOffsetLength : (Vector2.multiply(collider.localOffset, collider.entity.transform.scale)).length();
this.center = MathHelper.pointOnCirlce(Vector2.zero, offsetLength, collider.entity.transform.rotationDegrees + offsetAngle);
}
tempMat = Matrix2D.createTranslation(this._polygonCenter.x, this._polygonCenter.y);
combinedMatrix = Matrix2D.multiply(combinedMatrix, tempMat);
Vector2Ext.transform(this._originalPoints, combinedMatrix, this.points);
this.isUnrotated = collider.entity.transform.rotation == 0;
if (collider._isRotationDirty)
this._areEdgeNormalsDirty = true;
}
this.position = Vector2.add(collider.entity.transform.position, this.center);
this.bounds = Rectangle.rectEncompassingPoints(this.points);
this.bounds.location = Vector2.add(this.bounds.location, this.position);
}; };
return Polygon; return Polygon;
}(Shape)); }(Shape));
@@ -3809,6 +3969,18 @@ var Vector2Ext = (function () {
} }
return vec; return vec;
}; };
Vector2Ext.transformA = function (sourceArray, sourceIndex, matrix, destinationArray, destinationIndex, length) {
for (var i = 0; i < length; i++) {
var position = sourceArray[sourceIndex + i];
var destination = destinationArray[destinationIndex + 1];
destination.x = (position.x * matrix.m11) + (position.y * matrix.m21) + matrix.m31;
destination.y = (position.x * matrix.m12) + (position.y * matrix.m22) + matrix.m32;
destinationArray[destinationIndex + i] = destination;
}
};
Vector2Ext.transform = function (sourceArray, matrix, destinationArray) {
this.transformA(sourceArray, 0, matrix, destinationArray, 0, sourceArray.length);
};
return Vector2Ext; return Vector2Ext;
}()); }());
var WebGLUtils = (function () { var WebGLUtils = (function () {

File diff suppressed because one or more lines are too long

View File

@@ -106,12 +106,13 @@ class Main extends eui.UILayer {
new Vector2(0, 0)])); new Vector2(0, 0)]));
player.addComponent(new SpawnComponent(EnemyType.worm)); player.addComponent(new SpawnComponent(EnemyType.worm));
player.addComponent(new BoxCollider()); player.addComponent(new BoxCollider());
player.addComponent(new Mover());
let player2 = scene.createEntity("player2"); let player2 = scene.createEntity("player2");
player2.addComponent(new BoxCollider()); player2.addComponent(new BoxCollider());
Main.emitter.addObserver(CoreEmitterType.Update, ()=>{ // Main.emitter.addObserver(CoreEmitterType.Update, ()=>{
console.log("update emitter"); // console.log("update emitter");
}); // });
} }
} }

View File

@@ -1,4 +1,4 @@
class SpawnComponent extends Component { class SpawnComponent extends Component implements ITriggerListener {
public cooldown = -1; public cooldown = -1;
public minInterval = 2; public minInterval = 2;
public maxInterval = 60; public maxInterval = 60;
@@ -17,6 +17,15 @@ class SpawnComponent extends Component {
public update() { public update() {
// console.log("update"); // console.log("update");
this.entity.getComponent<Mover>(Mover).move(new Vector2(1, 0));
}
public onTriggerEnter(other: Collider, local: Collider){
console.log("enter collider", other, local);
}
public onTriggerExit(other: Collider, local: Collider){
console.log("exit collider", other, local);
} }
} }

View File

@@ -194,7 +194,7 @@ declare class Entity {
hasComponent<T extends Component>(type: any): boolean; hasComponent<T extends Component>(type: any): boolean;
getOrCreateComponent<T extends Component>(type: T): T; getOrCreateComponent<T extends Component>(type: T): T;
getComponent<T extends Component>(type: any): T; getComponent<T extends Component>(type: any): T;
getComponents(typeName: string, componentList?: any): any; getComponents(typeName: string | any, componentList?: any): any;
removeComponentForType<T extends Component>(type: any): boolean; removeComponentForType<T extends Component>(type: any): boolean;
removeComponent(component: Component): void; removeComponent(component: Component): void;
removeAllComponents(): void; removeAllComponents(): void;
@@ -381,6 +381,13 @@ interface ITriggerListener {
onTriggerEnter(other: Collider, local: Collider): any; onTriggerEnter(other: Collider, local: Collider): any;
onTriggerExit(other: Collider, local: Collider): any; onTriggerExit(other: Collider, local: Collider): any;
} }
declare class Mover extends Component {
private _triggerHelper;
onAddedToEntity(): void;
calculateMovement(motion: Vector2): CollisionResult;
applyMovement(motion: Vector2): void;
move(motion: Vector2): CollisionResult;
}
declare abstract class Collider extends Component { declare abstract class Collider extends Component {
shape: Shape; shape: Shape;
physicsLayer: number; physicsLayer: number;
@@ -389,9 +396,9 @@ declare abstract class Collider extends Component {
shouldColliderScaleAndRotationWithTransform: boolean; shouldColliderScaleAndRotationWithTransform: boolean;
collidesWithLayers: number; collidesWithLayers: number;
_localOffsetLength: number; _localOffsetLength: number;
_isPositionDirty: boolean;
_isRotationDirty: boolean;
protected _isParentEntityAddedToScene: any; protected _isParentEntityAddedToScene: any;
protected _isPositionDirty: boolean;
protected _isRotationDirty: boolean;
protected _colliderRequiresAutoSizing: any; protected _colliderRequiresAutoSizing: any;
protected _localOffset: Vector2; protected _localOffset: Vector2;
protected _isColliderRegisterd: any; protected _isColliderRegisterd: any;
@@ -401,6 +408,8 @@ declare abstract class Collider extends Component {
registerColliderWithPhysicsSystem(): void; registerColliderWithPhysicsSystem(): void;
unregisterColliderWithPhysicsSystem(): void; unregisterColliderWithPhysicsSystem(): void;
overlaps(other: Collider): any; overlaps(other: Collider): any;
collidesWith(collider: Collider, motion: Vector2): CollisionResult;
onAddedToEntity(): void;
onEntityTransformChanged(comp: ComponentTransform): void; onEntityTransformChanged(comp: ComponentTransform): void;
onEnabled(): void; onEnabled(): void;
onDisabled(): void; onDisabled(): void;
@@ -471,7 +480,7 @@ declare class ComponentList {
updateLists(): void; updateLists(): void;
private handleRemove; private handleRemove;
getComponent<T extends Component>(type: any, onlyReturnInitializedComponents: boolean): T; getComponent<T extends Component>(type: any, onlyReturnInitializedComponents: boolean): T;
getComponents(typeName: string, components?: any): any; getComponents(typeName: string | any, components?: any): any;
update(): void; update(): void;
onEntityTransformChanged(comp: any): void; onEntityTransformChanged(comp: any): void;
} }
@@ -588,6 +597,7 @@ declare class Rectangle {
readonly right: number; readonly right: number;
readonly top: number; readonly top: number;
readonly bottom: number; readonly bottom: number;
readonly center: Vector2;
location: Vector2; location: Vector2;
constructor(x?: number, y?: number, width?: number, height?: number); constructor(x?: number, y?: number, width?: number, height?: number);
intersects(value: Rectangle): boolean; intersects(value: Rectangle): boolean;
@@ -598,6 +608,7 @@ declare class Rectangle {
edgeNormal: Vector2; edgeNormal: Vector2;
}; };
calculateBounds(parentPosition: Vector2, position: Vector2, origin: Vector2, scale: Vector2, rotation: number, width: number, height: number): void; calculateBounds(parentPosition: Vector2, position: Vector2, origin: Vector2, scale: Vector2, rotation: number, width: number, height: number): void;
static rectEncompassingPoints(points: Vector2[]): Rectangle;
} }
declare class Vector2 { declare class Vector2 {
x: number; x: number;
@@ -663,6 +674,7 @@ declare class Physics {
static readonly allLayers: number; static readonly allLayers: number;
static overlapCircleAll(center: Vector2, randius: number, results: any[], layerMask?: number): number; static overlapCircleAll(center: Vector2, randius: number, results: any[], layerMask?: number): number;
static boxcastBroadphase(rect: Rectangle, layerMask?: number): Collider[]; static boxcastBroadphase(rect: Rectangle, layerMask?: number): Collider[];
static boxcastBroadphaseExcludingSelf(collider: Collider, rect: Rectangle, layerMask?: number): Collider[];
static addCollider(collider: Collider): void; static addCollider(collider: Collider): void;
static removeCollider(collider: Collider): void; static removeCollider(collider: Collider): void;
static updateCollider(collider: Collider): void; static updateCollider(collider: Collider): void;
@@ -674,6 +686,7 @@ declare abstract class Shape {
abstract recalculateBounds(collider: Collider): any; abstract recalculateBounds(collider: Collider): any;
abstract pointCollidesWithShape(point: Vector2): CollisionResult; abstract pointCollidesWithShape(point: Vector2): CollisionResult;
abstract overlaps(other: Shape): any; abstract overlaps(other: Shape): any;
abstract collidesWithShape(other: Shape): CollisionResult;
} }
declare class Polygon extends Shape { declare class Polygon extends Shape {
points: Vector2[]; points: Vector2[];
@@ -717,6 +730,7 @@ declare class Circle extends Shape {
overlaps(other: Shape): any; overlaps(other: Shape): any;
} }
declare class CollisionResult { declare class CollisionResult {
collider: Collider;
minimumTranslationVector: Vector2; minimumTranslationVector: Vector2;
normal: Vector2; normal: Vector2;
point: Vector2; point: Vector2;
@@ -798,6 +812,8 @@ declare class Vector2Ext {
static cross(u: Vector2, v: Vector2): number; static cross(u: Vector2, v: Vector2): number;
static perpendicular(first: Vector2, second: Vector2): Vector2; static perpendicular(first: Vector2, second: Vector2): Vector2;
static normalize(vec: Vector2): Vector2; static normalize(vec: Vector2): Vector2;
static transformA(sourceArray: Vector2[], sourceIndex: number, matrix: Matrix2D, destinationArray: Vector2[], destinationIndex: number, length: number): void;
static transform(sourceArray: Vector2[], matrix: Matrix2D, destinationArray: Vector2[]): void;
} }
declare class WebGLUtils { declare class WebGLUtils {
static getWebGL(): WebGLRenderingContext; static getWebGL(): WebGLRenderingContext;

View File

@@ -1786,6 +1786,56 @@ var SpriteRenderer = (function (_super) {
}; };
return SpriteRenderer; return SpriteRenderer;
}(RenderableComponent)); }(RenderableComponent));
var Mover = (function (_super) {
__extends(Mover, _super);
function Mover() {
return _super !== null && _super.apply(this, arguments) || this;
}
Mover.prototype.onAddedToEntity = function () {
this._triggerHelper = new ColliderTriggerHelper(this.entity);
};
Mover.prototype.calculateMovement = function (motion) {
var collisionResult = new CollisionResult();
if (!this.entity.getComponent(Collider) || !this._triggerHelper) {
return null;
}
var colliders = this.entity.getComponents(Collider);
for (var i = 0; i < colliders.length; i++) {
var collider = colliders[i];
if (collider.isTrigger)
continue;
var bounds = collider.bounds;
bounds.x += motion.x;
bounds.y += motion.y;
var neighbors = Physics.boxcastBroadphaseExcludingSelf(collider, bounds, collider.collidesWithLayers);
for (var j = 0; j < neighbors.length; j++) {
var neighbor = neighbors[j];
if (neighbor.isTrigger)
continue;
var _internalcollisionResult = collider.collidesWith(neighbor, motion);
if (_internalcollisionResult) {
motion = Vector2.subtract(motion, _internalcollisionResult.minimumTranslationVector);
if (_internalcollisionResult.collider) {
collisionResult = _internalcollisionResult;
}
}
}
}
ListPool.free(colliders);
return collisionResult;
};
Mover.prototype.applyMovement = function (motion) {
this.entity.transform.position = Vector2.add(this.entity.transform.position, motion);
if (this._triggerHelper)
this._triggerHelper.update();
};
Mover.prototype.move = function (motion) {
var collisionResult = this.calculateMovement(motion);
this.applyMovement(motion);
return collisionResult;
};
return Mover;
}(Component));
var Collider = (function (_super) { var Collider = (function (_super) {
__extends(Collider, _super); __extends(Collider, _super);
function Collider() { function Collider() {
@@ -1842,6 +1892,36 @@ var Collider = (function (_super) {
Collider.prototype.overlaps = function (other) { Collider.prototype.overlaps = function (other) {
return this.shape.overlaps(other.shape); return this.shape.overlaps(other.shape);
}; };
Collider.prototype.collidesWith = function (collider, motion) {
var oldPosition = this.shape.position;
this.shape.position = Vector2.add(this.shape.position, motion);
var result = this.shape.collidesWithShape(collider.shape);
if (result)
result.collider = collider;
this.shape.position = oldPosition;
return result;
};
Collider.prototype.onAddedToEntity = function () {
if (this._colliderRequiresAutoSizing) {
if (!(this instanceof BoxCollider)) {
console.error("Only box and circle colliders can be created automatically");
}
var renderable = this.entity.getComponent(RenderableComponent);
if (!renderable) {
var renderbaleBounds = renderable.bounds;
var width = renderbaleBounds.width / this.entity.transform.scale.x;
var height = renderbaleBounds.height / this.entity.transform.scale.y;
if (this instanceof BoxCollider) {
var boxCollider = this;
boxCollider.width = width;
boxCollider.height = height;
this.localOffset = Vector2.subtract(renderbaleBounds.center, this.entity.transform.position);
}
}
}
this._isParentEntityAddedToScene = true;
this.registerColliderWithPhysicsSystem();
};
Collider.prototype.onEntityTransformChanged = function (comp) { Collider.prototype.onEntityTransformChanged = function (comp) {
switch (comp) { switch (comp) {
case ComponentTransform.position: case ComponentTransform.position:
@@ -2213,13 +2293,19 @@ var ComponentList = (function () {
components = []; components = [];
for (var i = 0; i < this._components.length; i++) { for (var i = 0; i < this._components.length; i++) {
var component = this._components[i]; var component = this._components[i];
if (egret.is(component, typeName)) if (typeof (typeName) == "string" && egret.is(component, typeName))
components.push(component); components.push(component);
else if (component instanceof typeName) {
components.push(component);
}
} }
for (var i = 0; i < this._componentsToAdd.length; i++) { for (var i = 0; i < this._componentsToAdd.length; i++) {
var component = this._componentsToAdd[i]; var component = this._componentsToAdd[i];
if (egret.is(component, typeName)) if (typeof (typeName) == "string" && egret.is(component, typeName))
components.push(component); components.push(component);
else if (component instanceof typeName) {
components.push(component);
}
} }
return components; return components;
}; };
@@ -2721,6 +2807,13 @@ var Rectangle = (function () {
enumerable: true, enumerable: true,
configurable: true configurable: true
}); });
Object.defineProperty(Rectangle.prototype, "center", {
get: function () {
return new Vector2(this.x + (this.width / 2), this.y + (this.height / 2));
},
enumerable: true,
configurable: true
});
Object.defineProperty(Rectangle.prototype, "location", { Object.defineProperty(Rectangle.prototype, "location", {
get: function () { get: function () {
return new Vector2(this.x, this.y); return new Vector2(this.x, this.y);
@@ -2824,6 +2917,28 @@ var Rectangle = (function () {
this.height = maxY - minY; this.height = maxY - minY;
} }
}; };
Rectangle.rectEncompassingPoints = function (points) {
var minX = Number.POSITIVE_INFINITY;
var minY = Number.POSITIVE_INFINITY;
var maxX = Number.NEGATIVE_INFINITY;
var maxY = Number.NEGATIVE_INFINITY;
for (var i = 0; i < points.length; i++) {
var pt = points[i];
if (pt.x < minX) {
minX = pt.x;
}
if (pt.x > maxX) {
maxX = pt.x;
}
if (pt.y < minY) {
minY = pt.y;
}
if (pt.y > maxY) {
maxY = pt.y;
}
}
return this.fromMinMax(minX, minY, maxX, maxY);
};
return Rectangle; return Rectangle;
}()); }());
var Vector2 = (function () { var Vector2 = (function () {
@@ -2936,7 +3051,7 @@ var ColliderTriggerHelper = (function () {
this._entity = entity; this._entity = entity;
} }
ColliderTriggerHelper.prototype.update = function () { ColliderTriggerHelper.prototype.update = function () {
var colliders = this._entity.getComponents("Collider"); var colliders = this._entity.getComponents(Collider);
for (var i = 0; i < colliders.length; i++) { for (var i = 0; i < colliders.length; i++) {
var collider = colliders[i]; var collider = colliders[i];
var neighbors = Physics.boxcastBroadphase(collider.bounds, collider.collidesWithLayers); var neighbors = Physics.boxcastBroadphase(collider.bounds, collider.collidesWithLayers);
@@ -3138,6 +3253,10 @@ var Physics = (function () {
if (layerMask === void 0) { layerMask = this.allLayers; } if (layerMask === void 0) { layerMask = this.allLayers; }
return this._spatialHash.aabbBroadphase(rect, null, layerMask); return this._spatialHash.aabbBroadphase(rect, null, layerMask);
}; };
Physics.boxcastBroadphaseExcludingSelf = function (collider, rect, layerMask) {
if (layerMask === void 0) { layerMask = this.allLayers; }
return this._spatialHash.aabbBroadphase(rect, collider, layerMask);
};
Physics.addCollider = function (collider) { Physics.addCollider = function (collider) {
Physics._spatialHash.register(collider); Physics._spatialHash.register(collider);
}; };
@@ -3191,14 +3310,27 @@ var Polygon = (function (_super) {
} }
}; };
Polygon.prototype.setPoints = function (points) { Polygon.prototype.setPoints = function (points) {
var _this = this;
this.points = points; this.points = points;
this.recalculateCenterAndEdgeNormals(); this.recalculateCenterAndEdgeNormals();
this._originalPoints = new Array(points.length); this._originalPoints = new Array(this.points.length);
this._originalPoints = points; this.points.forEach(function (point) { return _this._originalPoints.push(point); });
}; };
Polygon.prototype.collidesWithShape = function (other) { Polygon.prototype.collidesWithShape = function (other) {
if (other instanceof Polygon) var result = new CollisionResult();
return ShapeCollisions.polygonToPolygon(this, other); if (other instanceof Polygon) {
result = ShapeCollisions.polygonToPolygon(this, other);
return result;
}
if (other instanceof Circle) {
result = ShapeCollisions.circleToPolygon(other, this);
if (result) {
result.invertResult();
return result;
}
return null;
}
throw new Error("overlaps of Polygon to " + other + " are not supported");
}; };
Polygon.prototype.recalculateCenterAndEdgeNormals = function () { Polygon.prototype.recalculateCenterAndEdgeNormals = function () {
this._polygonCenter = Polygon.findPolygonCenter(this.points); this._polygonCenter = Polygon.findPolygonCenter(this.points);
@@ -3273,6 +3405,34 @@ var Polygon = (function (_super) {
}; };
Polygon.prototype.recalculateBounds = function (collider) { Polygon.prototype.recalculateBounds = function (collider) {
this.center = collider.localOffset; this.center = collider.localOffset;
if (collider.shouldColliderScaleAndRotationWithTransform) {
var hasUnitScale = true;
var tempMat = void 0;
var combinedMatrix = Matrix2D.createTranslation(-this._polygonCenter.x, -this._polygonCenter.y);
if (collider.entity.transform.scale != Vector2.one) {
tempMat = Matrix2D.createScale(collider.entity.transform.scale.x, collider.entity.transform.scale.y);
combinedMatrix = Matrix2D.multiply(combinedMatrix, tempMat);
hasUnitScale = false;
var scaledOffset = Vector2.multiply(collider.localOffset, collider.entity.transform.scale);
this.center = scaledOffset;
}
if (collider.entity.transform.rotation != 0) {
tempMat = Matrix2D.createRotation(collider.entity.transform.rotation);
combinedMatrix = Matrix2D.multiply(combinedMatrix, tempMat);
var offsetAngle = Math.atan2(collider.localOffset.y, collider.localOffset.x) * MathHelper.Rad2Deg;
var offsetLength = hasUnitScale ? collider._localOffsetLength : (Vector2.multiply(collider.localOffset, collider.entity.transform.scale)).length();
this.center = MathHelper.pointOnCirlce(Vector2.zero, offsetLength, collider.entity.transform.rotationDegrees + offsetAngle);
}
tempMat = Matrix2D.createTranslation(this._polygonCenter.x, this._polygonCenter.y);
combinedMatrix = Matrix2D.multiply(combinedMatrix, tempMat);
Vector2Ext.transform(this._originalPoints, combinedMatrix, this.points);
this.isUnrotated = collider.entity.transform.rotation == 0;
if (collider._isRotationDirty)
this._areEdgeNormalsDirty = true;
}
this.position = Vector2.add(collider.entity.transform.position, this.center);
this.bounds = Rectangle.rectEncompassingPoints(this.points);
this.bounds.location = Vector2.add(this.bounds.location, this.position);
}; };
return Polygon; return Polygon;
}(Shape)); }(Shape));
@@ -3809,6 +3969,18 @@ var Vector2Ext = (function () {
} }
return vec; return vec;
}; };
Vector2Ext.transformA = function (sourceArray, sourceIndex, matrix, destinationArray, destinationIndex, length) {
for (var i = 0; i < length; i++) {
var position = sourceArray[sourceIndex + i];
var destination = destinationArray[destinationIndex + 1];
destination.x = (position.x * matrix.m11) + (position.y * matrix.m21) + matrix.m31;
destination.y = (position.x * matrix.m12) + (position.y * matrix.m22) + matrix.m32;
destinationArray[destinationIndex + i] = destination;
}
};
Vector2Ext.transform = function (sourceArray, matrix, destinationArray) {
this.transformA(sourceArray, 0, matrix, destinationArray, 0, sourceArray.length);
};
return Vector2Ext; return Vector2Ext;
}()); }());
var WebGLUtils = (function () { var WebGLUtils = (function () {

File diff suppressed because one or more lines are too long

View File

@@ -57,6 +57,10 @@ abstract class Component {
} }
public debugRender(){
}
/** 内部使用 运行时不应该调用 */ /** 内部使用 运行时不应该调用 */
public registerComponent(){ public registerComponent(){
this.entity.componentBits.set(ComponentTypeManager.getIndexFor(this), false); this.entity.componentBits.set(ComponentTypeManager.getIndexFor(this), false);

View File

@@ -46,4 +46,17 @@ class BoxCollider extends Collider {
this.shape = new Box(1, 1); this.shape = new Box(1, 1);
this._colliderRequiresAutoSizing = true; this._colliderRequiresAutoSizing = true;
} }
public setSize(width: number, height: number){
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);
}
return this;
}
} }

View File

@@ -7,9 +7,9 @@ abstract class Collider extends Component{
public collidesWithLayers = Physics.allLayers; public collidesWithLayers = Physics.allLayers;
public _localOffsetLength: number; public _localOffsetLength: number;
public _isPositionDirty = true;
public _isRotationDirty = true;
protected _isParentEntityAddedToScene; protected _isParentEntityAddedToScene;
protected _isPositionDirty = true;
protected _isRotationDirty = true;
protected _colliderRequiresAutoSizing; protected _colliderRequiresAutoSizing;
protected _localOffset: Vector2; protected _localOffset: Vector2;
protected _isColliderRegisterd; protected _isColliderRegisterd;
@@ -59,6 +59,46 @@ abstract class Collider extends Component{
return this.shape.overlaps(other.shape); return this.shape.overlaps(other.shape);
} }
public collidesWith(collider: Collider, motion: Vector2){
let oldPosition = this.shape.position;
this.shape.position = Vector2.add(this.shape.position, motion);
let result = this.shape.collidesWithShape(collider.shape);
if (result)
result.collider = collider;
this.shape.position = oldPosition;
return result;
}
public onAddedToEntity(){
if (this._colliderRequiresAutoSizing){
if (!(this instanceof BoxCollider)){
console.error("Only box and circle colliders can be created automatically");
}
let renderable = this.entity.getComponent<RenderableComponent>(RenderableComponent);
if (!renderable){
let renderbaleBounds = renderable.bounds;
let width = renderbaleBounds.width / this.entity.transform.scale.x;
let height = renderbaleBounds.height / this.entity.transform.scale.y;
if (this instanceof BoxCollider){
let boxCollider = this as BoxCollider;
boxCollider.width = width;
boxCollider.height = height;
this.localOffset = Vector2.subtract(renderbaleBounds.center, this.entity.transform.position);
}
}
}
this._isParentEntityAddedToScene = true;
this.registerColliderWithPhysicsSystem();
}
public onEntityTransformChanged(comp: ComponentTransform){ public onEntityTransformChanged(comp: ComponentTransform){
switch (comp){ switch (comp){
case ComponentTransform.position: case ComponentTransform.position:

View File

@@ -0,0 +1,62 @@
class Mover extends Component {
private _triggerHelper: ColliderTriggerHelper;
public onAddedToEntity(){
this._triggerHelper = new ColliderTriggerHelper(this.entity);
}
public calculateMovement(motion: Vector2){
let collisionResult = new CollisionResult();
if (!this.entity.getComponent(Collider) || !this._triggerHelper){
return null;
}
let colliders: Collider[] = this.entity.getComponents(Collider);
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);
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;
}
}
}
}
ListPool.free(colliders);
return collisionResult;
}
public applyMovement(motion: Vector2){
this.entity.transform.position = Vector2.add(this.entity.transform.position, motion);
if (this._triggerHelper)
this._triggerHelper.update();
}
public move(motion: Vector2){
let collisionResult = this.calculateMovement(motion);
this.applyMovement(motion);
return collisionResult;
}
}

View File

@@ -212,7 +212,7 @@ class Entity {
return this.components.getComponent(type, false) as T; return this.components.getComponent(type, false) as T;
} }
public getComponents(typeName: string, componentList?){ public getComponents(typeName: string | any, componentList?){
return this.components.getComponents(typeName, componentList); return this.components.getComponents(typeName, componentList);
} }

View File

@@ -120,20 +120,26 @@ class ComponentList {
return null; return null;
} }
public getComponents(typeName: string, components?){ public getComponents(typeName: string | any, components?){
if (!components) if (!components)
components = []; components = [];
for (let i = 0; i < this._components.length; i ++){ for (let i = 0; i < this._components.length; i ++){
let component = this._components[i]; let component = this._components[i];
if (egret.is(component, typeName)) if (typeof(typeName) == "string" && egret.is(component, typeName))
components.push(component); components.push(component);
else if (component instanceof typeName) {
components.push(component);
}
} }
for (let i = 0; i < this._componentsToAdd.length; i ++){ for (let i = 0; i < this._componentsToAdd.length; i ++){
let component = this._componentsToAdd[i]; let component = this._componentsToAdd[i];
if (egret.is(component, typeName)) if (typeof(typeName) == "string" && egret.is(component, typeName))
components.push(component); components.push(component);
else if (component instanceof typeName){
components.push(component);
}
} }
return components; return components;

View File

@@ -23,6 +23,10 @@ class Rectangle {
return this.y + this.height; return this.y + this.height;
} }
public get center(){
return new Vector2(this.x + (this.width / 2), this.y + (this.height / 2));
}
public get location() { public get location() {
return new Vector2(this.x, this.y); return new Vector2(this.x, this.y);
} }
@@ -140,4 +144,35 @@ class Rectangle {
this.height = maxY - minY; this.height = maxY - minY;
} }
} }
/**
* 给定多边形的点,计算边界
* @param points
*/
public static rectEncompassingPoints(points: Vector2[]){
let minX = Number.POSITIVE_INFINITY;
let minY = Number.POSITIVE_INFINITY;
let maxX = Number.NEGATIVE_INFINITY;
let maxY = Number.NEGATIVE_INFINITY;
for (let i = 0; i < points.length; i ++){
let pt = points[i];
if (pt.x < minX){
minX = pt.x;
}
if (pt.x > maxX){
maxX = pt.x;
}
if (pt.y < minY){
minY = pt.y;
}
if (pt.y > maxY){
maxY = pt.y;
}
}
return this.fromMinMax(minX, minY, maxX, maxY);
}
} }

View File

@@ -14,7 +14,7 @@ class ColliderTriggerHelper {
* 实体被移动后应该调用更新。它会处理碰撞器重叠的任何itriggerlistener。 * 实体被移动后应该调用更新。它会处理碰撞器重叠的任何itriggerlistener。
*/ */
public update() { public update() {
let colliders = this._entity.getComponents("Collider"); let colliders = this._entity.getComponents(Collider);
for (let i = 0; i < colliders.length; i++) { for (let i = 0; i < colliders.length; i++) {
let collider = colliders[i]; let collider = colliders[i];

View File

@@ -11,6 +11,10 @@ class Physics {
return this._spatialHash.aabbBroadphase(rect, null, layerMask); return this._spatialHash.aabbBroadphase(rect, null, layerMask);
} }
public static boxcastBroadphaseExcludingSelf(collider: Collider, rect: Rectangle, layerMask = this.allLayers){
return this._spatialHash.aabbBroadphase(rect, collider, layerMask);
}
public static addCollider(collider: Collider){ public static addCollider(collider: Collider){
Physics._spatialHash.register(collider); Physics._spatialHash.register(collider);
} }

View File

@@ -1,4 +1,5 @@
class CollisionResult { class CollisionResult {
public collider: Collider;
public minimumTranslationVector: Vector2; public minimumTranslationVector: Vector2;
public normal: Vector2; public normal: Vector2;
public point: Vector2; public point: Vector2;

View File

@@ -42,13 +42,29 @@ class Polygon extends Shape {
this.points = points; this.points = points;
this.recalculateCenterAndEdgeNormals(); this.recalculateCenterAndEdgeNormals();
this._originalPoints = new Array(points.length); this._originalPoints = new Array(this.points.length);
this._originalPoints = points; this.points.forEach(point => this._originalPoints.push(point));
} }
public collidesWithShape(other: Shape){ public collidesWithShape(other: Shape){
if (other instanceof Polygon) let result = new CollisionResult();
return ShapeCollisions.polygonToPolygon(this, other); if (other instanceof Polygon){
result = ShapeCollisions.polygonToPolygon(this, other);
return result;
}
if (other instanceof Circle){
result = ShapeCollisions.circleToPolygon(other, this);
if (result){
result.invertResult();
return result;
}
return null;
}
throw new Error(`overlaps of Polygon to ${other} are not supported`);
} }
public recalculateCenterAndEdgeNormals() { public recalculateCenterAndEdgeNormals() {
@@ -133,6 +149,11 @@ class Polygon extends Shape {
return isInside; return isInside;
} }
/**
* 建立一个对称的多边形(六边形八角形n角形)并返回点
* @param vertCount
* @param radius
*/
public static buildSymmertricalPolygon(vertCount: number, radius: number) { public static buildSymmertricalPolygon(vertCount: number, radius: number) {
let verts = new Array(vertCount); let verts = new Array(vertCount);
@@ -146,5 +167,42 @@ class Polygon extends Shape {
public recalculateBounds(collider: Collider) { public recalculateBounds(collider: Collider) {
this.center = collider.localOffset; this.center = collider.localOffset;
if (collider.shouldColliderScaleAndRotationWithTransform){
let hasUnitScale = true;
let tempMat: Matrix2D;
let combinedMatrix = Matrix2D.createTranslation(-this._polygonCenter.x, -this._polygonCenter.y);
if (collider.entity.transform.scale != Vector2.one){
tempMat = Matrix2D.createScale(collider.entity.transform.scale.x, collider.entity.transform.scale.y);
combinedMatrix = Matrix2D.multiply(combinedMatrix, tempMat);
hasUnitScale = false;
let scaledOffset = Vector2.multiply(collider.localOffset, collider.entity.transform.scale);
this.center = scaledOffset;
}
if (collider.entity.transform.rotation != 0){
tempMat = Matrix2D.createRotation(collider.entity.transform.rotation);
combinedMatrix = Matrix2D.multiply(combinedMatrix, tempMat);
let offsetAngle = Math.atan2(collider.localOffset.y, collider.localOffset.x) * MathHelper.Rad2Deg;
let offsetLength = hasUnitScale ? collider._localOffsetLength : (Vector2.multiply(collider.localOffset, collider.entity.transform.scale)).length();
this.center = MathHelper.pointOnCirlce(Vector2.zero, offsetLength, collider.entity.transform.rotationDegrees + offsetAngle);
}
tempMat = Matrix2D.createTranslation(this._polygonCenter.x, this._polygonCenter.y);
combinedMatrix = Matrix2D.multiply(combinedMatrix, tempMat);
Vector2Ext.transform(this._originalPoints, combinedMatrix, this.points);
this.isUnrotated = collider.entity.transform.rotation == 0;
if (collider._isRotationDirty)
this._areEdgeNormalsDirty = true;
}
this.position = Vector2.add(collider.entity.transform.position, this.center);
this.bounds = Rectangle.rectEncompassingPoints(this.points);
this.bounds.location = Vector2.add(this.bounds.location, this.position);
} }
} }

View File

@@ -6,4 +6,5 @@ abstract class Shape {
public abstract recalculateBounds(collider: Collider); public abstract recalculateBounds(collider: Collider);
public abstract pointCollidesWithShape(point: Vector2): CollisionResult; public abstract pointCollidesWithShape(point: Vector2): CollisionResult;
public abstract overlaps(other: Shape); public abstract overlaps(other: Shape);
public abstract collidesWithShape(other: Shape): CollisionResult;
} }

View File

@@ -5,7 +5,7 @@ class Vector2Ext {
* @param center * @param center
* @param c * @param c
*/ */
public static isTriangleCCW(a: Vector2, center: Vector2, c: Vector2){ public static isTriangleCCW(a: Vector2, center: Vector2, c: Vector2) {
return this.cross(Vector2.subtract(center, a), Vector2.subtract(c, center)) < 0; return this.cross(Vector2.subtract(center, a), Vector2.subtract(c, center)) < 0;
} }
@@ -14,7 +14,7 @@ class Vector2Ext {
* @param u * @param u
* @param v * @param v
*/ */
public static cross(u: Vector2, v: Vector2){ public static cross(u: Vector2, v: Vector2) {
return u.y * v.x - u.x * v.y; return u.y * v.x - u.x * v.y;
} }
@@ -23,7 +23,7 @@ class Vector2Ext {
* @param first * @param first
* @param second * @param second
*/ */
public static perpendicular(first: Vector2, second: Vector2){ public static perpendicular(first: Vector2, second: Vector2) {
return new Vector2(-1 * (second.y - first.y), second.x - first.x); return new Vector2(-1 * (second.y - first.y), second.x - first.x);
} }
@@ -32,9 +32,9 @@ class Vector2Ext {
* 标准化把向量弄乱了 * 标准化把向量弄乱了
* @param vec * @param vec
*/ */
public static normalize(vec: Vector2){ public static normalize(vec: Vector2) {
let magnitude = Math.sqrt((vec.x * vec.x) + (vec.y * vec.y)); let magnitude = Math.sqrt((vec.x * vec.x) + (vec.y * vec.y));
if (magnitude > MathHelper.Epsilon){ if (magnitude > MathHelper.Epsilon) {
vec = Vector2.divide(vec, new Vector2(magnitude)); vec = Vector2.divide(vec, new Vector2(magnitude));
} else { } else {
vec.x = vec.y = 0; vec.x = vec.y = 0;
@@ -42,4 +42,19 @@ class Vector2Ext {
return vec; return vec;
} }
public static transformA(sourceArray: Vector2[], sourceIndex: number, matrix: Matrix2D,
destinationArray: Vector2[], destinationIndex: number, length: number) {
for (let i = 0; i < length; i ++){
let position = sourceArray[sourceIndex + i];
let destination = destinationArray[destinationIndex + 1];
destination.x = (position.x * matrix.m11) + (position.y * matrix.m21) + matrix.m31;
destination.y = (position.x * matrix.m12) + (position.y * matrix.m22) + matrix.m32;
destinationArray[destinationIndex + i] = destination;
}
}
public static transform(sourceArray: Vector2[], matrix: Matrix2D, destinationArray: Vector2[]) {
this.transformA(sourceArray, 0, matrix, destinationArray, 0, sourceArray.length);
}
} }