[add] Engine
This commit is contained in:
192
assets/Script/Engine/Utils/Number/NumberEx.ts
Normal file
192
assets/Script/Engine/Utils/Number/NumberEx.ts
Normal file
@@ -0,0 +1,192 @@
|
||||
import { CoroutineV2 } from "../../CatanEngine/CoroutineV2/CoroutineV2";
|
||||
import { RandomEx } from "./RandomEx";
|
||||
|
||||
export module NumberEx {
|
||||
/**
|
||||
* 數字滾動
|
||||
* @param startNum
|
||||
* @param endNum
|
||||
* @param callbackfn
|
||||
* @param chabgeRate
|
||||
*/
|
||||
export function* ChangeScore(startNum: number, endNum: number, callbackfn: (num: number) => void, sec: number) {
|
||||
let fps = 30;
|
||||
let waitTime = 0.03;
|
||||
let changeRate = sec * fps; // -1為了讓changeRate數字能混亂點
|
||||
changeRate = changeRate - 1 <= 0 ? changeRate : changeRate - 1;
|
||||
changeRate = 1 / changeRate;
|
||||
let diff = endNum - startNum;
|
||||
let isIncrease = endNum >= startNum;
|
||||
let tempScore = startNum;
|
||||
let counter = 0;
|
||||
//let randomRate = 0;
|
||||
while (true) {
|
||||
if (endNum != tempScore) {
|
||||
/*if (counter % 2 == 0) {
|
||||
if (isIncrease) {
|
||||
randomRate = RandomEx.GetFloat(0, diff * changeRate).ExToNumFloorDecimal(2);
|
||||
} else {
|
||||
randomRate = RandomEx.GetFloat(0, -diff * changeRate).ExToNumFloorDecimal(2);
|
||||
}
|
||||
} else {
|
||||
randomRate = -randomRate;
|
||||
}*/
|
||||
tempScore += diff * changeRate //+ randomRate;
|
||||
// 遞增
|
||||
if (isIncrease && tempScore > endNum) {
|
||||
tempScore = endNum;
|
||||
}
|
||||
// 遞減
|
||||
if (!isIncrease && tempScore < endNum) {
|
||||
tempScore = endNum;
|
||||
}
|
||||
callbackfn(tempScore.ExToInt());
|
||||
// yield null;
|
||||
counter++;
|
||||
yield CoroutineV2.WaitTime(waitTime);
|
||||
}
|
||||
else {
|
||||
callbackfn(endNum);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 數字跳動
|
||||
* @param minNum 起始數字
|
||||
* @param maxNum 最終數字
|
||||
* @param callbackfn callbackfn
|
||||
* @param sec 時間
|
||||
*/
|
||||
export function* BeatScore(minNum: number, maxNum: number, endNum: number, callbackfn: (num: number) => void, sec: number): IterableIterator<any> {
|
||||
let fps: number = 13;
|
||||
let waitTime: number = 0.07;
|
||||
let changeRate: number = sec * fps; // -1為了讓changeRate數字能混亂點
|
||||
changeRate = changeRate - 1 <= 0 ? changeRate : changeRate - 1;
|
||||
changeRate = 1 / changeRate;
|
||||
let diff: number = maxNum - minNum;
|
||||
let isIncrease: boolean = maxNum >= minNum;
|
||||
let tempScore: number = minNum;
|
||||
let counter: number = 0;
|
||||
let randomRate: number = 0;
|
||||
let lastNum: number = minNum;
|
||||
let nowNum: number = minNum;
|
||||
while (true) {
|
||||
if (maxNum !== tempScore) {
|
||||
if (counter % 2 === 0) {
|
||||
if (isIncrease) {
|
||||
randomRate = RandomEx.GetFloat(0, diff * changeRate).ExToNumFloorDecimal(2);
|
||||
} else {
|
||||
randomRate = RandomEx.GetFloat(0, -diff * changeRate).ExToNumFloorDecimal(2);
|
||||
}
|
||||
} else {
|
||||
randomRate = -randomRate;
|
||||
}
|
||||
|
||||
tempScore += diff * changeRate + randomRate;
|
||||
// 遞增
|
||||
if (isIncrease && tempScore > maxNum) {
|
||||
tempScore = maxNum;
|
||||
}
|
||||
// 遞減
|
||||
if (!isIncrease && tempScore < maxNum) {
|
||||
tempScore = maxNum;
|
||||
}
|
||||
while (nowNum === lastNum) {
|
||||
nowNum = RandomEx.GetInt(minNum, maxNum + 1);
|
||||
}
|
||||
lastNum = nowNum;
|
||||
callbackfn(nowNum);
|
||||
// yield null;
|
||||
counter++;
|
||||
yield CoroutineV2.WaitTime(waitTime);
|
||||
} else {
|
||||
callbackfn(endNum);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 检测数字是否越界,如果越界给出提示
|
||||
* @param {*number} num 输入数
|
||||
*/
|
||||
function checkBoundary(num: number) {
|
||||
if (_boundaryCheckingState) {
|
||||
if (num > Number.MAX_SAFE_INTEGER || num < Number.MIN_SAFE_INTEGER) {
|
||||
console.warn(`${num} is beyond boundary when transfer to integer, the results may not be accurate`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 精确乘法
|
||||
*/
|
||||
export function times(num1: number, num2: number, ...others: number[]): number {
|
||||
if (others.length > 0) {
|
||||
return times(times(num1, num2), others[0], ...others.slice(1));
|
||||
}
|
||||
const num1Changed = num1.Float2Fixed();
|
||||
const num2Changed = num2.Float2Fixed();
|
||||
const baseNum = num1.DigitLength() + num2.DigitLength();
|
||||
const leftValue = num1Changed * num2Changed;
|
||||
|
||||
checkBoundary(leftValue);
|
||||
|
||||
return leftValue / Math.pow(10, baseNum);
|
||||
}
|
||||
|
||||
/**
|
||||
* 精确加法
|
||||
*/
|
||||
export function plus(num1: number, num2: number, ...others: number[]): number {
|
||||
if (others.length > 0) {
|
||||
return plus(plus(num1, num2), others[0], ...others.slice(1));
|
||||
}
|
||||
const baseNum = Math.pow(10, Math.max(num1.DigitLength(), num2.DigitLength()));
|
||||
return (times(num1, baseNum) + times(num2, baseNum)) / baseNum;
|
||||
}
|
||||
|
||||
/**
|
||||
* 精确减法
|
||||
*/
|
||||
export function minus(num1: number, num2: number, ...others: number[]): number {
|
||||
if (others.length > 0) {
|
||||
return minus(minus(num1, num2), others[0], ...others.slice(1));
|
||||
}
|
||||
const baseNum = Math.pow(10, Math.max(num1.DigitLength(), num2.DigitLength()));
|
||||
return (times(num1, baseNum) - times(num2, baseNum)) / baseNum;
|
||||
}
|
||||
|
||||
/**
|
||||
* 精确除法
|
||||
*/
|
||||
export function divide(num1: number, num2: number, ...others: number[]): number {
|
||||
if (others.length > 0) {
|
||||
return divide(divide(num1, num2), others[0], ...others.slice(1));
|
||||
}
|
||||
const num1Changed = num1.Float2Fixed();
|
||||
const num2Changed = num2.Float2Fixed();
|
||||
checkBoundary(num1Changed);
|
||||
checkBoundary(num2Changed);
|
||||
return times((num1Changed / num2Changed), Math.pow(10, num2.DigitLength() - num1.DigitLength()));
|
||||
}
|
||||
|
||||
/**
|
||||
* 四舍五入
|
||||
*/
|
||||
export function round(num: number, ratio: number): number {
|
||||
const base = Math.pow(10, ratio);
|
||||
return divide(Math.round(times(num, base)), base);
|
||||
}
|
||||
|
||||
let _boundaryCheckingState = false;
|
||||
/**
|
||||
* 是否进行边界检查
|
||||
* @param flag 标记开关,true 为开启,false 为关闭
|
||||
*/
|
||||
function enableBoundaryChecking(flag = true) {
|
||||
_boundaryCheckingState = flag;
|
||||
}
|
||||
}
|
10
assets/Script/Engine/Utils/Number/NumberEx.ts.meta
Normal file
10
assets/Script/Engine/Utils/Number/NumberEx.ts.meta
Normal file
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"ver": "1.1.0",
|
||||
"uuid": "363f5f7f-0623-4013-8571-0bb5c1dc95e6",
|
||||
"importer": "typescript",
|
||||
"isPlugin": false,
|
||||
"loadPluginInWeb": true,
|
||||
"loadPluginInNative": true,
|
||||
"loadPluginInEditor": false,
|
||||
"subMetas": {}
|
||||
}
|
90
assets/Script/Engine/Utils/Number/RandomEx.ts
Normal file
90
assets/Script/Engine/Utils/Number/RandomEx.ts
Normal file
@@ -0,0 +1,90 @@
|
||||
|
||||
export module RandomEx {
|
||||
|
||||
/**
|
||||
* 取得隨機布林值
|
||||
*/
|
||||
export function GetBool() {
|
||||
return GetInt() >= 0;
|
||||
}
|
||||
/**
|
||||
* 取得隨機整數(回傳min ~ max - 1)
|
||||
* @param min
|
||||
* @param max
|
||||
*/
|
||||
export function GetInt(min: number = Number.MIN_VALUE, max: number = Number.MAX_VALUE): number {
|
||||
return Math.floor(Math.random() * (max - min)) + min;
|
||||
}
|
||||
/**
|
||||
* 取得隨機小數
|
||||
* @param min
|
||||
* @param max
|
||||
*/
|
||||
export function GetFloat(min: number = Number.MIN_VALUE, max: number = Number.MAX_VALUE): number {
|
||||
return Math.random() * (max - min) + min;
|
||||
}
|
||||
/**
|
||||
* 隨機取得複數個不重複回傳
|
||||
* @param num 取得數量
|
||||
* @param items 陣列
|
||||
*/
|
||||
export function GetMultiNoRepeat(num: number, items: any[]): any[] {
|
||||
let result: any[] = [];
|
||||
for (let i: number = 0; i < num; i++) {
|
||||
let ran: number = Math.floor(Math.random() * items.length);
|
||||
let item = items.splice(ran, 1)[0];
|
||||
if (result.indexOf(item) == -1) {
|
||||
result.push(item);
|
||||
}
|
||||
};
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根據權重取得複數個不重複回傳
|
||||
* @param prize 獎項
|
||||
* @param weights 機率
|
||||
* @param count 數量
|
||||
*/
|
||||
export function GetMultiNoRepeatByWeight(prize: any[], weights: number[] = null, count: number = 1): any[] {
|
||||
if (weights === null) {
|
||||
weights = [];
|
||||
for (let i: number = 0; i < prize.length; i++) {
|
||||
weights.push(1);
|
||||
}
|
||||
}
|
||||
let target: any[] = [];
|
||||
for (let i: number = 0; i < count; i++) {
|
||||
let results: number[] = RandomEx.GetPrizeByWeight(prize, weights);
|
||||
prize.splice(results[0], 1);
|
||||
weights.splice(results[0], 1);
|
||||
target.push(results[1]);
|
||||
}
|
||||
return target;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 根據權重隨機取值
|
||||
* @param prize 獎項
|
||||
* @param weights 機率
|
||||
*/
|
||||
export function GetPrizeByWeight(prize: any[], weights: number[]): any[] {
|
||||
if (prize.length !== weights.length) {
|
||||
console.error(`GetWeight error -> prize.length:${prize.length} !== weights.length:${weights.length}`);
|
||||
return null;
|
||||
}
|
||||
let totalWeight: number = 0;
|
||||
for (let i: number = 0; i < weights.length; i++) {
|
||||
totalWeight += weights[i];
|
||||
}
|
||||
let random: number = RandomEx.GetInt(0, totalWeight) + 1;
|
||||
let nowWeight: number = weights[0];
|
||||
for (let i: number = 0; i < weights.length; i++) {
|
||||
if (nowWeight >= random) {
|
||||
return [i, prize[i]];
|
||||
}
|
||||
nowWeight += weights[i + 1];
|
||||
}
|
||||
}
|
||||
}
|
10
assets/Script/Engine/Utils/Number/RandomEx.ts.meta
Normal file
10
assets/Script/Engine/Utils/Number/RandomEx.ts.meta
Normal file
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"ver": "1.1.0",
|
||||
"uuid": "ba4dee5b-ca5b-4435-a068-c4f5dd832bab",
|
||||
"importer": "typescript",
|
||||
"isPlugin": false,
|
||||
"loadPluginInWeb": true,
|
||||
"loadPluginInNative": true,
|
||||
"loadPluginInEditor": false,
|
||||
"subMetas": {}
|
||||
}
|
Reference in New Issue
Block a user