新增 circleCollider与 polygonCollider

This commit is contained in:
yhh
2020-07-09 15:11:30 +08:00
parent 6e3eb1189a
commit 817b703d4f
13 changed files with 253 additions and 18 deletions

View File

@@ -3,11 +3,7 @@
[![Language grade: JavaScript](https://img.shields.io/lgtm/grade/javascript/g/esengine/egret-framework.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/esengine/egret-framework/context:javascript)
```
[![Language grade: JavaScript](https://img.shields.io/lgtm/grade/javascript/g/esengine/egret-framework.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/esengine/egret-framework/context:javascript)
```
这是一套用于egret的游戏框架里面包含ECS框架用于管理场景实体MVC框架用于管理ui界面fairygui一些常用2D碰撞检测及A*寻路。如果您还需要包含其他的AI系统可以查看作者其他库行为树、简易FSM、实用AI
这是一套用于egret的游戏框架里面包含ECS框架用于管理场景实体一些常用2D碰撞检测及A*寻路。如果您还需要包含其他的AI系统可以查看作者其他库行为树、简易FSM、实用AI
## 当前版本功能

View File

@@ -458,6 +458,14 @@ declare class BoxCollider extends Collider {
constructor();
setSize(width: number, height: number): this;
}
declare class CircleCollider extends Collider {
radius: number;
constructor(radius?: number);
setRadius(radius: number): CircleCollider;
}
declare class PolygonCollider extends Collider {
constructor(points: Vector2[]);
}
declare class EntitySystem {
private _scene;
private _entities;
@@ -873,6 +881,7 @@ declare class Polygon extends Shape {
recalculateCenterAndEdgeNormals(): void;
overlaps(other: Shape): any;
static findPolygonCenter(points: Vector2[]): Vector2;
static recenterPolygonVerts(points: Vector2[]): void;
static getClosestPointOnPolygonToPoint(points: Vector2[], point: Vector2): {
closestPoint: any;
distanceSquared: any;
@@ -895,7 +904,7 @@ declare class Box extends Polygon {
}
declare class Circle extends Shape {
radius: number;
private _originalRadius;
_originalRadius: number;
center: Vector2;
constructor(radius: number);
pointCollidesWithShape(point: Vector2): CollisionResult;

View File

@@ -2043,7 +2043,7 @@ var Collider = (function (_super) {
};
Collider.prototype.onAddedToEntity = function () {
if (this._colliderRequiresAutoSizing) {
if (!(this instanceof BoxCollider)) {
if (!(this instanceof BoxCollider || this instanceof CircleCollider)) {
console.error("Only box and circle colliders can be created automatically");
}
var renderable = this.entity.getComponent(RenderableComponent);
@@ -2051,7 +2051,12 @@ var Collider = (function (_super) {
var bounds = renderable.bounds;
var width = bounds.width / this.entity.scale.x;
var height = bounds.height / this.entity.scale.y;
if (this instanceof BoxCollider) {
if (this instanceof CircleCollider) {
var circleCollider = this;
circleCollider.radius = Math.max(width, height) * 0.5;
this.localOffset = bounds.location;
}
else {
var boxCollider = this;
boxCollider.width = width;
boxCollider.height = height;
@@ -2147,6 +2152,53 @@ var BoxCollider = (function (_super) {
};
return BoxCollider;
}(Collider));
var CircleCollider = (function (_super) {
__extends(CircleCollider, _super);
function CircleCollider(radius) {
var _this = _super.call(this) || this;
if (radius)
_this._colliderRequiresAutoSizing = true;
_this.shape = new Circle(radius ? radius : 1);
return _this;
}
Object.defineProperty(CircleCollider.prototype, "radius", {
get: function () {
return this.shape.radius;
},
set: function (value) {
this.setRadius(value);
},
enumerable: true,
configurable: true
});
CircleCollider.prototype.setRadius = function (radius) {
this._colliderRequiresAutoSizing = false;
var circle = this.shape;
if (radius != circle.radius) {
circle.radius = radius;
circle._originalRadius = radius;
if (this.entity && this._isParentEntityAddedToScene)
Physics.updateCollider(this);
}
return this;
};
return CircleCollider;
}(Collider));
var PolygonCollider = (function (_super) {
__extends(PolygonCollider, _super);
function PolygonCollider(points) {
var _this = _super.call(this) || this;
var isPolygonClosed = points[0] == points[points.length - 1];
if (isPolygonClosed)
points.splice(points.length - 1, 1);
var center = Polygon.findPolygonCenter(points);
_this.setLocalOffset(center);
Polygon.recenterPolygonVerts(points);
_this.shape = new Polygon(points);
return _this;
}
return PolygonCollider;
}(Collider));
var EntitySystem = (function () {
function EntitySystem(matcher) {
this._entities = [];
@@ -3999,6 +4051,11 @@ var Polygon = (function (_super) {
}
return new Vector2(x / points.length, y / points.length);
};
Polygon.recenterPolygonVerts = function (points) {
var center = this.findPolygonCenter(points);
for (var i = 0; i < points.length; i++)
points[i] = Vector2.subtract(points[i], center);
};
Polygon.getClosestPointOnPolygonToPoint = function (points, point) {
var distanceSquared = Number.MAX_VALUE;
var edgeNormal = new Vector2(0, 0);
@@ -4439,6 +4496,12 @@ var SpatialHash = (function () {
results[resultCounter] = collider;
resultCounter++;
}
else if (collider instanceof CircleCollider) {
if (collider.shape.overlaps(this._overlapTestCircle)) {
results[resultCounter] = collider;
resultCounter++;
}
}
else {
throw new Error("overlapCircle against this collider type is not implemented!");
}

File diff suppressed because one or more lines are too long

View File

@@ -458,6 +458,14 @@ declare class BoxCollider extends Collider {
constructor();
setSize(width: number, height: number): this;
}
declare class CircleCollider extends Collider {
radius: number;
constructor(radius?: number);
setRadius(radius: number): CircleCollider;
}
declare class PolygonCollider extends Collider {
constructor(points: Vector2[]);
}
declare class EntitySystem {
private _scene;
private _entities;
@@ -873,6 +881,7 @@ declare class Polygon extends Shape {
recalculateCenterAndEdgeNormals(): void;
overlaps(other: Shape): any;
static findPolygonCenter(points: Vector2[]): Vector2;
static recenterPolygonVerts(points: Vector2[]): void;
static getClosestPointOnPolygonToPoint(points: Vector2[], point: Vector2): {
closestPoint: any;
distanceSquared: any;
@@ -895,7 +904,7 @@ declare class Box extends Polygon {
}
declare class Circle extends Shape {
radius: number;
private _originalRadius;
_originalRadius: number;
center: Vector2;
constructor(radius: number);
pointCollidesWithShape(point: Vector2): CollisionResult;

View File

@@ -2043,7 +2043,7 @@ var Collider = (function (_super) {
};
Collider.prototype.onAddedToEntity = function () {
if (this._colliderRequiresAutoSizing) {
if (!(this instanceof BoxCollider)) {
if (!(this instanceof BoxCollider || this instanceof CircleCollider)) {
console.error("Only box and circle colliders can be created automatically");
}
var renderable = this.entity.getComponent(RenderableComponent);
@@ -2051,7 +2051,12 @@ var Collider = (function (_super) {
var bounds = renderable.bounds;
var width = bounds.width / this.entity.scale.x;
var height = bounds.height / this.entity.scale.y;
if (this instanceof BoxCollider) {
if (this instanceof CircleCollider) {
var circleCollider = this;
circleCollider.radius = Math.max(width, height) * 0.5;
this.localOffset = bounds.location;
}
else {
var boxCollider = this;
boxCollider.width = width;
boxCollider.height = height;
@@ -2147,6 +2152,53 @@ var BoxCollider = (function (_super) {
};
return BoxCollider;
}(Collider));
var CircleCollider = (function (_super) {
__extends(CircleCollider, _super);
function CircleCollider(radius) {
var _this = _super.call(this) || this;
if (radius)
_this._colliderRequiresAutoSizing = true;
_this.shape = new Circle(radius ? radius : 1);
return _this;
}
Object.defineProperty(CircleCollider.prototype, "radius", {
get: function () {
return this.shape.radius;
},
set: function (value) {
this.setRadius(value);
},
enumerable: true,
configurable: true
});
CircleCollider.prototype.setRadius = function (radius) {
this._colliderRequiresAutoSizing = false;
var circle = this.shape;
if (radius != circle.radius) {
circle.radius = radius;
circle._originalRadius = radius;
if (this.entity && this._isParentEntityAddedToScene)
Physics.updateCollider(this);
}
return this;
};
return CircleCollider;
}(Collider));
var PolygonCollider = (function (_super) {
__extends(PolygonCollider, _super);
function PolygonCollider(points) {
var _this = _super.call(this) || this;
var isPolygonClosed = points[0] == points[points.length - 1];
if (isPolygonClosed)
points.splice(points.length - 1, 1);
var center = Polygon.findPolygonCenter(points);
_this.setLocalOffset(center);
Polygon.recenterPolygonVerts(points);
_this.shape = new Polygon(points);
return _this;
}
return PolygonCollider;
}(Collider));
var EntitySystem = (function () {
function EntitySystem(matcher) {
this._entities = [];
@@ -3999,6 +4051,11 @@ var Polygon = (function (_super) {
}
return new Vector2(x / points.length, y / points.length);
};
Polygon.recenterPolygonVerts = function (points) {
var center = this.findPolygonCenter(points);
for (var i = 0; i < points.length; i++)
points[i] = Vector2.subtract(points[i], center);
};
Polygon.getClosestPointOnPolygonToPoint = function (points, point) {
var distanceSquared = Number.MAX_VALUE;
var edgeNormal = new Vector2(0, 0);
@@ -4439,6 +4496,12 @@ var SpatialHash = (function () {
results[resultCounter] = collider;
resultCounter++;
}
else if (collider instanceof CircleCollider) {
if (collider.shape.overlaps(this._overlapTestCircle)) {
results[resultCounter] = collider;
resultCounter++;
}
}
else {
throw new Error("overlapCircle against this collider type is not implemented!");
}

File diff suppressed because one or more lines are too long

View File

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

View File

@@ -99,7 +99,7 @@ abstract class Collider extends Component {
public onAddedToEntity() {
if (this._colliderRequiresAutoSizing) {
if (!(this instanceof BoxCollider)) {
if (!(this instanceof BoxCollider || this instanceof CircleCollider)) {
console.error("Only box and circle colliders can be created automatically");
}
@@ -111,12 +111,17 @@ abstract class Collider extends Component {
let width = bounds.width / this.entity.scale.x;
let height = bounds.height / this.entity.scale.y;
if (this instanceof BoxCollider) {
let boxCollider = this as BoxCollider;
// 圆碰撞器需要特别注意原点
if (this instanceof CircleCollider){
let circleCollider = this as CircleCollider;
circleCollider.radius = Math.max(width, height) * 0.5;
this.localOffset = bounds.location;
} else {
let boxCollider = this;
boxCollider.width = width;
boxCollider.height = height;
// 获取渲染的中心将其转移到本地坐标并使用它作为碰撞器的localOffset
this.localOffset = bounds.location;
}
} else {

View File

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

View File

@@ -1,7 +1,7 @@
///<reference path="./Shape.ts" />
class Circle extends Shape {
public radius: number;
private _originalRadius: number;
public _originalRadius: number;
public center = new Vector2();
constructor(radius: number) {

View File

@@ -93,6 +93,10 @@ class Polygon extends Shape {
throw new Error(`overlaps of Pologon to ${other} are not supported`);
}
/**
* 找到多边形的中心。注意,这对于正则多边形是准确的。不规则多边形没有中心。
* @param points
*/
public static findPolygonCenter(points: Vector2[]) {
let x = 0, y = 0;
@@ -104,6 +108,16 @@ class Polygon extends Shape {
return new Vector2(x / points.length, y / points.length);
}
/**
* 重定位多边形的点
* @param points
*/
public static recenterPolygonVerts(points: Vector2[]){
let center = this.findPolygonCenter(points);
for (let i = 0; i < points.length; i ++)
points[i] = Vector2.subtract(points[i], center);
}
/**
* 迭代多边形的所有边,并得到任意边上离点最近的点。
* 通过最近点的平方距离和它所在的边的法线返回。

View File

@@ -94,10 +94,21 @@ class SpatialHash {
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 ++;
}
} else {
throw new Error("overlapCircle against this collider type is not implemented!");
}
// 如果我们所有的结果数据有了则返回
if (resultCounter == results.length)
return resultCounter;
}