新增flag 帮助处理位掩码

This commit is contained in:
YHH
2020-06-12 08:47:13 +08:00
parent ad68f0e1a0
commit 6fa56dd572
12 changed files with 537 additions and 8 deletions

View File

@@ -376,6 +376,11 @@ declare class SpriteRenderer extends RenderableComponent {
setSprite(sprite: egret.DisplayObject): SpriteRenderer;
initialize(): void;
}
declare abstract class Collider extends Component {
shape: Shape;
physicsLayer: number;
readonly bounds: Rectangle;
}
declare class EntitySystem {
private _scene;
private _entities;
@@ -495,6 +500,14 @@ declare class Time {
private static _lastTime;
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 {
static toDegrees(radians: number): number;
static toRadians(degrees: number): number;
@@ -588,6 +601,12 @@ declare class Physics {
}
declare abstract class Shape {
bounds: Rectangle;
position: Vector2;
}
declare class Circle extends Shape {
radius: number;
private _originalRadius;
constructor(radius: number);
}
declare class Polygon extends Shape {
points: Vector2[];
@@ -610,7 +629,28 @@ declare class Particle {
applyForce(force: Vector2): void;
}
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 {
gravity: Vector2;

View File

@@ -1781,6 +1781,22 @@ var SpriteRenderer = (function (_super) {
};
return SpriteRenderer;
}(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 () {
function EntitySystem(matcher) {
this._entities = [];
@@ -2320,6 +2336,31 @@ var Time = (function () {
Time._lastTime = 0;
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 () {
function MathHelper() {
}
@@ -2786,6 +2827,16 @@ var Shape = (function () {
}
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) {
__extends(Polygon, _super);
function Polygon(vertCount, radius) {
@@ -2834,14 +2885,96 @@ var Particle = (function () {
return Particle;
}());
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) {
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 potentials = this.aabbBroadphase(bounds, null, layerMask);
potentials.forEach(function (collider) {
if (resultCounter == results.length)
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;
}());
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 () {
function VerletWorld(simulationBounds) {
this.gravity = new Vector2(0, 980);

File diff suppressed because one or more lines are too long

View 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
View 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;
}
}

View 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;
}
}

View File

@@ -1,3 +1,4 @@
abstract class Shape {
public bounds: Rectangle;
public position: Vector2;
}

View File

@@ -1,7 +1,111 @@
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 potentials = this.aabbBroadphase(bounds, null, layerMask);
potentials.forEach(collider => {
if (resultCounter == results.length)
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();
}
}