Initial Cocos Creator port of main-site Unity WebGL game.
Includes core gameplay, 600 exported levels, visual assets, web bridge, and bootstrap scene. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
178
assets/scripts/gameplay/Movement.ts
Normal file
178
assets/scripts/gameplay/Movement.ts
Normal file
@@ -0,0 +1,178 @@
|
||||
import { _decorator, Component, Vec3 } from 'cc';
|
||||
import {
|
||||
Direction, GameState, GridType, MoveState, MoverRole,
|
||||
addDirection, getMoveCondition, lookupMove,
|
||||
} from '../core/Define';
|
||||
import { GameManager } from '../manager/GameManager';
|
||||
|
||||
const { ccclass, property } = _decorator;
|
||||
|
||||
@ccclass('Movement')
|
||||
export class Movement extends Component {
|
||||
@property
|
||||
moveSpeed = 4;
|
||||
|
||||
direction: Direction = Direction.North;
|
||||
moveState: MoveState = MoveState.Idle;
|
||||
moverRole: MoverRole = 'player';
|
||||
|
||||
protected targetPosition = new Vec3();
|
||||
protected targetGridType: GridType = GridType.None;
|
||||
protected lastPosition = new Vec3();
|
||||
protected step = 0;
|
||||
|
||||
private moveWait = false;
|
||||
private queue: Promise<void> = Promise.resolve();
|
||||
static callEach = false;
|
||||
|
||||
get curGrid(): GridType {
|
||||
return GameManager.instance!.calculateGridType(this.node.position);
|
||||
}
|
||||
get nextGrid(): GridType {
|
||||
return GameManager.instance!.calculateNextGridType(this.node.position, this.direction);
|
||||
}
|
||||
get lastGrid(): GridType {
|
||||
return GameManager.instance!.calculateLastGridType(this.node.position, this.direction);
|
||||
}
|
||||
get isFront(): boolean {
|
||||
return this.direction === Direction.South || this.direction === Direction.East;
|
||||
}
|
||||
|
||||
start() {
|
||||
this.setDirection(this.direction);
|
||||
}
|
||||
|
||||
update(dt: number) {
|
||||
if (this.moveState !== MoveState.Moving) return;
|
||||
const pos = this.node.position;
|
||||
const next = new Vec3();
|
||||
Vec3.moveTowards(next, pos, this.targetPosition, this.moveSpeed * dt);
|
||||
this.node.setPosition(next);
|
||||
this.onMoving();
|
||||
if (Vec3.distance(next, this.targetPosition) < 0.01) {
|
||||
this.node.setPosition(this.targetPosition);
|
||||
this.moveState = MoveState.Idle;
|
||||
this.moveWait = false;
|
||||
this.onMoveToTarget();
|
||||
}
|
||||
}
|
||||
|
||||
setDirection(dir: Direction) {
|
||||
this.direction = dir;
|
||||
}
|
||||
|
||||
protected onMoving() {}
|
||||
protected onMoveToTarget() {}
|
||||
protected onMoveNextSet(_isJump: boolean) {}
|
||||
protected onMoveFail(_isJump: boolean) {}
|
||||
protected playMoveAnim() {}
|
||||
|
||||
private moveNextCheck(isJump: boolean, toFront: boolean): number {
|
||||
const gm = GameManager.instance!;
|
||||
const dir = toFront ? this.direction : addDirection(this.direction, 2);
|
||||
const targetTmp = gm.nextGridPosition(this.node.position, dir);
|
||||
const targetType = gm.calculateGridType(targetTmp);
|
||||
const table = getMoveCondition(gm.multMode);
|
||||
const nextG = toFront ? this.nextGrid : this.lastGrid;
|
||||
const v = lookupMove(table, this.moverRole, this.curGrid, nextG, isJump);
|
||||
if (v !== undefined) {
|
||||
if (v === 1) {
|
||||
if (gm.multMode) {
|
||||
const nextCell = gm.worldToCell(targetTmp);
|
||||
for (const n of ['PlayerA1', 'PlayerA2', 'PlayerA3', 'PlayerB1', 'PlayerB2', 'PlayerB3']) {
|
||||
const p = gm.findNodeByName(n);
|
||||
if (p) {
|
||||
const c = gm.worldToCell(p.worldPosition);
|
||||
if (c.x === nextCell.x && c.y === nextCell.y) return 0;
|
||||
}
|
||||
}
|
||||
if (nextG === GridType.Ride) {
|
||||
const ride = gm.getGameObject(targetTmp);
|
||||
const expect = this.node.name.replace('Player', 'Vehicle');
|
||||
if (ride && ride.name !== expect) return 0;
|
||||
}
|
||||
}
|
||||
this.targetPosition.set(targetTmp);
|
||||
this.targetGridType = targetType;
|
||||
}
|
||||
return v;
|
||||
}
|
||||
return gm.multMode ? 0 : -1;
|
||||
}
|
||||
|
||||
private enqueue(fn: () => Promise<void>) {
|
||||
this.queue = this.queue.then(fn).catch((e) => console.error(e));
|
||||
}
|
||||
|
||||
private waitUntil(cond: () => boolean): Promise<void> {
|
||||
return new Promise((resolve) => {
|
||||
const tick = () => {
|
||||
if (cond()) resolve();
|
||||
else requestAnimationFrame(tick);
|
||||
};
|
||||
tick();
|
||||
});
|
||||
}
|
||||
|
||||
private async moveCoroutine(n: number, isJump: boolean) {
|
||||
await this.waitUntil(() => !this.moveWait);
|
||||
const toFront = n > 0;
|
||||
this.step = Math.abs(n);
|
||||
const gm = GameManager.instance!;
|
||||
while (this.step > 0 && gm.gameState === GameState.Run) {
|
||||
this.step--;
|
||||
const r = this.moveNextCheck(isJump, toFront);
|
||||
if (r === -1) {
|
||||
this.onMoveFail(isJump);
|
||||
return;
|
||||
}
|
||||
if (r === 1) {
|
||||
this.moveWait = true;
|
||||
this.lastPosition.set(this.node.position);
|
||||
this.moveState = MoveState.Moving;
|
||||
this.onMoveNextSet(isJump);
|
||||
await this.waitUntil(() => !this.moveWait);
|
||||
} else {
|
||||
this.playMoveAnim();
|
||||
this.moveState = MoveState.Moving;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private async rotateCoroutine(n: number) {
|
||||
await this.waitUntil(() => !this.moveWait);
|
||||
this.moveWait = true;
|
||||
this.setDirection(addDirection(this.direction, n));
|
||||
this.moveWait = false;
|
||||
this.onMoveToTarget();
|
||||
}
|
||||
|
||||
protected jsCallCheck(n: number): boolean {
|
||||
const gm = GameManager.instance!;
|
||||
const name = this.node.name;
|
||||
if (name === 'Player' || name === 'Vehicle') return gm.jsCallCheck(n);
|
||||
if (gm.multMode) return gm.jsCallCheckMultMode(n, name);
|
||||
return false;
|
||||
}
|
||||
|
||||
callMove(n: number) {
|
||||
if (!this.jsCallCheck(n)) return;
|
||||
this.enqueue(() => this.moveCoroutine(n, false));
|
||||
}
|
||||
|
||||
callRotateLeft(n: number) {
|
||||
if (!this.jsCallCheck(n)) return;
|
||||
this.enqueue(() => this.rotateCoroutine(-n));
|
||||
}
|
||||
|
||||
callRotateRight(n: number) {
|
||||
if (!this.jsCallCheck(n)) return;
|
||||
this.enqueue(() => this.rotateCoroutine(n));
|
||||
}
|
||||
|
||||
callJump() {
|
||||
if (this.moverRole !== 'player') return;
|
||||
if (!this.jsCallCheck(1)) return;
|
||||
this.enqueue(() => this.moveCoroutine(1, true));
|
||||
}
|
||||
}
|
||||
9
assets/scripts/gameplay/Movement.ts.meta
Normal file
9
assets/scripts/gameplay/Movement.ts.meta
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"ver": "4.0.24",
|
||||
"importer": "typescript",
|
||||
"imported": true,
|
||||
"uuid": "5fdb4109-5d6a-4002-90f9-a7568122ac93",
|
||||
"files": [],
|
||||
"subMetas": {},
|
||||
"userData": {}
|
||||
}
|
||||
Reference in New Issue
Block a user