新增子模块与文件迁移

This commit is contained in:
yhh
2020-12-10 16:15:19 +08:00
parent c0450f21b6
commit 59c8d456cb
30 changed files with 3028 additions and 2726 deletions

View File

@@ -86,8 +86,8 @@ module es {
if (this._instance._scene == null) {
this._instance._scene = value;
this._instance.onSceneChanged();
this._instance._scene.begin();
Core.Instance.onSceneChanged();
} else {
this._instance._nextScene = value;
}

View File

@@ -398,7 +398,7 @@ module es {
* 对精灵坐标进行四舍五入
*/
public roundPosition() {
this.position = this._position.round();
this.position = Vector2Ext.round(this._position);
}
public updateTransform() {

View File

@@ -116,7 +116,7 @@ module es {
* @param polygon
* @param result
*/
public static circleToPolygon(circle: Circle, polygon: Polygon, result: CollisionResult): boolean {
public static circleToPolygon(circle: Circle, polygon: Polygon, result: CollisionResult = new CollisionResult()): boolean {
// 圆圈在多边形中的位置坐标
let poly2Circle = Vector2.subtract(circle.position, polygon.position);
@@ -141,7 +141,7 @@ module es {
mtv = new Vector2(result.normal.x * circle.radius, result.normal.y * circle.radius);
} else {
let distance = Math.sqrt(distanceSquared.value);
mtv = new Vector2(-poly2Circle.x + closestPoint.x, -poly2Circle.y + closestPoint.y)
mtv = Vector2.subtract(new Vector2(-1), Vector2.subtract(poly2Circle, closestPoint))
.multiply(new Vector2((circle.radius - distance) / distance));
}
}
@@ -153,19 +153,19 @@ module es {
}
/**
* 适用于心在框内以及只与方框外心重的圆。
* 适用于心在框内的圆,也适用于与框外心重的圆。
* @param circle
* @param box
* @param result
*/
public static circleToBox(circle: Circle, box: Box, result: CollisionResult): boolean {
public static circleToBox(circle: Circle, box: Box, result: CollisionResult = new CollisionResult()): boolean {
let closestPointOnBounds = box.bounds.getClosestPointOnRectangleBorderToPoint(circle.position, result.normal);
// 处理那些中心在盒子里的圆,因为比较好操作
// 处理中心在盒子里的圆,如果我们是包含的, 它的成本更低
if (box.containsPoint(circle.position)) {
result.point = closestPointOnBounds;
result.point = closestPointOnBounds.clone();
// 计算mtv。找安全的,没有碰撞的位置,然后从那里得到mtv
// 计算MTV。找安全的、非碰撞的位置,并从中得到MTV
let safePlace = Vector2.add(closestPointOnBounds, Vector2.multiply(result.normal, new Vector2(circle.radius)));
result.minimumTranslationVector = Vector2.subtract(circle.position, safePlace);
@@ -173,7 +173,8 @@ module es {
}
let sqrDistance = Vector2.distanceSquared(closestPointOnBounds, circle.position);
// 看盒子上的点与圆的距离是否小于半径
// 看框上的点距圆的半径是否小于圆的半径
if (sqrDistance == 0) {
result.minimumTranslationVector = Vector2.multiply(result.normal, new Vector2(circle.radius));
} else if (sqrDistance <= circle.radius * circle.radius) {
@@ -236,7 +237,7 @@ module es {
let t = Vector2.dot(w, v) / Vector2.dot(v, v);
t = MathHelper.clamp(t, 0, 1);
return Vector2.add(lineA, Vector2.multiply(v, new Vector2(t, t)));
return Vector2.add(lineA, Vector2.multiply(v, new Vector2(t)));
}
/**
@@ -265,7 +266,7 @@ module es {
* @param second
* @param result
*/
public static circleToCircle(first: Circle, second: Circle, result: CollisionResult): boolean {
public static circleToCircle(first: Circle, second: Circle, result: CollisionResult = new CollisionResult()): boolean {
let distanceSquared = Vector2.distanceSquared(first.position, second.position);
let sumOfRadii = first.radius + second.radius;
let collided = distanceSquared < sumOfRadii * sumOfRadii;
@@ -275,6 +276,11 @@ module es {
result.minimumTranslationVector = Vector2.multiply(new Vector2(-depth), result.normal);
result.point = Vector2.add(second.position, Vector2.multiply(result.normal, new Vector2(second.radius)));
// 这可以得到实际的碰撞点,可能有用也可能没用,所以我们暂时把它留在这里
// let collisionPointX = ((first.position.x * second.radius) + (second.position.x * first.radius)) / sumOfRadii;
// let collisionPointY = ((first.position.y * second.radius) + (second.position.y * first.radius)) / sumOfRadii;
// result.point = new Vector2(collisionPointX, collisionPointY);
return true;
}
@@ -315,7 +321,7 @@ module es {
return new Rectangle(topLeft.x, topLeft.y, fullSize.x, fullSize.y)
}
public static lineToPoly(start: Vector2, end: Vector2, polygon: Polygon, hit: RaycastHit): boolean {
public static lineToPoly(start: Vector2, end: Vector2, polygon: Polygon, hit: RaycastHit = new RaycastHit()): boolean {
let normal = Vector2.zero;
let intersectionPoint = Vector2.zero;
let fraction = Number.MAX_VALUE;

View File

@@ -1,297 +1,297 @@
class ArrayUtils {
/**
*
* @param ary
*/
public static bubbleSort(ary: number[]): void {
let isExchange: Boolean = false;
for (let i: number = 0; i < ary.length; i++) {
isExchange = false;
for (let j: number = ary.length - 1; j > i; j--) {
if (ary[j] < ary[j - 1]) {
let temp: number = ary[j];
ary[j] = ary[j - 1];
ary[j - 1] = temp;
isExchange = true;
}
}
if (!isExchange)
break;
}
}
/**
*
* @param ary
*/
public static insertionSort(ary: number[]): void {
let len: number = ary.length;
for (let i: number = 1; i < len; i++) {
let val: number = ary[i];
for (var j: number = i; j > 0 && ary[j - 1] > val; j--) {
ary[j] = ary[j - 1];
}
ary[j] = val;
}
}
/**
*
* @param ary
* @param value
* @returns
*/
public static binarySearch(ary: number[], value: number): number {
let startIndex: number = 0;
let endIndex: number = ary.length;
let sub: number = (startIndex + endIndex) >> 1;
while (startIndex < endIndex) {
if (value <= ary[sub]) endIndex = sub;
else if (value >= ary[sub]) startIndex = sub + 1;
sub = (startIndex + endIndex) >> 1;
}
if (ary[startIndex] == value) return startIndex;
return -1;
}
/**
*
* @param ary
* @param num
*/
public static findElementIndex(ary: any[], num: any): any {
let len: number = ary.length;
for (let i: number = 0; i < len; ++i) {
if (ary[i] == num)
return i;
}
return null;
}
/**
*
* @param ary
*/
public static getMaxElementIndex(ary: number[]): number {
let matchIndex: number = 0;
let len: number = ary.length;
for (let j: number = 1; j < len; j++) {
if (ary[j] > ary[matchIndex])
matchIndex = j;
}
return matchIndex;
}
/**
*
* @param ary
*/
public static getMinElementIndex(ary: number[]): number {
let matchIndex: number = 0;
let len: number = ary.length;
for (let j: number = 1; j < len; j++) {
if (ary[j] < ary[matchIndex])
matchIndex = j;
}
return matchIndex;
}
/**
* "唯一性"
* @param ary
* @returns
*
* @tutorial
* : [1, 2, 2, 3, 4]
* : [1, 2, 3, 4]
*/
public static getUniqueAry(ary: number[]): number[] {
let uAry: number[] = [];
let newAry: number[] = [];
let count = ary.length;
for (let i: number = 0; i < count; ++i) {
let value: number = ary[i];
if (uAry.indexOf(value) == -1) uAry.push(value);
}
count = uAry.length;
for (let i: number = count - 1; i >= 0; --i) {
newAry.unshift(uAry[i]);
}
return newAry;
}
/**
* 2
* A = [1, 2, 3, 4, 6]
* B = [0, 2, 1, 3, 4]
* [6, 0]
* @param aryA
* @param aryB
* @return
*/
public static getDifferAry(aryA: number[], aryB: number[]): number[] {
aryA = this.getUniqueAry(aryA);
aryB = this.getUniqueAry(aryB);
let ary: number[] = aryA.concat(aryB);
let uObj: Object = {};
let newAry: number[] = [];
let count: number = ary.length;
for (let j: number = 0; j < count; ++j) {
if (!uObj[ary[j]]) {
uObj[ary[j]] = {};
uObj[ary[j]].count = 0;
uObj[ary[j]].key = ary[j];
uObj[ary[j]].count++;
} else {
if (uObj[ary[j]] instanceof Object) {
uObj[ary[j]].count++;
}
}
}
for (let i in uObj) {
if (uObj[i].count != 2) {
newAry.unshift(uObj[i].key);
}
}
return newAry;
}
/**
*
* @param array
* @param index1
* @param index2
*/
public static swap(array: any[], index1: number, index2: number): void {
let temp: any = array[index1];
array[index1] = array[index2];
array[index2] = temp;
}
/**
*
* @param ary
*/
public static clearList(ary: any[]): void {
if (!ary) return;
let length: number = ary.length;
for (let i: number = length - 1; i >= 0; i -= 1) {
ary.splice(i, 1);
}
}
/**
*
* @param ary
* @return
*/
public static cloneList(ary: any[]): any[] {
if (!ary) return null;
return ary.slice(0, ary.length);
}
/**
* 2
* @param ary1 1
* @param ary2 2
*/
public static equals(ary1: number[], ary2: number[]): Boolean {
if (ary1 == ary2) return true;
let length: number = ary1.length;
if (length != ary2.length) return false;
while (length--) {
if (ary1[length] != ary2[length])
return false;
}
return true;
}
/**
*
* @param ary
* @param index
* @param value
* @returns
*/
public static insert(ary: any[], index: number, value: any): any {
if (!ary) return null;
let length: number = ary.length;
if (index > length) index = length;
if (index < 0) index = 0;
if (index == length) ary.push(value); //插入最后
else if (index == 0) ary.unshift(value); //插入头
else {
for (let i: number = length - 1; i >= index; i -= 1) {
ary[i + 1] = ary[i];
}
ary[index] = value;
}
return value;
}
/**
* FisherYates shuffle
* @param list
*/
public static shuffle<T>(list: T[]) {
let n = list.length;
while (n > 1) {
n--;
let k = RandomUtils.randint(0, n + 1);
let value: T = list[k];
list[k] = list[n];
list[n] = value;
}
}
/**
* falsetrue
* @param list
* @param item
*/
public static addIfNotPresent<T>(list: T[], item: T) {
if (new linq.List(list).contains(item))
return false;
list.push(item);
return true;
}
/**
*
* @param list
*/
public static lastItem<T>(list: T[]) {
return list[list.length - 1];
}
/**
* !
* @param list
*/
public static randomItem<T>(list: T[]) {
return list[RandomUtils.randint(0, list.length - 1)];
}
/**
* List可以通过ListPool.free放回池中
* @param list
* @param itemCount
*/
public static randomItems<T>(list: T[], itemCount: number){
let set = new Set<T>();
while (set.size != itemCount) {
let item = this.randomItem(list);
if (!set.has(item))
set.add(item);
}
let items = es.ListPool.obtain<T>();
set.forEach(value => items.push(value));
return items;
}
class ArrayUtils {
/**
*
* @param ary
*/
public static bubbleSort(ary: number[]): void {
let isExchange: Boolean = false;
for (let i: number = 0; i < ary.length; i++) {
isExchange = false;
for (let j: number = ary.length - 1; j > i; j--) {
if (ary[j] < ary[j - 1]) {
let temp: number = ary[j];
ary[j] = ary[j - 1];
ary[j - 1] = temp;
isExchange = true;
}
}
if (!isExchange)
break;
}
}
/**
*
* @param ary
*/
public static insertionSort(ary: number[]): void {
let len: number = ary.length;
for (let i: number = 1; i < len; i++) {
let val: number = ary[i];
for (var j: number = i; j > 0 && ary[j - 1] > val; j--) {
ary[j] = ary[j - 1];
}
ary[j] = val;
}
}
/**
*
* @param ary
* @param value
* @returns
*/
public static binarySearch(ary: number[], value: number): number {
let startIndex: number = 0;
let endIndex: number = ary.length;
let sub: number = (startIndex + endIndex) >> 1;
while (startIndex < endIndex) {
if (value <= ary[sub]) endIndex = sub;
else if (value >= ary[sub]) startIndex = sub + 1;
sub = (startIndex + endIndex) >> 1;
}
if (ary[startIndex] == value) return startIndex;
return -1;
}
/**
*
* @param ary
* @param num
*/
public static findElementIndex(ary: any[], num: any): any {
let len: number = ary.length;
for (let i: number = 0; i < len; ++i) {
if (ary[i] == num)
return i;
}
return null;
}
/**
*
* @param ary
*/
public static getMaxElementIndex(ary: number[]): number {
let matchIndex: number = 0;
let len: number = ary.length;
for (let j: number = 1; j < len; j++) {
if (ary[j] > ary[matchIndex])
matchIndex = j;
}
return matchIndex;
}
/**
*
* @param ary
*/
public static getMinElementIndex(ary: number[]): number {
let matchIndex: number = 0;
let len: number = ary.length;
for (let j: number = 1; j < len; j++) {
if (ary[j] < ary[matchIndex])
matchIndex = j;
}
return matchIndex;
}
/**
* "唯一性"
* @param ary
* @returns
*
* @tutorial
* : [1, 2, 2, 3, 4]
* : [1, 2, 3, 4]
*/
public static getUniqueAry(ary: number[]): number[] {
let uAry: number[] = [];
let newAry: number[] = [];
let count = ary.length;
for (let i: number = 0; i < count; ++i) {
let value: number = ary[i];
if (uAry.indexOf(value) == -1) uAry.push(value);
}
count = uAry.length;
for (let i: number = count - 1; i >= 0; --i) {
newAry.unshift(uAry[i]);
}
return newAry;
}
/**
* 2
* A = [1, 2, 3, 4, 6]
* B = [0, 2, 1, 3, 4]
* [6, 0]
* @param aryA
* @param aryB
* @return
*/
public static getDifferAry(aryA: number[], aryB: number[]): number[] {
aryA = this.getUniqueAry(aryA);
aryB = this.getUniqueAry(aryB);
let ary: number[] = aryA.concat(aryB);
let uObj: Object = {};
let newAry: number[] = [];
let count: number = ary.length;
for (let j: number = 0; j < count; ++j) {
if (!uObj[ary[j]]) {
uObj[ary[j]] = {};
uObj[ary[j]].count = 0;
uObj[ary[j]].key = ary[j];
uObj[ary[j]].count++;
} else {
if (uObj[ary[j]] instanceof Object) {
uObj[ary[j]].count++;
}
}
}
for (let i in uObj) {
if (uObj[i].count != 2) {
newAry.unshift(uObj[i].key);
}
}
return newAry;
}
/**
*
* @param array
* @param index1
* @param index2
*/
public static swap(array: any[], index1: number, index2: number): void {
let temp: any = array[index1];
array[index1] = array[index2];
array[index2] = temp;
}
/**
*
* @param ary
*/
public static clearList(ary: any[]): void {
if (!ary) return;
let length: number = ary.length;
for (let i: number = length - 1; i >= 0; i -= 1) {
ary.splice(i, 1);
}
}
/**
*
* @param ary
* @return
*/
public static cloneList(ary: any[]): any[] {
if (!ary) return null;
return ary.slice(0, ary.length);
}
/**
* 2
* @param ary1 1
* @param ary2 2
*/
public static equals(ary1: number[], ary2: number[]): Boolean {
if (ary1 == ary2) return true;
let length: number = ary1.length;
if (length != ary2.length) return false;
while (length--) {
if (ary1[length] != ary2[length])
return false;
}
return true;
}
/**
*
* @param ary
* @param index
* @param value
* @returns
*/
public static insert(ary: any[], index: number, value: any): any {
if (!ary) return null;
let length: number = ary.length;
if (index > length) index = length;
if (index < 0) index = 0;
if (index == length) ary.push(value); //插入最后
else if (index == 0) ary.unshift(value); //插入头
else {
for (let i: number = length - 1; i >= index; i -= 1) {
ary[i + 1] = ary[i];
}
ary[index] = value;
}
return value;
}
/**
* FisherYates shuffle
* @param list
*/
public static shuffle<T>(list: T[]) {
let n = list.length;
while (n > 1) {
n--;
let k = RandomUtils.randint(0, n + 1);
let value: T = list[k];
list[k] = list[n];
list[n] = value;
}
}
/**
* falsetrue
* @param list
* @param item
*/
public static addIfNotPresent<T>(list: T[], item: T) {
if (new linq.List(list).contains(item))
return false;
list.push(item);
return true;
}
/**
*
* @param list
*/
public static lastItem<T>(list: T[]) {
return list[list.length - 1];
}
/**
* !
* @param list
*/
public static randomItem<T>(list: T[]) {
return list[RandomUtils.randint(0, list.length - 1)];
}
/**
* List可以通过ListPool.free放回池中
* @param list
* @param itemCount
*/
public static randomItems<T>(list: T[], itemCount: number){
let set = new Set<T>();
while (set.size != itemCount) {
let item = this.randomItem(list);
if (!set.has(item))
set.add(item);
}
let items = es.ListPool.obtain<T>();
set.forEach(value => items.push(value));
return items;
}
}

View File

@@ -1,134 +1,134 @@
module es{
export class Base64Utils {
private static _keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
/**
* Base64位解析
*/
static get nativeBase64() {
return (typeof (window.atob) === "function");
}
/**
*
* @param input
*/
static decode(input:string): string {
input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");
if (this.nativeBase64) {
return window.atob(input);
} else {
var output: any = [], chr1: number, chr2: number, chr3: number, enc1: number, enc2: number, enc3: number, enc4: number, i: number = 0;
while (i < input.length) {
enc1 = this._keyStr.indexOf(input.charAt(i++));
enc2 = this._keyStr.indexOf(input.charAt(i++));
enc3 = this._keyStr.indexOf(input.charAt(i++));
enc4 = this._keyStr.indexOf(input.charAt(i++));
chr1 = (enc1 << 2) | (enc2 >> 4);
chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
chr3 = ((enc3 & 3) << 6) | enc4;
output.push(String.fromCharCode(chr1));
if (enc3 !== 64) {
output.push(String.fromCharCode(chr2));
}
if (enc4 !== 64) {
output.push(String.fromCharCode(chr3));
}
}
output = output.join("");
return output;
}
}
/**
*
* @param input
*/
static encode(input:string): string {
input = input.replace(/\r\n/g, "\n");
if (this.nativeBase64) {
window.btoa(input);
} else {
var output: any = [], chr1: number, chr2: number, chr3: number, enc1: number, enc2: number, enc3: number, enc4: number, i: number = 0;
while (i < input.length) {
chr1 = input.charCodeAt(i++);
chr2 = input.charCodeAt(i++);
chr3 = input.charCodeAt(i++);
enc1 = chr1 >> 2;
enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
enc4 = chr3 & 63;
if (isNaN(chr2)) {
enc3 = enc4 = 64;
} else if (isNaN(chr3)) {
enc4 = 64;
}
output.push(this._keyStr.charAt(enc1));
output.push(this._keyStr.charAt(enc2));
output.push(this._keyStr.charAt(enc3));
output.push(this._keyStr.charAt(enc4));
}
output = output.join("");
return output;
}
}
/**
* Base64格式数据
* @param input
* @param bytes
*/
static decodeBase64AsArray(input: string, bytes: number): Uint32Array {
bytes = bytes || 1;
var dec = Base64Utils.decode(input), i, j, len;
var ar: Uint32Array = new Uint32Array(dec.length / bytes);
for (i = 0, len = dec.length / bytes; i < len; i++) {
ar[i] = 0;
for (j = bytes - 1; j >= 0; --j) {
ar[i] += dec.charCodeAt((i * bytes) + j) << (j << 3);
}
}
return ar;
}
/**
*
* @param data
* @param decoded
* @param compression
* @private
*/
static decompress(data: string, decoded: any, compression: string): any {
throw new Error("GZIP/ZLIB compressed TMX Tile Map not supported!");
}
/**
* csv数据
* @param input
*/
static decodeCSV(input: string): Array<number> {
var entries: Array<any> = input.replace("\n", "").trim().split(",");
var result:Array<number> = [];
for (var i:number = 0; i < entries.length; i++) {
result.push(+entries[i]);
}
return result;
}
}
}
module es{
export class Base64Utils {
private static _keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
/**
* Base64位解析
*/
static get nativeBase64() {
return (typeof (window.atob) === "function");
}
/**
*
* @param input
*/
static decode(input:string): string {
input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");
if (this.nativeBase64) {
return window.atob(input);
} else {
var output: any = [], chr1: number, chr2: number, chr3: number, enc1: number, enc2: number, enc3: number, enc4: number, i: number = 0;
while (i < input.length) {
enc1 = this._keyStr.indexOf(input.charAt(i++));
enc2 = this._keyStr.indexOf(input.charAt(i++));
enc3 = this._keyStr.indexOf(input.charAt(i++));
enc4 = this._keyStr.indexOf(input.charAt(i++));
chr1 = (enc1 << 2) | (enc2 >> 4);
chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
chr3 = ((enc3 & 3) << 6) | enc4;
output.push(String.fromCharCode(chr1));
if (enc3 !== 64) {
output.push(String.fromCharCode(chr2));
}
if (enc4 !== 64) {
output.push(String.fromCharCode(chr3));
}
}
output = output.join("");
return output;
}
}
/**
*
* @param input
*/
static encode(input:string): string {
input = input.replace(/\r\n/g, "\n");
if (this.nativeBase64) {
window.btoa(input);
} else {
var output: any = [], chr1: number, chr2: number, chr3: number, enc1: number, enc2: number, enc3: number, enc4: number, i: number = 0;
while (i < input.length) {
chr1 = input.charCodeAt(i++);
chr2 = input.charCodeAt(i++);
chr3 = input.charCodeAt(i++);
enc1 = chr1 >> 2;
enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
enc4 = chr3 & 63;
if (isNaN(chr2)) {
enc3 = enc4 = 64;
} else if (isNaN(chr3)) {
enc4 = 64;
}
output.push(this._keyStr.charAt(enc1));
output.push(this._keyStr.charAt(enc2));
output.push(this._keyStr.charAt(enc3));
output.push(this._keyStr.charAt(enc4));
}
output = output.join("");
return output;
}
}
/**
* Base64格式数据
* @param input
* @param bytes
*/
static decodeBase64AsArray(input: string, bytes: number): Uint32Array {
bytes = bytes || 1;
var dec = Base64Utils.decode(input), i, j, len;
var ar: Uint32Array = new Uint32Array(dec.length / bytes);
for (i = 0, len = dec.length / bytes; i < len; i++) {
ar[i] = 0;
for (j = bytes - 1; j >= 0; --j) {
ar[i] += dec.charCodeAt((i * bytes) + j) << (j << 3);
}
}
return ar;
}
/**
*
* @param data
* @param decoded
* @param compression
* @private
*/
static decompress(data: string, decoded: any, compression: string): any {
throw new Error("GZIP/ZLIB compressed TMX Tile Map not supported!");
}
/**
* csv数据
* @param input
*/
static decodeCSV(input: string): Array<number> {
var entries: Array<any> = input.replace("\n", "").trim().split(",");
var result:Array<number> = [];
for (var i:number = 0; i < entries.length; i++) {
result.push(+entries[i]);
}
return result;
}
}
}

View File

@@ -1,133 +1,133 @@
class RandomUtils {
/**
* start stop之间取一个随机整数step指定间隔 start与stop较大的一个
*
* this.randrange(1, 10, 3)
* 1 4 7 , 1010
*
* @param start
* @param stop
* @param step
* @return start < stop, [start, stop)
*
*/
public static randrange(start: number, stop: number, step: number = 1): number {
if (step == 0)
throw new Error('step 不能为 0');
let width: number = stop - start;
if (width == 0)
throw new Error('没有可用的范围(' + start + ',' + stop + ')');
if (width < 0)
width = start - stop;
let n: number = Math.floor((width + step - 1) / step);
return Math.floor(this.random() * n) * step + Math.min(start, stop);
}
/**
* a b直间的随机整数 a b
* @param a
* @param b
* @return [a, b]
*
*/
public static randint(a: number, b: number): number {
a = Math.floor(a);
b = Math.floor(b);
if (a > b)
a++;
else
b++;
return this.randrange(a, b);
}
/**
* a - b之间的随机数 Math.max(a, b)
* @param a
* @param b
* @return a < b, [a, b)
*/
public static randnum(a: number, b: number): number {
return this.random() * (b - a) + a;
}
/**
*
* @param array
* @return
*/
public static shuffle(array: any[]): any[] {
array.sort(this._randomCompare);
return array;
}
/**
*
* @param sequence vectorlength属性
*
* @return
*
*/
public static choice(sequence: any): any {
if (!sequence.hasOwnProperty("length"))
throw new Error('无法对此对象执行此操作');
let index: number = Math.floor(this.random() * sequence.length);
if (sequence instanceof String)
return String(sequence).charAt(index);
else
return sequence[index];
}
/**
* æ ?
* <pre>
* this.sample([1, 2, 3, 4, 5], 3) // Choose 3 elements
* [4, 1, 5]
* </pre>
* @param sequence
* @param num
* @return
*
*/
public static sample(sequence: any[], num: number): any[] {
let len: number = sequence.length;
if (num <= 0 || len < num)
throw new Error("采样数量不够");
let selected: any[] = [];
let indices: any[] = [];
for (let i: number = 0; i < num; i++) {
let index: number = Math.floor(this.random() * len);
while (indices.indexOf(index) >= 0)
index = Math.floor(this.random() * len);
selected.push(sequence[index]);
indices.push(index);
}
return selected;
}
/**
* 0.0 - 1.0 Math.random()
* @return Math.random()
*
*/
public static random(): number {
return Math.random();
}
/**
*
* @param chance
* @return
*/
public static boolean(chance: number = .5): boolean {
return (this.random() < chance) ? true : false;
}
private static _randomCompare(a: Object, b: Object): number {
return (this.random() > .5) ? 1 : -1;
}
class RandomUtils {
/**
* start stop之间取一个随机整数step指定间隔 start与stop较大的一个
*
* this.randrange(1, 10, 3)
* 1 4 7 , 1010
*
* @param start
* @param stop
* @param step
* @return start < stop, [start, stop)
*
*/
public static randrange(start: number, stop: number, step: number = 1): number {
if (step == 0)
throw new Error('step 不能为 0');
let width: number = stop - start;
if (width == 0)
throw new Error('没有可用的范围(' + start + ',' + stop + ')');
if (width < 0)
width = start - stop;
let n: number = Math.floor((width + step - 1) / step);
return Math.floor(this.random() * n) * step + Math.min(start, stop);
}
/**
* a b直间的随机整数 a b
* @param a
* @param b
* @return [a, b]
*
*/
public static randint(a: number, b: number): number {
a = Math.floor(a);
b = Math.floor(b);
if (a > b)
a++;
else
b++;
return this.randrange(a, b);
}
/**
* a - b之间的随机数 Math.max(a, b)
* @param a
* @param b
* @return a < b, [a, b)
*/
public static randnum(a: number, b: number): number {
return this.random() * (b - a) + a;
}
/**
*
* @param array
* @return
*/
public static shuffle(array: any[]): any[] {
array.sort(this._randomCompare);
return array;
}
/**
*
* @param sequence vectorlength属性
*
* @return
*
*/
public static choice(sequence: any): any {
if (!sequence.hasOwnProperty("length"))
throw new Error('无法对此对象执行此操作');
let index: number = Math.floor(this.random() * sequence.length);
if (sequence instanceof String)
return String(sequence).charAt(index);
else
return sequence[index];
}
/**
* æ ?
* <pre>
* this.sample([1, 2, 3, 4, 5], 3) // Choose 3 elements
* [4, 1, 5]
* </pre>
* @param sequence
* @param num
* @return
*
*/
public static sample(sequence: any[], num: number): any[] {
let len: number = sequence.length;
if (num <= 0 || len < num)
throw new Error("采样数量不够");
let selected: any[] = [];
let indices: any[] = [];
for (let i: number = 0; i < num; i++) {
let index: number = Math.floor(this.random() * len);
while (indices.indexOf(index) >= 0)
index = Math.floor(this.random() * len);
selected.push(sequence[index]);
indices.push(index);
}
return selected;
}
/**
* 0.0 - 1.0 Math.random()
* @return Math.random()
*
*/
public static random(): number {
return Math.random();
}
/**
*
* @param chance
* @return
*/
public static boolean(chance: number = .5): boolean {
return (this.random() < chance) ? true : false;
}
private static _randomCompare(a: Object, b: Object): number {
return (this.random() > .5) ? 1 : -1;
}
}

View File

@@ -0,0 +1,220 @@
module es {
export class RectangleExt {
/**
* 获取指定边的位置
* @param rect
* @param edge
*/
public static getSide(rect: Rectangle, edge: Edge) {
switch (edge) {
case Edge.top:
return rect.top;
case Edge.bottom:
return rect.bottom;
case es.Edge.left:
return rect.left;
case Edge.right:
return rect.right;
}
}
/**
* 计算两个矩形的并集。结果将是一个包含其他两个的矩形。
* @param first
* @param point
*/
public static union(first: Rectangle, point: Vector2) {
let rect = new Rectangle(point.x, point.y, 0, 0);
let result = new Rectangle();
result.x = Math.min(first.x, rect.x);
result.y = Math.min(first.y, rect.y);
result.width = Math.max(first.right, rect.right) - result.x;
result.height = Math.max(first.bottom, rect.bottom) - result.y;
return result;
}
public static getHalfRect(rect: Rectangle, edge: Edge) {
switch (edge) {
case Edge.top:
return new Rectangle(rect.x, rect.y, rect.width, rect.height / 2);
case Edge.bottom:
return new Rectangle(rect.x, rect.y + rect.height / 2, rect.width, rect.height / 2);
case Edge.left:
return new Rectangle(rect.x, rect.y, rect.width / 2, rect.height);
case Edge.right:
return new Rectangle(rect.x + rect.width / 2, rect.y, rect.width / 2, rect.height);
}
}
/**
* 获取矩形的一部分,其宽度/高度的大小位于矩形的边缘,但仍然包含在其中。
* @param rect
* @param edge
* @param size
*/
public static getRectEdgePortion(rect: Rectangle, edge: Edge, size: number = 1) {
switch (edge) {
case es.Edge.top:
return new Rectangle(rect.x, rect.y, rect.width, size);
case Edge.bottom:
return new Rectangle(rect.x, rect.y + rect.height - size, rect.width, size);
case Edge.left:
return new Rectangle(rect.x, rect.y, size, rect.height);
case Edge.right:
return new Rectangle(rect.x + rect.width - size, rect.y, size, rect.height);
}
}
public static expandSide(rect: Rectangle, edge: Edge, amount: number) {
amount = Math.abs(amount);
switch (edge) {
case Edge.top:
rect.y -= amount;
rect.height += amount;
break;
case es.Edge.bottom:
rect.height += amount;
break;
case Edge.left:
rect.x -= amount;
rect.width += amount;
break;
case Edge.right:
rect.width += amount;
break;
}
}
public static contract(rect: Rectangle, horizontalAmount, verticalAmount) {
rect.x += horizontalAmount;
rect.y += verticalAmount;
rect.width -= horizontalAmount * 2;
rect.height -= verticalAmount * 2;
}
/**
* 给定多边形的点,计算其边界
* @param points
*/
public static boundsFromPolygonVector(points: Vector2[]) {
// 我们需要找到最小/最大的x/y值。
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.fromMinMaxVector(new Vector2(minX, minY), new Vector2(maxX, maxY));
}
/**
* 创建一个给定最小/最大点(左上角,右下角)的矩形
* @param min
* @param max
*/
public static fromMinMaxVector(min: Vector2, max: Vector2) {
return new Rectangle(min.x, min.y, max.x - min.x, max.y - min.y);
}
/**
* 返回一个跨越当前边界和提供的delta位置的Bounds
* @param rect
* @param deltaX
* @param deltaY
*/
public static getSweptBroadphaseBounds(rect: Rectangle, deltaX: number, deltaY: number){
let broadphasebox = Rectangle.empty;
broadphasebox.x = deltaX > 0 ? rect.x : rect.x + deltaX;
broadphasebox.y = deltaY > 0 ? rect.y : rect.y + deltaY;
broadphasebox.width = deltaX > 0 ? deltaX + rect.width : rect.width - deltaX;
broadphasebox.height = deltaY > 0 ? deltaY + rect.height : rect.height - deltaY;
return broadphasebox;
}
/**
* 如果矩形发生碰撞返回true
* moveX和moveY将返回b1为避免碰撞而必须移动的移动量
* @param rect
* @param other
* @param moveX
* @param moveY
*/
public collisionCheck(rect: Rectangle, other: Rectangle, moveX: Ref<number>, moveY: Ref<number>) {
moveX.value = moveY.value = 0;
let l = other.x - (rect.x + rect.width);
let r = (other.x + other.width) - rect.x;
let t = other.y - (rect.y + rect.height);
let b = (other.y + other.height) - rect.y;
// 检验是否有碰撞
if (l > 0 || r < 0 || t > 0 || b < 0)
return false;
// 求两边的偏移量
moveX.value = Math.abs(l) < r ? l : r;
moveY.value = Math.abs(t) < b ? t : b;
// 只使用最小的偏移量
if (Math.abs(moveX.value) < Math.abs(moveY.value))
moveY.value = 0;
else
moveX.value = 0;
return true;
}
/**
* 计算两个矩形之间有符号的交点深度
* @param rectA
* @param rectB
* @returns 两个相交的矩形之间的重叠量。
* 这些深度值可以是负值,取决于矩形相交的边。
* 这允许调用者确定正确的推送对象的方向,以解决碰撞问题。
* 如果矩形不相交则返回Vector2.zero。
*/
public static getIntersectionDepth(rectA: Rectangle, rectB: Rectangle) {
// 计算半尺寸
let halfWidthA = rectA.width / 2;
let halfHeightA = rectA.height / 2;
let halfWidthB = rectB.width / 2;
let halfHeightB = rectB.height / 2;
// 计算中心
let centerA = new Vector2(rectA.left + halfWidthA, rectA.top + halfHeightA);
let centerB = new Vector2(rectB.left + halfWidthB, rectB.top + halfHeightB);
// 计算当前中心间的距离和最小非相交距离
let distanceX = centerA.x - centerB.x;
let distanceY = centerA.y - centerB.y;
let minDistanceX = halfWidthA + halfWidthB;
let minDistanceY = halfHeightA + halfHeightB;
// 如果我们根本不相交,则返回(00)
if (Math.abs(distanceX) >= minDistanceX || Math.abs(distanceY) >= minDistanceY)
return Vector2.zero;
// 计算并返回交叉点深度
let depthX = distanceX > 0 ? minDistanceX - distanceX : -minDistanceX - distanceX;
let depthY = distanceY > 0 ? minDistanceY - distanceY : -minDistanceY - distanceY;
return new Vector2(depthX, depthY);
}
}
}

View File

@@ -1,9 +1,9 @@
class WebGLUtils {
/**
* webgl context
*/
public static getContext() {
const canvas = document.getElementsByTagName('canvas')[0];
return canvas.getContext('2d');
}
class WebGLUtils {
/**
* webgl context
*/
public static getContext() {
const canvas = document.getElementsByTagName('canvas')[0];
return canvas.getContext('2d');
}
}

View File

@@ -1,4 +1,4 @@
///<reference path="../LinkList.ts" />
///<reference path="../Collections/LinkList.ts" />
module es {
/**
* 类,它可以计算出一个网格,表示从给定的一组遮挡物的原点可以看到哪些区域。使用方法如下。

View File

@@ -1,96 +0,0 @@
module es {
export class RectangleExt {
/**
* 获取指定边的位置
* @param rect
* @param edge
*/
public static getSide(rect: Rectangle, edge: Edge) {
switch (edge) {
case Edge.top:
return rect.top;
case Edge.bottom:
return rect.bottom;
case es.Edge.left:
return rect.left;
case Edge.right:
return rect.right;
}
}
/**
* 计算两个矩形的并集。结果将是一个包含其他两个的矩形。
* @param first
* @param point
*/
public static union(first: Rectangle, point: Vector2) {
let rect = new Rectangle(point.x, point.y, 0, 0);
let result = new Rectangle();
result.x = Math.min(first.x, rect.x);
result.y = Math.min(first.y, rect.y);
result.width = Math.max(first.right, rect.right) - result.x;
result.height = Math.max(first.bottom, rect.bottom) - result.y;
return result;
}
public static getHalfRect(rect: Rectangle, edge: Edge) {
switch (edge) {
case Edge.top:
return new Rectangle(rect.x, rect.y, rect.width, rect.height / 2);
case Edge.bottom:
return new Rectangle(rect.x, rect.y + rect.height / 2, rect.width, rect.height / 2);
case Edge.left:
return new Rectangle(rect.x, rect.y, rect.width / 2, rect.height);
case Edge.right:
return new Rectangle(rect.x + rect.width / 2, rect.y, rect.width / 2, rect.height);
}
}
/**
* 获取矩形的一部分,其宽度/高度的大小位于矩形的边缘,但仍然包含在其中。
* @param rect
* @param edge
* @param size
*/
public static getRectEdgePortion(rect: Rectangle, edge: Edge, size: number = 1) {
switch (edge) {
case es.Edge.top:
return new Rectangle(rect.x, rect.y, rect.width, size);
case Edge.bottom:
return new Rectangle(rect.x, rect.y + rect.height - size, rect.width, size);
case Edge.left:
return new Rectangle(rect.x, rect.y, size, rect.height);
case Edge.right:
return new Rectangle(rect.x + rect.width - size, rect.y, size, rect.height);
}
}
public static expandSide(rect: Rectangle, edge: Edge, amount: number) {
amount = Math.abs(amount);
switch (edge) {
case Edge.top:
rect.y -= amount;
rect.height += amount;
break;
case es.Edge.bottom:
rect.height += amount;
break;
case Edge.left:
rect.x -= amount;
rect.width += amount;
break;
case Edge.right:
rect.width += amount;
break;
}
}
public static contract(rect: Rectangle, horizontalAmount, verticalAmount) {
rect.x += horizontalAmount;
rect.y += verticalAmount;
rect.width -= horizontalAmount * 2;
rect.height -= verticalAmount * 2;
}
}
}