移动类至es模块

This commit is contained in:
YHH
2020-07-23 09:10:27 +08:00
parent 15c0844e29
commit 814234ca61
20 changed files with 1101 additions and 998 deletions

View File

@@ -1,4 +1,5 @@
class ComponentPool<T extends PooledComponent>{
module es {
export class ComponentPool<T extends PooledComponent>{
private _cache: T[];
private _type: any;
@@ -20,3 +21,4 @@ class ComponentPool<T extends PooledComponent>{
this._cache.push(component);
}
}
}

View File

@@ -1,5 +1,6 @@
///<reference path="./RenderableComponent.ts" />
class Mesh extends RenderableComponent {
module es {
export class Mesh extends RenderableComponent {
private _mesh: egret.Mesh;
constructor(){
@@ -14,19 +15,10 @@ class Mesh extends RenderableComponent {
return this;
}
public onAddedToEntity(){
this.addChild(this._mesh);
}
public onRemovedFromEntity(){
this.removeChild(this._mesh);
}
public render(camera: Camera){
this.x = this.entity.position.x - camera.position.x + camera.origin.x;
this.y = this.entity.position.y - camera.position.y + camera.origin.y;
}
public reset() {
}
render(camera: es.Camera) {
}
}
}

View File

@@ -1,5 +1,6 @@
///<reference path="./Collider.ts" />
class BoxCollider extends Collider {
module es {
export class BoxCollider extends Collider {
public get width(){
return (this.shape as Box).width;
}
@@ -8,6 +9,43 @@ class BoxCollider extends Collider {
this.setWidth(value);
}
public get height(){
return (this.shape as Box).height;
}
public set height(value: number){
this.setHeight(value);
}
/**
* 零参数构造函数要求RenderableComponent在实体上这样碰撞器可以在实体被添加到场景时调整自身的大小。
*/
constructor(){
super();
// 我们在这里插入一个1x1框作为占位符直到碰撞器在下一阵被添加到实体并可以获得更精确的自动调整大小数据
this.shape = new Box(1, 1);
this._colliderRequiresAutoSizing = true;
}
/**
* 设置BoxCollider的大小
* @param width
* @param height
*/
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);
if (this.entity && this._isParentEntityAddedToScene)
Physics.updateCollider(this);
}
return this;
}
/**
* 设置BoxCollider的宽度
* @param width
@@ -25,14 +63,6 @@ class BoxCollider extends Collider {
return this;
}
public get height(){
return (this.shape as Box).height;
}
public set height(value: number){
this.setHeight(value);
}
/**
* 设置BoxCollider的高度
* @param height
@@ -48,27 +78,8 @@ class BoxCollider extends Collider {
}
}
/**
* 零参数构造函数要求RenderableComponent在实体上这样碰撞器可以在实体被添加到场景时调整自身的大小。
*/
constructor(){
super();
// 我们在这里插入一个1x1框作为占位符直到碰撞器在下一阵被添加到实体并可以获得更精确的自动调整大小数据
this.shape = new Box(1, 1);
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);
if (this.entity && this._isParentEntityAddedToScene)
Physics.updateCollider(this);
}
return this;
public toString(){
return `[BoxCollider: bounds: ${this.bounds}]`;
}
}
}

View File

@@ -1,7 +1,9 @@
class CircleCollider extends Collider {
module es {
export class CircleCollider extends Collider {
public get radius(): number {
return (this.shape as Circle).radius;
}
public set radius(value: number) {
this.setRadius(value);
}
@@ -38,4 +40,9 @@ class CircleCollider extends Collider {
return this;
}
public toString() {
return `[CircleCollider: bounds: ${this.bounds}, radius: ${(this.shape as Circle).radius}]`
}
}
}

View File

@@ -1,7 +1,8 @@
module es {
/**
* 多边形应该以顺时针方式定义
*/
class PolygonCollider extends Collider {
export class PolygonCollider extends Collider {
/**
* 如果这些点没有居中它们将以localOffset的差异为居中。
* @param points
@@ -16,7 +17,10 @@ class PolygonCollider extends Collider {
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,4 +1,23 @@
interface ITriggerListener {
module es{
/**
* 当添加到组件时,每当实体上的冲突器与另一个组件重叠/退出时,将调用这些方法。
* ITriggerListener方法将在实现接口的触发器实体上的任何组件上调用。
* 注意这个接口只与Mover类一起工作
*/
export interface ITriggerListener {
/**
* 当碰撞器与触发碰撞器相交时调用。这是在触发碰撞器和触发碰撞器上调用的。
* 移动必须由Mover/ProjectileMover方法处理以使其自动工作。
* @param other
* @param local
*/
onTriggerEnter(other: Collider, local: Collider);
/**
* 当另一个碰撞器离开触发碰撞器时调用
* @param other
* @param local
*/
onTriggerExit(other: Collider, local: Collider);
}
}

View File

@@ -1,3 +1,4 @@
module es {
/**
* 辅助类说明了一种处理移动的方法,它考虑了包括触发器在内的所有冲突。
* ITriggerListener接口用于管理对移动过程中违反的任何触发器的回调。
@@ -5,7 +6,7 @@
*
* 请注意多个移动者相互交互将多次调用ITriggerListener。
*/
class Mover extends Component {
export class Mover extends Component {
private _triggerHelper: ColliderTriggerHelper;
public onAddedToEntity(){
@@ -91,3 +92,4 @@ class Mover extends Component {
return collisionResult;
}
}
}

View File

@@ -1,8 +1,9 @@
module es {
/**
* 只向itriggerlistener报告冲突的移动器
* 该对象将始终移动完整的距离
*/
class ProjectileMover extends Component {
export class ProjectileMover extends Component {
private _tempTriggerList: ITriggerListener[] = [];
private _collider: Collider;
@@ -54,3 +55,4 @@ class ProjectileMover extends Component {
this._tempTriggerList.length = 0;
}
}
}

View File

@@ -1,5 +1,6 @@
///<reference path="./TiledSpriteRenderer.ts"/>
class ScrollingSpriteRenderer extends TiledSpriteRenderer {
module es {
export class ScrollingSpriteRenderer extends TiledSpriteRenderer {
public scrollSpeedX = 15;
public scroolSpeedY = 0;
private _scrollX = 0;
@@ -31,7 +32,6 @@ class ScrollingSpriteRenderer extends TiledSpriteRenderer {
cacheBitmap.cacheAsBitmap = true;
renderTexture.drawToTexture(cacheBitmap, new egret.Rectangle(0, 0, this.sourceRect.width, this.sourceRect.height));
this.bitmap.texture = renderTexture;
}
}
}

View File

@@ -1,4 +1,5 @@
class Sprite {
module es {
export class Sprite {
public texture2D: egret.Texture;
public readonly sourceRect: Rectangle;
public readonly center: Vector2;
@@ -22,3 +23,4 @@ class Sprite {
this.uvs.height = sourceRect.height * inverseTexH;
}
}
}

View File

@@ -1,4 +1,5 @@
class SpriteAnimation {
module es {
export class SpriteAnimation {
public readonly sprites: Sprite[];
public readonly frameRate: number;
@@ -7,3 +8,4 @@ class SpriteAnimation {
this.frameRate = frameRate;
}
}
}

View File

@@ -1,18 +1,54 @@
///<reference path="./SpriteRenderer.ts" />
class SpriteAnimator extends SpriteRenderer {
/** 在动画完成时触发,包括动画名称; */
public onAnimationCompletedEvent: Function;
/** 动画播放速度 */
module es {
export enum LoopMode {
/** 在一个循环序列[A][B][C][A][B][C][A][B][C]... */
loop,
/** [A][B][C]然后暂停设置时间为0 [A] */
once,
/** [A][B][C]。当它到达终点时,它会继续播放最后一帧,并且不会停止播放 */
clampForever,
/** 以一个乒乓循环的方式永远播放这个序列 [A][B][C][B][A][B][C][B]... */
pingPong,
/** 将顺序向前播放一次,然后返回到开始[A][B][C][B][A]然后暂停并设置时间为0 */
pingPongOnce,
}
export enum State {
none,
running,
paused,
completed,
}
export class SpriteAnimator extends SpriteRenderer {
/**
* 在动画完成时触发,包括动画名称
*/
public onAnimationCompletedEvent: (string) => {};
/**
* 动画播放速度
*/
public speed = 1;
/** 动画的当前状态 */
/**
* 动画的当前状态
*/
public animationState = State.none;
/** 当前动画 */
/**
* 当前动画
*/
public currentAnimation: SpriteAnimation;
/** 当前动画的名称 */
/**
* 当前动画的名称
*/
public currentAnimationName: string;
/** 当前动画的精灵数组中当前帧的索引 */
/**
* 当前动画的精灵数组中当前帧的索引
*/
public currentFrame: number;
/** 检查当前动画是否正在运行 */
/**
* 检查当前动画是否正在运行
*/
public get isRunning(): boolean {
return this.animationState == State.running;
}
@@ -21,14 +57,47 @@ class SpriteAnimator extends SpriteRenderer {
public get animations() {
return this._animations;
}
private _animations: Map<string, SpriteAnimation> = new Map<string, SpriteAnimation>();
private _elapsedTime: number = 0;
private _loopMode: LoopMode;
public _elapsedTime: number = 0;
public _loopMode: LoopMode;
constructor(sprite?: Sprite) {
super();
super(sprite);
}
if (sprite) this.setSprite(sprite);
public update() {
if (this.animationState != State.running || !this.currentAnimation) return;
let animation = this.currentAnimation;
let secondsPerFrame = 1 / (animation.frameRate * this.speed);
let iterationDuration = secondsPerFrame * animation.sprites.length;
this._elapsedTime += Time.deltaTime;
let time = Math.abs(this._elapsedTime);
// Once和PingPongOnce完成后重置为Time = 0
if (this._loopMode == LoopMode.once && time > iterationDuration ||
this._loopMode == LoopMode.pingPongOnce && time > iterationDuration * 2) {
this.animationState = State.completed;
this._elapsedTime = 0;
this.currentFrame = 0;
this.sprite = animation.sprites[this.currentFrame];
return;
}
// 弄清楚我们在哪个坐标系上
let i = Math.floor(time / secondsPerFrame);
let n = animation.sprites.length;
if (n > 2 && (this._loopMode == LoopMode.pingPong || this._loopMode == LoopMode.pingPongOnce)) {
// pingpong
let maxIndex = n - 1;
this.currentFrame = maxIndex - Math.abs(maxIndex - i % (maxIndex * 2));
} else {
this.currentFrame = i % n;
}
this.sprite = animation.sprites[this.currentFrame];
}
/**
@@ -37,6 +106,7 @@ class SpriteAnimator extends SpriteRenderer {
* @param animation
*/
public addAnimation(name: string, animation: SpriteAnimation): SpriteAnimator {
// 如果我们没有精灵,使用我们找到的第一帧
if (!this.sprite && animation.sprites.length > 0)
this.setSprite(animation.sprites[0]);
this._animations[name] = animation;
@@ -90,57 +160,5 @@ class SpriteAnimator extends SpriteRenderer {
this.currentFrame = 0;
this.animationState = State.none;
}
public update(){
if (this.animationState != State.running || !this.currentAnimation) return;
let animation = this.currentAnimation;
let secondsPerFrame = 1 / (animation.frameRate * this.speed);
let iterationDuration = secondsPerFrame * animation.sprites.length;
this._elapsedTime += Time.deltaTime;
let time = Math.abs(this._elapsedTime);
if (this._loopMode == LoopMode.once && time > iterationDuration ||
this._loopMode == LoopMode.pingPongOnce && time > iterationDuration * 2){
this.animationState = State.completed;
this._elapsedTime = 0;
this.currentFrame = 0;
this.sprite = animation.sprites[this.currentFrame];
return;
}
// 弄清楚我们在哪个坐标系上
let i = Math.floor(time / secondsPerFrame);
let n = animation.sprites.length;
if (n > 2 && (this._loopMode == LoopMode.pingPong || this._loopMode == LoopMode.pingPongOnce)){
// pingpong
let maxIndex = n - 1;
this.currentFrame = maxIndex - Math.abs(maxIndex - i % (maxIndex * 2));
}else{
this.currentFrame = i % n;
}
this.sprite = animation.sprites[this.currentFrame];
}
}
enum LoopMode {
/** 在一个循环序列[A][B][C][A][B][C][A][B][C]... */
loop,
/** [A][B][C]然后暂停设置时间为0 [A] */
once,
/** [A][B][C]。当它到达终点时,它会继续播放最后一帧,并且不会停止播放 */
clampForever,
/** 以一个乒乓循环的方式永远播放这个序列 [A][B][C][B][A][B][C][B]... */
pingPong,
/** 将顺序向前播放一次,然后返回到开始[A][B][C][B][A]然后暂停并设置时间为0 */
pingPongOnce,
}
enum State {
none,
running,
paused,
completed,
}

View File

@@ -67,7 +67,7 @@ module es {
protected _origin: Vector2;
protected _sprite: Sprite;
constructor(sprite: Sprite | egret.Texture) {
constructor(sprite: Sprite | egret.Texture = null) {
super();
if (sprite instanceof Sprite)
this.setSprite(sprite);

View File

@@ -1,8 +1,9 @@
///<reference path="./SpriteRenderer.ts" />
module es {
/**
* 滚动由两张图片组合而成
*/
class TiledSpriteRenderer extends SpriteRenderer {
export class TiledSpriteRenderer extends SpriteRenderer {
protected sourceRect: Rectangle;
protected leftTexture: egret.Bitmap;
protected rightTexture: egret.Bitmap;
@@ -21,7 +22,7 @@ class TiledSpriteRenderer extends SpriteRenderer {
}
constructor(sprite: Sprite) {
super();
super(sprite);
this.leftTexture = new egret.Bitmap();
this.rightTexture = new egret.Bitmap();
@@ -32,7 +33,7 @@ class TiledSpriteRenderer extends SpriteRenderer {
this.sourceRect = sprite.sourceRect;
}
public render(camera: Camera) {
public render(camera: es.Camera) {
if (!this.sprite)
return;
@@ -51,7 +52,6 @@ class TiledSpriteRenderer extends SpriteRenderer {
cacheBitmap.cacheAsBitmap = true;
renderTexture.drawToTexture(cacheBitmap, new egret.Rectangle(0, 0, this.sourceRect.width, this.sourceRect.height));
this.bitmap.texture = renderTexture;
}
}
}

View File

@@ -1,9 +1,10 @@
module es {
/**
* 这个类可以从两方面来考虑。你可以把它看成一个位向量或者一组非负整数。这个名字有点误导人。
*
* 它是由一个位向量实现的,但同样可以把它看成是一个非负整数的集合;集合中的每个整数由对应索引处的集合位表示。该结构的大小由集合中的最大整数决定。
*/
class BitSet{
export class BitSet{
private static LONG_MASK: number = 0x3f;
private _bits: number[];
@@ -131,3 +132,4 @@ class BitSet{
}
}
}
}

View File

@@ -1,4 +1,5 @@
class ComponentTypeManager{
module es {
export class ComponentTypeManager{
private static _componentTypesMask: Map<any, number> = new Map<any, number>();
public static add(type){
@@ -16,3 +17,4 @@ class ComponentTypeManager{
return v;
}
}
}

View File

@@ -1,4 +1,5 @@
class EntityProcessorList {
module es {
export class EntityProcessorList {
private _processors: EntitySystem[] = [];
public add(processor: EntitySystem){
@@ -67,3 +68,4 @@ class EntityProcessorList {
return null;
}
}
}

View File

@@ -55,18 +55,20 @@ module es {
public overlaps(other: Shape){
// 特殊情况这一个高性能方式实现其他情况则使用polygon方法检测
if (this.isUnrotated){
if (other instanceof Box)
return this.bounds.intersects(other.bounds);
if (other instanceof Circle)
return Collisions.isRectToCircle(this.bounds, other.position, other.radius);
}
return super.overlaps(other);
}
public collidesWithShape(other: Shape){
// 特殊情况这一个高性能方式实现其他情况则使用polygon方法检测
if (other instanceof Box){
if (other instanceof Box && (other as Box).isUnrotated){
return ShapeCollisions.boxToBox(this, other);
}
@@ -75,14 +77,11 @@ module es {
return super.collidesWithShape(other);
}
/**
*
* @param point
*/
public containsPoint(point: Vector2){
if (this.isUnrotated)
return this.bounds.contains(point.x, point.y);
return super.containsPoint(point);
}
}
}

View File

@@ -1,15 +1,8 @@
///<reference path="./Shape.ts" />
class Circle extends Shape {
module es {
export class Circle extends Shape {
public radius: number;
public _originalRadius: number;
public center = new Vector2();
public get position(){
return new Vector2(this.parent.x, this.parent.y);
}
public get bounds(){
return new Rectangle().setEgretRect(this.getBounds());
}
constructor(radius: number) {
super();
@@ -17,12 +10,44 @@ class Circle extends Shape {
this._originalRadius = radius;
}
public pointCollidesWithShape(point: Vector2): CollisionResult {
return ShapeCollisions.pointToCircle(point, this);
public recalculateBounds(collider: es.Collider) {
// 如果我们没有旋转或不关心TRS我们使用localOffset作为中心
this.center = collider.localOffset;
if (collider.shouldColliderScaleAndRotateWithTransform) {
// 我们只将直线缩放为一个圆,所以我们将使用最大值
let scale = collider.entity.transform.scale;
let hasUnitScale = scale.x == 1 && scale.y == 1;
let maxScale = Math.max(scale.x, scale.y);
this.radius = this._originalRadius * maxScale;
if (collider.entity.transform.rotation != 0) {
// 为了处理偏移原点的旋转,我们只需要将圆心围绕(0,0)在一个圆上移动我们的偏移量就是0角
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.rotation + offsetAngle);
}
}
this.position = Vector2.add(collider.transform.position, this.center);
this.bounds = new Rectangle(this.position.x - this.radius, this.position.y - this.radius, this.radius * 2, this.radius * 2);
}
public overlaps(other: Shape) {
if (other instanceof Box && (other as Box).isUnrotated)
return Collisions.isRectToCircle(other.bounds, this.position, this.radius);
if (other instanceof Circle)
return Collisions.isCircleToCircle(this.position, this.radius, other.position, (other as Circle).radius);
if (other instanceof Polygon)
return ShapeCollisions.circleToPolygon(this, other);
throw new Error(`overlaps of circle to ${other} are not supported`);
}
public collidesWithShape(other: Shape): CollisionResult {
if (other instanceof Box) {
if (other instanceof Box && (other as Box).isUnrotated) {
return ShapeCollisions.circleToBox(this, other);
}
@@ -37,16 +62,8 @@ class Circle extends Shape {
throw new Error(`Collisions of Circle to ${other} are not supported`);
}
public overlaps(other: Shape){
if (other instanceof Box)
return Collisions.isRectToCircle(other.bounds, this.position, this.radius);
if (other instanceof Circle)
return Collisions.isCircleToCircle(this.position, this.radius, other.position, (other as Circle).radius);
if (other instanceof Polygon)
return ShapeCollisions.circleToPolygon(this, other);
throw new Error(`overlaps of circle to ${other} are not supported`);
public pointCollidesWithShape(point: Vector2): CollisionResult {
return ShapeCollisions.pointToCircle(point, this);
}
}
}

View File

@@ -1,17 +1,28 @@
class SpatialHash {
module es {
export class SpatialHash {
public gridBounds: Rectangle = new Rectangle();
private _raycastParser: RaycastResultParser;
/** 散列中每个单元格的大小 */
private _cellSize: number;
/** 1除以单元格大小。缓存结果因为它被大量使用。 */
private _inverseCellSize: number;
/** 缓存的循环用于重叠检查 */
private _overlapTestCircle: Circle = new Circle(0);
/** 用于返回冲突信息的共享HashSet */
private _tempHashSet: Collider[] = [];
/** 保存所有数据的字典 */
private _cellDict: NumberDictionary = new NumberDictionary();
public _raycastParser: RaycastResultParser;
/**
* 散列中每个单元格的大小
*/
public _cellSize: number;
/**
* 1除以单元格大小。缓存结果因为它被大量使用。
*/
public _inverseCellSize: number;
/**
* 缓存的循环用于重叠检查
*/
public _overlapTestCircle: Circle = new Circle(0);
/**
* 保存所有数据的字典
*/
public _cellDict: NumberDictionary = new NumberDictionary();
/**
* 用于返回冲突信息的共享HashSet
*/
public _tempHashSet: Collider[] = [];
constructor(cellSize: number = 100) {
this._cellSize = cellSize;
@@ -20,24 +31,30 @@ class SpatialHash {
}
/**
* 从SpatialHash中删除对象
* @param collider
* 获取单元格的x,y值作为世界空间的x,y值
* @param x
* @param y
*/
public remove(collider: Collider) {
let bounds = collider.registeredPhysicsBounds;
let p1 = this.cellCoords(bounds.x, bounds.y);
let p2 = this.cellCoords(bounds.right, bounds.bottom);
private cellCoords(x: number, y: number): Vector2 {
return new Vector2(Math.floor(x * this._inverseCellSize), Math.floor(y * this._inverseCellSize));
}
for (let x = p1.x; x <= p2.x; x++) {
for (let y = p1.y; y <= p2.y; y++) {
// 单元格应该始终存在,因为这个碰撞器应该在所有查询的单元格
let cell = this.cellAtPosition(x, y);
if (!cell)
console.error(`removing Collider [${collider}] from a cell that it is not present in`);
else
cell.remove(collider);
/**
* 获取世界空间x,y值的单元格。
* 如果单元格为空且createCellIfEmpty为true则会创建一个新的单元格
* @param x
* @param y
* @param createCellIfEmpty
*/
private cellAtPosition(x: number, y: number, createCellIfEmpty: boolean = false) {
let cell: Collider[] = this._cellDict.tryGetValue(x, y);
if (!cell) {
if (createCellIfEmpty) {
cell = [];
this._cellDict.add(x, y, cell);
}
}
return cell;
}
/**
@@ -69,52 +86,56 @@ class SpatialHash {
}
}
/**
* 从SpatialHash中删除对象
* @param collider
*/
public remove(collider: Collider) {
let bounds = collider.registeredPhysicsBounds;
let p1 = this.cellCoords(bounds.x, bounds.y);
let p2 = this.cellCoords(bounds.right, bounds.bottom);
for (let x = p1.x; x <= p2.x; x++) {
for (let y = p1.y; y <= p2.y; y++) {
// 单元格应该始终存在,因为这个碰撞器应该在所有查询的单元格中
let cell = this.cellAtPosition(x, y);
if (!cell)
console.error(`removing Collider [${collider}] from a cell that it is not present in`);
else
cell.remove(collider);
}
}
}
/**
* 使用蛮力方法从SpatialHash中删除对象
* @param obj
*/
public removeWithBruteForce(obj: Collider){
this._cellDict.remove(obj);
}
public clear(){
this._cellDict.clear();
}
/**
* 获取位于指定圆内的所有碰撞器
* @param circleCenter
* @param radius
* @param results
* @param layerMask
* debug绘制空间散列的内容
* @param secondsToDisplay
* @param textScale
*/
public overlapCircle(circleCenter: Vector2, radius: number, results: Collider[], layerMask) {
let bounds = new Rectangle(circleCenter.x - radius, circleCenter.y - radius, radius * 2, radius * 2);
this._overlapTestCircle.radius = radius;
// this._overlapTestCircle.position = circleCenter;
let resultCounter = 0;
let aabbBroadphaseResult = this.aabbBroadphase(bounds, null, layerMask);
bounds = aabbBroadphaseResult.bounds;
let potentials = aabbBroadphaseResult.tempHashSet;
for (let i = 0; i < potentials.length; i++) {
let collider = potentials[i];
if (collider instanceof BoxCollider) {
results[resultCounter] = collider;
resultCounter++;
} else if (collider instanceof CircleCollider) {
if (collider.shape.overlaps(this._overlapTestCircle)){
results[resultCounter] = collider;
resultCounter ++;
public debugDraw(secondsToDisplay: number, textScale: number = 1){
for (let x = this.gridBounds.x; x <= this.gridBounds.right; x ++){
for (let y = this.gridBounds.y; y <= this.gridBounds.bottom; y ++){
let cell = this.cellAtPosition(x, y);
if (cell && cell.length > 0)
this.debugDrawCellDetails(x, y, cell.length, secondsToDisplay, textScale);
}
} else if(collider instanceof PolygonCollider) {
if (collider.shape.overlaps(this._overlapTestCircle)){
results[resultCounter] = collider;
resultCounter ++;
}
} else {
throw new Error("overlapCircle against this collider type is not implemented!");
}
// 如果我们所有的结果数据有了则返回
if (resultCounter == results.length)
return resultCounter;
}
private debugDrawCellDetails(x: number, y: number, cellCount: number, secondsToDisplay = 0.5, textScale = 1){
return resultCounter;
}
/**
@@ -155,62 +176,56 @@ class SpatialHash {
}
/**
* 获取世界空间x,y值的单元格。
* 如果单元格为空且createCellIfEmpty为true则会创建一个新的单元格
* @param x
* @param y
* @param createCellIfEmpty
* 获取位于指定圆内的所有碰撞器
* @param circleCenter
* @param radius
* @param results
* @param layerMask
*/
private cellAtPosition(x: number, y: number, createCellIfEmpty: boolean = false) {
let cell: Collider[] = this._cellDict.tryGetValue(x, y);
if (!cell) {
if (createCellIfEmpty) {
cell = [];
this._cellDict.add(x, y, cell);
public overlapCircle(circleCenter: Vector2, radius: number, results: Collider[], layerMask) {
let bounds = new Rectangle(circleCenter.x - radius, circleCenter.y - radius, radius * 2, radius * 2);
this._overlapTestCircle.radius = radius;
this._overlapTestCircle.position = circleCenter;
let resultCounter = 0;
let aabbBroadphaseResult = this.aabbBroadphase(bounds, null, layerMask);
bounds = aabbBroadphaseResult.bounds;
let potentials = aabbBroadphaseResult.tempHashSet;
for (let i = 0; i < potentials.length; i++) {
let collider = potentials[i];
if (collider instanceof BoxCollider) {
results[resultCounter] = collider;
resultCounter++;
} else if (collider instanceof CircleCollider) {
if (collider.shape.overlaps(this._overlapTestCircle)){
results[resultCounter] = collider;
resultCounter ++;
}
} else if(collider instanceof PolygonCollider) {
if (collider.shape.overlaps(this._overlapTestCircle)){
results[resultCounter] = collider;
resultCounter ++;
}
return cell;
} else {
throw new Error("overlapCircle against this collider type is not implemented!");
}
/**
* 获取单元格的x,y值作为世界空间的x,y值
* @param x
* @param y
*/
private cellCoords(x: number, y: number): Vector2 {
return new Vector2(Math.floor(x * this._inverseCellSize), Math.floor(y * this._inverseCellSize));
// 如果我们所有的结果数据有了则返回
if (resultCounter == results.length)
return resultCounter;
}
/**
* debug绘制空间散列的内容
* @param secondsToDisplay
* @param textScale
*/
public debugDraw(secondsToDisplay: number, textScale: number = 1){
for (let x = this.gridBounds.x; x <= this.gridBounds.right; x ++){
for (let y = this.gridBounds.y; y <= this.gridBounds.bottom; y ++){
let cell = this.cellAtPosition(x, y);
if (cell && cell.length > 0)
this.debugDrawCellDetails(x, y, cell.length, secondsToDisplay, textScale);
return resultCounter;
}
}
}
private debugDrawCellDetails(x: number, y: number, cellCount: number, secondsToDisplay = 0.5, textScale = 1){
}
}
class RaycastResultParser {
}
/**
* 包装一个Unit32列表碰撞器字典
* 它的主要目的是将int、int x、y坐标散列到单个Uint32键中使用O(1)查找。
*/
class NumberDictionary {
private _store: Map<string, Collider[]> = new Map<string, Collider[]>();
export class NumberDictionary {
public _store: Map<string, Collider[]> = new Map<string, Collider[]>();
/**
* 根据x和y值计算并返回散列键
@@ -247,3 +262,8 @@ class NumberDictionary {
this._store.clear();
}
}
export class RaycastResultParser {
}
}