新增flag 帮助处理位掩码
This commit is contained in:
@@ -11,6 +11,7 @@
|
|||||||
- [x] 数学库
|
- [x] 数学库
|
||||||
- [x] 简易矩阵类
|
- [x] 简易矩阵类
|
||||||
- [x] 简易2d 向量类
|
- [x] 简易2d 向量类
|
||||||
|
- [x] 掩码实用类
|
||||||
- [x] BreadthFirst 寻路算法
|
- [x] BreadthFirst 寻路算法
|
||||||
- [x] Dijkstra 寻路算法
|
- [x] Dijkstra 寻路算法
|
||||||
|
|
||||||
@@ -36,7 +37,6 @@
|
|||||||
- [ ] FSM 简易状态机
|
- [ ] FSM 简易状态机
|
||||||
- [ ] 数学库
|
- [ ] 数学库
|
||||||
- [ ] 贝塞尔曲线
|
- [ ] 贝塞尔曲线
|
||||||
- [ ] 掩码实用类
|
|
||||||
- [ ] 快速随机数类
|
- [ ] 快速随机数类
|
||||||
- [ ] 浮点助手类
|
- [ ] 浮点助手类
|
||||||
- [ ] 高性能数组
|
- [ ] 高性能数组
|
||||||
|
|||||||
42
demo/libs/framework/framework.d.ts
vendored
42
demo/libs/framework/framework.d.ts
vendored
@@ -376,6 +376,11 @@ declare class SpriteRenderer extends RenderableComponent {
|
|||||||
setSprite(sprite: egret.DisplayObject): SpriteRenderer;
|
setSprite(sprite: egret.DisplayObject): SpriteRenderer;
|
||||||
initialize(): void;
|
initialize(): void;
|
||||||
}
|
}
|
||||||
|
declare abstract class Collider extends Component {
|
||||||
|
shape: Shape;
|
||||||
|
physicsLayer: number;
|
||||||
|
readonly bounds: Rectangle;
|
||||||
|
}
|
||||||
declare class EntitySystem {
|
declare class EntitySystem {
|
||||||
private _scene;
|
private _scene;
|
||||||
private _entities;
|
private _entities;
|
||||||
@@ -495,6 +500,14 @@ declare class Time {
|
|||||||
private static _lastTime;
|
private static _lastTime;
|
||||||
static update(currentTime: number): void;
|
static update(currentTime: number): void;
|
||||||
}
|
}
|
||||||
|
declare class Flags {
|
||||||
|
static isFlagSet(self: number, flag: number): boolean;
|
||||||
|
static isUnshiftedFlagSet(self: number, flag: number): boolean;
|
||||||
|
static setFlagExclusive(self: number, flag: number): void;
|
||||||
|
static setFlag(self: number, flag: number): void;
|
||||||
|
static unsetFlag(self: number, flag: number): void;
|
||||||
|
static invertFlags(self: number): void;
|
||||||
|
}
|
||||||
declare class MathHelper {
|
declare class MathHelper {
|
||||||
static toDegrees(radians: number): number;
|
static toDegrees(radians: number): number;
|
||||||
static toRadians(degrees: number): number;
|
static toRadians(degrees: number): number;
|
||||||
@@ -588,6 +601,12 @@ declare class Physics {
|
|||||||
}
|
}
|
||||||
declare abstract class Shape {
|
declare abstract class Shape {
|
||||||
bounds: Rectangle;
|
bounds: Rectangle;
|
||||||
|
position: Vector2;
|
||||||
|
}
|
||||||
|
declare class Circle extends Shape {
|
||||||
|
radius: number;
|
||||||
|
private _originalRadius;
|
||||||
|
constructor(radius: number);
|
||||||
}
|
}
|
||||||
declare class Polygon extends Shape {
|
declare class Polygon extends Shape {
|
||||||
points: Vector2[];
|
points: Vector2[];
|
||||||
@@ -610,7 +629,28 @@ declare class Particle {
|
|||||||
applyForce(force: Vector2): void;
|
applyForce(force: Vector2): void;
|
||||||
}
|
}
|
||||||
declare class SpatialHash {
|
declare class SpatialHash {
|
||||||
overlapCircle(circleCenter: Vector2, radius: number, results: any[], layerMask: any): number;
|
private _raycastParser;
|
||||||
|
private _cellSize;
|
||||||
|
private _inverseCellSize;
|
||||||
|
private _overlapTestCircle;
|
||||||
|
private _tempHashSet;
|
||||||
|
private _cellDict;
|
||||||
|
constructor(cellSize?: number);
|
||||||
|
overlapCircle(circleCenter: Vector2, radius: number, results: Collider[], layerMask: any): number;
|
||||||
|
aabbBroadphase(bounds: Rectangle, excludeCollider: Collider, layerMask: number): Collider[];
|
||||||
|
private cellAtPosition;
|
||||||
|
private cellCoords;
|
||||||
|
}
|
||||||
|
declare class RaycastResultParser {
|
||||||
|
}
|
||||||
|
declare class NumberDictionary {
|
||||||
|
private _store;
|
||||||
|
private getKey;
|
||||||
|
add(x: number, y: number, list: Collider[]): void;
|
||||||
|
remove(obj: Collider): void;
|
||||||
|
tryGetValue(x: number, y: number): Collider[];
|
||||||
|
getAllObjects(): Collider[];
|
||||||
|
clear(): void;
|
||||||
}
|
}
|
||||||
declare class VerletWorld {
|
declare class VerletWorld {
|
||||||
gravity: Vector2;
|
gravity: Vector2;
|
||||||
|
|||||||
@@ -1781,6 +1781,22 @@ var SpriteRenderer = (function (_super) {
|
|||||||
};
|
};
|
||||||
return SpriteRenderer;
|
return SpriteRenderer;
|
||||||
}(RenderableComponent));
|
}(RenderableComponent));
|
||||||
|
var Collider = (function (_super) {
|
||||||
|
__extends(Collider, _super);
|
||||||
|
function Collider() {
|
||||||
|
var _this = _super !== null && _super.apply(this, arguments) || this;
|
||||||
|
_this.physicsLayer = 1 << 0;
|
||||||
|
return _this;
|
||||||
|
}
|
||||||
|
Object.defineProperty(Collider.prototype, "bounds", {
|
||||||
|
get: function () {
|
||||||
|
return this.shape.bounds;
|
||||||
|
},
|
||||||
|
enumerable: true,
|
||||||
|
configurable: true
|
||||||
|
});
|
||||||
|
return Collider;
|
||||||
|
}(Component));
|
||||||
var EntitySystem = (function () {
|
var EntitySystem = (function () {
|
||||||
function EntitySystem(matcher) {
|
function EntitySystem(matcher) {
|
||||||
this._entities = [];
|
this._entities = [];
|
||||||
@@ -2320,6 +2336,31 @@ var Time = (function () {
|
|||||||
Time._lastTime = 0;
|
Time._lastTime = 0;
|
||||||
return Time;
|
return Time;
|
||||||
}());
|
}());
|
||||||
|
var Flags = (function () {
|
||||||
|
function Flags() {
|
||||||
|
}
|
||||||
|
Flags.isFlagSet = function (self, flag) {
|
||||||
|
return (self & flag) != 0;
|
||||||
|
};
|
||||||
|
Flags.isUnshiftedFlagSet = function (self, flag) {
|
||||||
|
flag = 1 << flag;
|
||||||
|
return (self & flag) != 0;
|
||||||
|
};
|
||||||
|
Flags.setFlagExclusive = function (self, flag) {
|
||||||
|
self = 1 << flag;
|
||||||
|
};
|
||||||
|
Flags.setFlag = function (self, flag) {
|
||||||
|
self = (self | 1 << flag);
|
||||||
|
};
|
||||||
|
Flags.unsetFlag = function (self, flag) {
|
||||||
|
flag = 1 << flag;
|
||||||
|
self = (self & (~flag));
|
||||||
|
};
|
||||||
|
Flags.invertFlags = function (self) {
|
||||||
|
self = ~self;
|
||||||
|
};
|
||||||
|
return Flags;
|
||||||
|
}());
|
||||||
var MathHelper = (function () {
|
var MathHelper = (function () {
|
||||||
function MathHelper() {
|
function MathHelper() {
|
||||||
}
|
}
|
||||||
@@ -2786,6 +2827,16 @@ var Shape = (function () {
|
|||||||
}
|
}
|
||||||
return Shape;
|
return Shape;
|
||||||
}());
|
}());
|
||||||
|
var Circle = (function (_super) {
|
||||||
|
__extends(Circle, _super);
|
||||||
|
function Circle(radius) {
|
||||||
|
var _this = _super.call(this) || this;
|
||||||
|
_this.radius = radius;
|
||||||
|
_this._originalRadius = radius;
|
||||||
|
return _this;
|
||||||
|
}
|
||||||
|
return Circle;
|
||||||
|
}(Shape));
|
||||||
var Polygon = (function (_super) {
|
var Polygon = (function (_super) {
|
||||||
__extends(Polygon, _super);
|
__extends(Polygon, _super);
|
||||||
function Polygon(vertCount, radius) {
|
function Polygon(vertCount, radius) {
|
||||||
@@ -2834,14 +2885,96 @@ var Particle = (function () {
|
|||||||
return Particle;
|
return Particle;
|
||||||
}());
|
}());
|
||||||
var SpatialHash = (function () {
|
var SpatialHash = (function () {
|
||||||
function SpatialHash() {
|
function SpatialHash(cellSize) {
|
||||||
|
if (cellSize === void 0) { cellSize = 100; }
|
||||||
|
this._tempHashSet = [];
|
||||||
|
this._cellDict = new NumberDictionary();
|
||||||
|
this._cellSize = cellSize;
|
||||||
|
this._inverseCellSize = 1 / this._cellSize;
|
||||||
|
this._raycastParser = new RaycastResultParser();
|
||||||
}
|
}
|
||||||
SpatialHash.prototype.overlapCircle = function (circleCenter, radius, results, layerMask) {
|
SpatialHash.prototype.overlapCircle = function (circleCenter, radius, results, layerMask) {
|
||||||
|
var bounds = new Rectangle(circleCenter.x - radius, circleCenter.y - radius, radius * 2, radius * 2);
|
||||||
|
this._overlapTestCircle.radius = radius;
|
||||||
|
this._overlapTestCircle.position = circleCenter;
|
||||||
var resultCounter = 0;
|
var resultCounter = 0;
|
||||||
|
var potentials = this.aabbBroadphase(bounds, null, layerMask);
|
||||||
|
potentials.forEach(function (collider) {
|
||||||
|
if (resultCounter == results.length)
|
||||||
|
return resultCounter;
|
||||||
|
});
|
||||||
return resultCounter;
|
return resultCounter;
|
||||||
};
|
};
|
||||||
|
SpatialHash.prototype.aabbBroadphase = function (bounds, excludeCollider, layerMask) {
|
||||||
|
this._tempHashSet.length = 0;
|
||||||
|
var p1 = this.cellCoords(bounds.x, bounds.y);
|
||||||
|
var p2 = this.cellCoords(bounds.right, bounds.bottom);
|
||||||
|
for (var x = p1.x; x <= p2.x; x++) {
|
||||||
|
for (var y = p1.y; y <= p2.y; y++) {
|
||||||
|
var cell = this.cellAtPosition(x, y);
|
||||||
|
if (!cell)
|
||||||
|
continue;
|
||||||
|
for (var i = 0; i < cell.length; i++) {
|
||||||
|
var collider = cell[i];
|
||||||
|
if (collider == excludeCollider || !Flags.isFlagSet(layerMask, collider.physicsLayer))
|
||||||
|
continue;
|
||||||
|
if (bounds.intersects(collider.bounds))
|
||||||
|
this._tempHashSet.push(collider);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return this._tempHashSet;
|
||||||
|
};
|
||||||
|
SpatialHash.prototype.cellAtPosition = function (x, y, createCellIfEmpty) {
|
||||||
|
if (createCellIfEmpty === void 0) { createCellIfEmpty = false; }
|
||||||
|
var cell = this._cellDict.tryGetValue(x, y);
|
||||||
|
if (!cell) {
|
||||||
|
if (createCellIfEmpty) {
|
||||||
|
cell = [];
|
||||||
|
this._cellDict.add(x, y, cell);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return cell;
|
||||||
|
};
|
||||||
|
SpatialHash.prototype.cellCoords = function (x, y) {
|
||||||
|
return new Point(Math.floor(x * this._inverseCellSize), Math.floor(y * this._inverseCellSize));
|
||||||
|
};
|
||||||
return SpatialHash;
|
return SpatialHash;
|
||||||
}());
|
}());
|
||||||
|
var RaycastResultParser = (function () {
|
||||||
|
function RaycastResultParser() {
|
||||||
|
}
|
||||||
|
return RaycastResultParser;
|
||||||
|
}());
|
||||||
|
var NumberDictionary = (function () {
|
||||||
|
function NumberDictionary() {
|
||||||
|
this._store = new Map();
|
||||||
|
}
|
||||||
|
NumberDictionary.prototype.getKey = function (x, y) {
|
||||||
|
return x << 32 | y;
|
||||||
|
};
|
||||||
|
NumberDictionary.prototype.add = function (x, y, list) {
|
||||||
|
this._store.set(this.getKey(x, y), list);
|
||||||
|
};
|
||||||
|
NumberDictionary.prototype.remove = function (obj) {
|
||||||
|
this._store.forEach(function (list) {
|
||||||
|
if (list.contains(obj))
|
||||||
|
list.remove(obj);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
NumberDictionary.prototype.tryGetValue = function (x, y) {
|
||||||
|
return this._store.get(this.getKey(x, y));
|
||||||
|
};
|
||||||
|
NumberDictionary.prototype.getAllObjects = function () {
|
||||||
|
var set = [];
|
||||||
|
this._store.forEach(function (list) { return set.concat(list); });
|
||||||
|
return set;
|
||||||
|
};
|
||||||
|
NumberDictionary.prototype.clear = function () {
|
||||||
|
this._store.clear();
|
||||||
|
};
|
||||||
|
return NumberDictionary;
|
||||||
|
}());
|
||||||
var VerletWorld = (function () {
|
var VerletWorld = (function () {
|
||||||
function VerletWorld(simulationBounds) {
|
function VerletWorld(simulationBounds) {
|
||||||
this.gravity = new Vector2(0, 980);
|
this.gravity = new Vector2(0, 980);
|
||||||
|
|||||||
2
demo/libs/framework/framework.min.js
vendored
2
demo/libs/framework/framework.min.js
vendored
File diff suppressed because one or more lines are too long
42
source/bin/framework.d.ts
vendored
42
source/bin/framework.d.ts
vendored
@@ -376,6 +376,11 @@ declare class SpriteRenderer extends RenderableComponent {
|
|||||||
setSprite(sprite: egret.DisplayObject): SpriteRenderer;
|
setSprite(sprite: egret.DisplayObject): SpriteRenderer;
|
||||||
initialize(): void;
|
initialize(): void;
|
||||||
}
|
}
|
||||||
|
declare abstract class Collider extends Component {
|
||||||
|
shape: Shape;
|
||||||
|
physicsLayer: number;
|
||||||
|
readonly bounds: Rectangle;
|
||||||
|
}
|
||||||
declare class EntitySystem {
|
declare class EntitySystem {
|
||||||
private _scene;
|
private _scene;
|
||||||
private _entities;
|
private _entities;
|
||||||
@@ -495,6 +500,14 @@ declare class Time {
|
|||||||
private static _lastTime;
|
private static _lastTime;
|
||||||
static update(currentTime: number): void;
|
static update(currentTime: number): void;
|
||||||
}
|
}
|
||||||
|
declare class Flags {
|
||||||
|
static isFlagSet(self: number, flag: number): boolean;
|
||||||
|
static isUnshiftedFlagSet(self: number, flag: number): boolean;
|
||||||
|
static setFlagExclusive(self: number, flag: number): void;
|
||||||
|
static setFlag(self: number, flag: number): void;
|
||||||
|
static unsetFlag(self: number, flag: number): void;
|
||||||
|
static invertFlags(self: number): void;
|
||||||
|
}
|
||||||
declare class MathHelper {
|
declare class MathHelper {
|
||||||
static toDegrees(radians: number): number;
|
static toDegrees(radians: number): number;
|
||||||
static toRadians(degrees: number): number;
|
static toRadians(degrees: number): number;
|
||||||
@@ -588,6 +601,12 @@ declare class Physics {
|
|||||||
}
|
}
|
||||||
declare abstract class Shape {
|
declare abstract class Shape {
|
||||||
bounds: Rectangle;
|
bounds: Rectangle;
|
||||||
|
position: Vector2;
|
||||||
|
}
|
||||||
|
declare class Circle extends Shape {
|
||||||
|
radius: number;
|
||||||
|
private _originalRadius;
|
||||||
|
constructor(radius: number);
|
||||||
}
|
}
|
||||||
declare class Polygon extends Shape {
|
declare class Polygon extends Shape {
|
||||||
points: Vector2[];
|
points: Vector2[];
|
||||||
@@ -610,7 +629,28 @@ declare class Particle {
|
|||||||
applyForce(force: Vector2): void;
|
applyForce(force: Vector2): void;
|
||||||
}
|
}
|
||||||
declare class SpatialHash {
|
declare class SpatialHash {
|
||||||
overlapCircle(circleCenter: Vector2, radius: number, results: any[], layerMask: any): number;
|
private _raycastParser;
|
||||||
|
private _cellSize;
|
||||||
|
private _inverseCellSize;
|
||||||
|
private _overlapTestCircle;
|
||||||
|
private _tempHashSet;
|
||||||
|
private _cellDict;
|
||||||
|
constructor(cellSize?: number);
|
||||||
|
overlapCircle(circleCenter: Vector2, radius: number, results: Collider[], layerMask: any): number;
|
||||||
|
aabbBroadphase(bounds: Rectangle, excludeCollider: Collider, layerMask: number): Collider[];
|
||||||
|
private cellAtPosition;
|
||||||
|
private cellCoords;
|
||||||
|
}
|
||||||
|
declare class RaycastResultParser {
|
||||||
|
}
|
||||||
|
declare class NumberDictionary {
|
||||||
|
private _store;
|
||||||
|
private getKey;
|
||||||
|
add(x: number, y: number, list: Collider[]): void;
|
||||||
|
remove(obj: Collider): void;
|
||||||
|
tryGetValue(x: number, y: number): Collider[];
|
||||||
|
getAllObjects(): Collider[];
|
||||||
|
clear(): void;
|
||||||
}
|
}
|
||||||
declare class VerletWorld {
|
declare class VerletWorld {
|
||||||
gravity: Vector2;
|
gravity: Vector2;
|
||||||
|
|||||||
@@ -1781,6 +1781,22 @@ var SpriteRenderer = (function (_super) {
|
|||||||
};
|
};
|
||||||
return SpriteRenderer;
|
return SpriteRenderer;
|
||||||
}(RenderableComponent));
|
}(RenderableComponent));
|
||||||
|
var Collider = (function (_super) {
|
||||||
|
__extends(Collider, _super);
|
||||||
|
function Collider() {
|
||||||
|
var _this = _super !== null && _super.apply(this, arguments) || this;
|
||||||
|
_this.physicsLayer = 1 << 0;
|
||||||
|
return _this;
|
||||||
|
}
|
||||||
|
Object.defineProperty(Collider.prototype, "bounds", {
|
||||||
|
get: function () {
|
||||||
|
return this.shape.bounds;
|
||||||
|
},
|
||||||
|
enumerable: true,
|
||||||
|
configurable: true
|
||||||
|
});
|
||||||
|
return Collider;
|
||||||
|
}(Component));
|
||||||
var EntitySystem = (function () {
|
var EntitySystem = (function () {
|
||||||
function EntitySystem(matcher) {
|
function EntitySystem(matcher) {
|
||||||
this._entities = [];
|
this._entities = [];
|
||||||
@@ -2320,6 +2336,31 @@ var Time = (function () {
|
|||||||
Time._lastTime = 0;
|
Time._lastTime = 0;
|
||||||
return Time;
|
return Time;
|
||||||
}());
|
}());
|
||||||
|
var Flags = (function () {
|
||||||
|
function Flags() {
|
||||||
|
}
|
||||||
|
Flags.isFlagSet = function (self, flag) {
|
||||||
|
return (self & flag) != 0;
|
||||||
|
};
|
||||||
|
Flags.isUnshiftedFlagSet = function (self, flag) {
|
||||||
|
flag = 1 << flag;
|
||||||
|
return (self & flag) != 0;
|
||||||
|
};
|
||||||
|
Flags.setFlagExclusive = function (self, flag) {
|
||||||
|
self = 1 << flag;
|
||||||
|
};
|
||||||
|
Flags.setFlag = function (self, flag) {
|
||||||
|
self = (self | 1 << flag);
|
||||||
|
};
|
||||||
|
Flags.unsetFlag = function (self, flag) {
|
||||||
|
flag = 1 << flag;
|
||||||
|
self = (self & (~flag));
|
||||||
|
};
|
||||||
|
Flags.invertFlags = function (self) {
|
||||||
|
self = ~self;
|
||||||
|
};
|
||||||
|
return Flags;
|
||||||
|
}());
|
||||||
var MathHelper = (function () {
|
var MathHelper = (function () {
|
||||||
function MathHelper() {
|
function MathHelper() {
|
||||||
}
|
}
|
||||||
@@ -2786,6 +2827,16 @@ var Shape = (function () {
|
|||||||
}
|
}
|
||||||
return Shape;
|
return Shape;
|
||||||
}());
|
}());
|
||||||
|
var Circle = (function (_super) {
|
||||||
|
__extends(Circle, _super);
|
||||||
|
function Circle(radius) {
|
||||||
|
var _this = _super.call(this) || this;
|
||||||
|
_this.radius = radius;
|
||||||
|
_this._originalRadius = radius;
|
||||||
|
return _this;
|
||||||
|
}
|
||||||
|
return Circle;
|
||||||
|
}(Shape));
|
||||||
var Polygon = (function (_super) {
|
var Polygon = (function (_super) {
|
||||||
__extends(Polygon, _super);
|
__extends(Polygon, _super);
|
||||||
function Polygon(vertCount, radius) {
|
function Polygon(vertCount, radius) {
|
||||||
@@ -2834,14 +2885,96 @@ var Particle = (function () {
|
|||||||
return Particle;
|
return Particle;
|
||||||
}());
|
}());
|
||||||
var SpatialHash = (function () {
|
var SpatialHash = (function () {
|
||||||
function SpatialHash() {
|
function SpatialHash(cellSize) {
|
||||||
|
if (cellSize === void 0) { cellSize = 100; }
|
||||||
|
this._tempHashSet = [];
|
||||||
|
this._cellDict = new NumberDictionary();
|
||||||
|
this._cellSize = cellSize;
|
||||||
|
this._inverseCellSize = 1 / this._cellSize;
|
||||||
|
this._raycastParser = new RaycastResultParser();
|
||||||
}
|
}
|
||||||
SpatialHash.prototype.overlapCircle = function (circleCenter, radius, results, layerMask) {
|
SpatialHash.prototype.overlapCircle = function (circleCenter, radius, results, layerMask) {
|
||||||
|
var bounds = new Rectangle(circleCenter.x - radius, circleCenter.y - radius, radius * 2, radius * 2);
|
||||||
|
this._overlapTestCircle.radius = radius;
|
||||||
|
this._overlapTestCircle.position = circleCenter;
|
||||||
var resultCounter = 0;
|
var resultCounter = 0;
|
||||||
|
var potentials = this.aabbBroadphase(bounds, null, layerMask);
|
||||||
|
potentials.forEach(function (collider) {
|
||||||
|
if (resultCounter == results.length)
|
||||||
|
return resultCounter;
|
||||||
|
});
|
||||||
return resultCounter;
|
return resultCounter;
|
||||||
};
|
};
|
||||||
|
SpatialHash.prototype.aabbBroadphase = function (bounds, excludeCollider, layerMask) {
|
||||||
|
this._tempHashSet.length = 0;
|
||||||
|
var p1 = this.cellCoords(bounds.x, bounds.y);
|
||||||
|
var p2 = this.cellCoords(bounds.right, bounds.bottom);
|
||||||
|
for (var x = p1.x; x <= p2.x; x++) {
|
||||||
|
for (var y = p1.y; y <= p2.y; y++) {
|
||||||
|
var cell = this.cellAtPosition(x, y);
|
||||||
|
if (!cell)
|
||||||
|
continue;
|
||||||
|
for (var i = 0; i < cell.length; i++) {
|
||||||
|
var collider = cell[i];
|
||||||
|
if (collider == excludeCollider || !Flags.isFlagSet(layerMask, collider.physicsLayer))
|
||||||
|
continue;
|
||||||
|
if (bounds.intersects(collider.bounds))
|
||||||
|
this._tempHashSet.push(collider);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return this._tempHashSet;
|
||||||
|
};
|
||||||
|
SpatialHash.prototype.cellAtPosition = function (x, y, createCellIfEmpty) {
|
||||||
|
if (createCellIfEmpty === void 0) { createCellIfEmpty = false; }
|
||||||
|
var cell = this._cellDict.tryGetValue(x, y);
|
||||||
|
if (!cell) {
|
||||||
|
if (createCellIfEmpty) {
|
||||||
|
cell = [];
|
||||||
|
this._cellDict.add(x, y, cell);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return cell;
|
||||||
|
};
|
||||||
|
SpatialHash.prototype.cellCoords = function (x, y) {
|
||||||
|
return new Point(Math.floor(x * this._inverseCellSize), Math.floor(y * this._inverseCellSize));
|
||||||
|
};
|
||||||
return SpatialHash;
|
return SpatialHash;
|
||||||
}());
|
}());
|
||||||
|
var RaycastResultParser = (function () {
|
||||||
|
function RaycastResultParser() {
|
||||||
|
}
|
||||||
|
return RaycastResultParser;
|
||||||
|
}());
|
||||||
|
var NumberDictionary = (function () {
|
||||||
|
function NumberDictionary() {
|
||||||
|
this._store = new Map();
|
||||||
|
}
|
||||||
|
NumberDictionary.prototype.getKey = function (x, y) {
|
||||||
|
return x << 32 | y;
|
||||||
|
};
|
||||||
|
NumberDictionary.prototype.add = function (x, y, list) {
|
||||||
|
this._store.set(this.getKey(x, y), list);
|
||||||
|
};
|
||||||
|
NumberDictionary.prototype.remove = function (obj) {
|
||||||
|
this._store.forEach(function (list) {
|
||||||
|
if (list.contains(obj))
|
||||||
|
list.remove(obj);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
NumberDictionary.prototype.tryGetValue = function (x, y) {
|
||||||
|
return this._store.get(this.getKey(x, y));
|
||||||
|
};
|
||||||
|
NumberDictionary.prototype.getAllObjects = function () {
|
||||||
|
var set = [];
|
||||||
|
this._store.forEach(function (list) { return set.concat(list); });
|
||||||
|
return set;
|
||||||
|
};
|
||||||
|
NumberDictionary.prototype.clear = function () {
|
||||||
|
this._store.clear();
|
||||||
|
};
|
||||||
|
return NumberDictionary;
|
||||||
|
}());
|
||||||
var VerletWorld = (function () {
|
var VerletWorld = (function () {
|
||||||
function VerletWorld(simulationBounds) {
|
function VerletWorld(simulationBounds) {
|
||||||
this.gravity = new Vector2(0, 980);
|
this.gravity = new Vector2(0, 980);
|
||||||
|
|||||||
2
source/bin/framework.min.js
vendored
2
source/bin/framework.min.js
vendored
File diff suppressed because one or more lines are too long
8
source/src/ECS/Components/Physics/Collider.ts
Normal file
8
source/src/ECS/Components/Physics/Collider.ts
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
abstract class Collider extends Component{
|
||||||
|
public shape: Shape;
|
||||||
|
public physicsLayer = 1 << 0;
|
||||||
|
|
||||||
|
public get bounds(): Rectangle {
|
||||||
|
return this.shape.bounds;
|
||||||
|
}
|
||||||
|
}
|
||||||
59
source/src/Math/Flags.ts
Normal file
59
source/src/Math/Flags.ts
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
/**
|
||||||
|
* 帮助处理位掩码的实用程序类
|
||||||
|
*/
|
||||||
|
class Flags {
|
||||||
|
/**
|
||||||
|
* 检查位标志是否已在整型中设置
|
||||||
|
* @param self
|
||||||
|
* @param flag
|
||||||
|
*/
|
||||||
|
public static isFlagSet(self: number, flag: number){
|
||||||
|
return (self & flag) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 检查位标志是否在整型中设置
|
||||||
|
* @param self
|
||||||
|
* @param flag
|
||||||
|
*/
|
||||||
|
public static isUnshiftedFlagSet(self: number, flag: number){
|
||||||
|
flag = 1 << flag;
|
||||||
|
return (self & flag) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置标志位,移除所有已经设置的标志
|
||||||
|
* @param self
|
||||||
|
* @param flag
|
||||||
|
*/
|
||||||
|
public static setFlagExclusive(self: number, flag: number){
|
||||||
|
self = 1 << flag;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置标志位
|
||||||
|
* @param self
|
||||||
|
* @param flag
|
||||||
|
*/
|
||||||
|
public static setFlag(self: number, flag: number){
|
||||||
|
self = (self | 1 << flag);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 取消标志位
|
||||||
|
* @param self
|
||||||
|
* @param flag
|
||||||
|
*/
|
||||||
|
public static unsetFlag(self: number, flag: number){
|
||||||
|
flag = 1 << flag;
|
||||||
|
self = (self & (~flag));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 反转集合位
|
||||||
|
* @param self
|
||||||
|
*/
|
||||||
|
public static invertFlags(self: number){
|
||||||
|
self = ~self;
|
||||||
|
}
|
||||||
|
}
|
||||||
11
source/src/Physics/Shapes/Circle.ts
Normal file
11
source/src/Physics/Shapes/Circle.ts
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
///<reference path="./Shape.ts" />
|
||||||
|
class Circle extends Shape {
|
||||||
|
public radius: number;
|
||||||
|
private _originalRadius: number;
|
||||||
|
|
||||||
|
constructor(radius: number){
|
||||||
|
super();
|
||||||
|
this.radius = radius;
|
||||||
|
this._originalRadius = radius;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
abstract class Shape {
|
abstract class Shape {
|
||||||
public bounds: Rectangle;
|
public bounds: Rectangle;
|
||||||
|
public position: Vector2;
|
||||||
}
|
}
|
||||||
@@ -1,7 +1,111 @@
|
|||||||
class SpatialHash {
|
class SpatialHash {
|
||||||
public overlapCircle(circleCenter: Vector2, radius: number, results: any[], layerMask){
|
private _raycastParser: RaycastResultParser;
|
||||||
|
private _cellSize: number;
|
||||||
|
private _inverseCellSize: number;
|
||||||
|
private _overlapTestCircle: Circle;
|
||||||
|
private _tempHashSet: Collider[] = [];
|
||||||
|
private _cellDict: NumberDictionary = new NumberDictionary();
|
||||||
|
|
||||||
|
constructor(cellSize: number = 100){
|
||||||
|
this._cellSize = cellSize;
|
||||||
|
this._inverseCellSize = 1 / this._cellSize;
|
||||||
|
this._raycastParser = new RaycastResultParser();
|
||||||
|
}
|
||||||
|
|
||||||
|
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 resultCounter = 0;
|
||||||
|
let potentials = this.aabbBroadphase(bounds, null, layerMask);
|
||||||
|
potentials.forEach(collider => {
|
||||||
|
if (resultCounter == results.length)
|
||||||
|
return resultCounter;
|
||||||
|
});
|
||||||
|
|
||||||
return resultCounter;
|
return resultCounter;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public aabbBroadphase(bounds: Rectangle, excludeCollider: Collider, layerMask: number){
|
||||||
|
this._tempHashSet.length = 0;
|
||||||
|
|
||||||
|
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)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
for (let i = 0; i < cell.length; i ++){
|
||||||
|
let collider = cell[i];
|
||||||
|
|
||||||
|
if (collider == excludeCollider || !Flags.isFlagSet(layerMask, collider.physicsLayer))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (bounds.intersects(collider.bounds))
|
||||||
|
this._tempHashSet.push(collider);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return this._tempHashSet;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
private cellCoords(x: number, y: number): Point {
|
||||||
|
return new Point(Math.floor(x * this._inverseCellSize), Math.floor(y * this._inverseCellSize));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class RaycastResultParser {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
class NumberDictionary {
|
||||||
|
private _store: Map<number, Collider[]> = new Map<number, Collider[]>();
|
||||||
|
|
||||||
|
private getKey(x: number, y: number): number{
|
||||||
|
return x << 32 | y;
|
||||||
|
}
|
||||||
|
|
||||||
|
public add(x: number, y: number, list: Collider[]){
|
||||||
|
this._store.set(this.getKey(x, y), list);
|
||||||
|
}
|
||||||
|
|
||||||
|
public remove(obj: Collider){
|
||||||
|
this._store.forEach(list => {
|
||||||
|
if (list.contains(obj))
|
||||||
|
list.remove(obj);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
public tryGetValue(x: number, y: number): Collider[]{
|
||||||
|
return this._store.get(this.getKey(x, y));
|
||||||
|
}
|
||||||
|
|
||||||
|
public getAllObjects(): Collider[]{
|
||||||
|
let set: Collider[] = [];
|
||||||
|
|
||||||
|
this._store.forEach(list => set.concat(list));
|
||||||
|
|
||||||
|
return set;
|
||||||
|
}
|
||||||
|
|
||||||
|
public clear(){
|
||||||
|
this._store.clear();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user