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:
213
assets/scripts/controller/PlayerController.ts
Normal file
213
assets/scripts/controller/PlayerController.ts
Normal file
@@ -0,0 +1,213 @@
|
||||
import { _decorator, Vec3 } from 'cc';
|
||||
import { Direction, GameState, GridType, Skin } from '../core/Define';
|
||||
import { EventManager, EventType } from '../core/EventManager';
|
||||
import { JsBridge } from '../bridge/JsBridge';
|
||||
import { GameManager } from '../manager/GameManager';
|
||||
import { Movement } from '../gameplay/Movement';
|
||||
import { VehicleController } from './VehicleController';
|
||||
import { VisualAssets } from '../visual/VisualAssets';
|
||||
|
||||
const { ccclass } = _decorator;
|
||||
|
||||
export interface ExternalData {
|
||||
position: { x: number; y: number; z: number };
|
||||
gridType: number;
|
||||
direction: string;
|
||||
}
|
||||
|
||||
export interface ExternalDataList {
|
||||
direction: number;
|
||||
externalDatas: ExternalData[];
|
||||
}
|
||||
|
||||
export interface ExternalResult {
|
||||
isWin: boolean;
|
||||
stepNum: number;
|
||||
direction: number;
|
||||
isInputEnd: boolean;
|
||||
}
|
||||
|
||||
@ccclass('PlayerController')
|
||||
export class PlayerController extends Movement {
|
||||
coins = 0;
|
||||
private vehicle: VehicleController | null = null;
|
||||
private sendFinally = false;
|
||||
|
||||
onLoad() {
|
||||
this.moverRole = 'player';
|
||||
EventManager.register(EventType.LevelInit, this.onLevelInit);
|
||||
EventManager.register(EventType.InputEnd, this.onInputEnd);
|
||||
this.coins = 0;
|
||||
}
|
||||
|
||||
onDestroy() {
|
||||
EventManager.remove(EventType.LevelInit, this.onLevelInit);
|
||||
EventManager.remove(EventType.InputEnd, this.onInputEnd);
|
||||
}
|
||||
|
||||
start() {
|
||||
super.start();
|
||||
VisualAssets.applyPlayerSprite(this.node, this.direction);
|
||||
if (this.node.name === 'Player' && GameManager.instance) {
|
||||
this.callChangeSkin(GameManager.instance.playerSkin);
|
||||
}
|
||||
}
|
||||
|
||||
override setDirection(dir: Direction) {
|
||||
super.setDirection(dir);
|
||||
VisualAssets.applyPlayerSprite(this.node, dir);
|
||||
}
|
||||
|
||||
private onLevelInit = () => {
|
||||
this.checkRide();
|
||||
};
|
||||
|
||||
private onInputEnd = () => {
|
||||
this.externalCallResult(false);
|
||||
};
|
||||
|
||||
protected onMoveNextSet(isJump: boolean) {
|
||||
if (isJump && this.targetGridType === GridType.Jump) {
|
||||
const p = this.node.worldPosition.clone();
|
||||
p.y += 0.15;
|
||||
this.targetPosition.set(p);
|
||||
}
|
||||
}
|
||||
|
||||
onMoving() {
|
||||
if (this.targetGridType === GridType.None && this.vehicle && !Movement.callEach) {
|
||||
this.vehicle.setPosition(this.node.worldPosition);
|
||||
}
|
||||
}
|
||||
|
||||
protected onMoveFail(isJump: boolean) {
|
||||
this.externalCallResult(false);
|
||||
const gm = GameManager.instance!;
|
||||
if (gm.multMode) {
|
||||
const other = gm.findNodeByName(this.node.name === 'Player' ? 'Enemy' : 'Player');
|
||||
other?.getComponent(PlayerController)?.externalCallResult(true);
|
||||
}
|
||||
console.log(`${this.node.name} 无法移动`, isJump);
|
||||
}
|
||||
|
||||
protected onMoveToTarget() {
|
||||
if (this.curGrid === GridType.Ride) {
|
||||
const obj = GameManager.instance!.getGameObject(this.node.worldPosition);
|
||||
if (obj) {
|
||||
this.vehicle = obj.getComponent(VehicleController);
|
||||
this.vehicle?.setPlayer(this);
|
||||
if (this.vehicle) this.vehicle.setDirection(this.direction);
|
||||
}
|
||||
} else if (this.curGrid !== GridType.None && this.vehicle) {
|
||||
this.vehicle.setPlayer(null);
|
||||
this.vehicle = null;
|
||||
}
|
||||
if (this.vehicle) {
|
||||
this.vehicle.setPosition(this.node.worldPosition);
|
||||
GameManager.instance!.removeObj(this.lastPosition);
|
||||
GameManager.instance!.addObj(this.node.worldPosition, GridType.Ride, this.vehicle.node);
|
||||
}
|
||||
this.externalCall();
|
||||
}
|
||||
|
||||
callChangeSkin(n: number) {
|
||||
if (n < 0 || n > Skin.sanxing) return;
|
||||
if (GameManager.instance) GameManager.instance.playerSkin = n as Skin;
|
||||
}
|
||||
|
||||
callPlayerInfo() {
|
||||
this.externalCall();
|
||||
}
|
||||
|
||||
setName(name: string) {
|
||||
this.vehicle?.setName(name);
|
||||
}
|
||||
|
||||
getCoinsNum() {
|
||||
JsBridge.call('coinsData', JSON.stringify({ coinsNum: this.coins, gameObjectName: this.node.name }));
|
||||
}
|
||||
|
||||
addCoins() {
|
||||
this.coins++;
|
||||
}
|
||||
|
||||
setPosition(pos: Vec3) {
|
||||
this.node.setPosition(pos);
|
||||
}
|
||||
|
||||
/** 供 VehicleController 同步 */
|
||||
syncFromVehicle(targetGridType: GridType, isJump: boolean) {
|
||||
this.targetGridType = targetGridType;
|
||||
this.onMoveNextSet(isJump);
|
||||
}
|
||||
|
||||
syncMoveToTargetFromVehicle() {
|
||||
this.onMoveToTarget();
|
||||
}
|
||||
|
||||
externalCall() {
|
||||
const gm = GameManager.instance!;
|
||||
const list: ExternalDataList = { direction: this.direction, externalDatas: [] };
|
||||
const self = gm.worldToCell(this.node.worldPosition);
|
||||
list.externalDatas.push({
|
||||
position: { x: self.x, y: self.y, z: 0 },
|
||||
gridType: this.curGrid,
|
||||
direction: 'self',
|
||||
});
|
||||
for (let d = Direction.North; d <= Direction.West; d++) {
|
||||
const wp = gm.nextGridPosition(this.node.worldPosition, d);
|
||||
const cell = gm.worldToCell(wp);
|
||||
list.externalDatas.push({
|
||||
position: { x: cell.x, y: cell.y, z: 0 },
|
||||
gridType: gm.calculateNextGridType(this.node.worldPosition, d),
|
||||
direction: gm.getRelativePosition(this.direction, d),
|
||||
});
|
||||
}
|
||||
const json = JSON.stringify(list);
|
||||
if (gm.multMode) JsBridge.call(`process${this.node.name}`, json);
|
||||
else JsBridge.call('processData', json);
|
||||
}
|
||||
|
||||
externalCallResult(isWin: boolean) {
|
||||
const gm = GameManager.instance!;
|
||||
if (isWin && (this.node.name === 'Player' || this.node.name === gm.multPlayerRole)) {
|
||||
/* success audio */
|
||||
} else if (!isWin && (this.node.name === 'Player' || this.node.name === gm.multPlayerRole)) {
|
||||
/* fail audio */
|
||||
}
|
||||
let myStep = gm.stepNum;
|
||||
if (gm.multMode) {
|
||||
switch (gm.multPlayerRole) {
|
||||
case 'PlayerA1': myStep = gm.stepA1Num; break;
|
||||
case 'PlayerA2': myStep = gm.stepA2Num; break;
|
||||
case 'PlayerA3': myStep = gm.stepA3Num; break;
|
||||
case 'PlayerB1': myStep = gm.stepB1Num; break;
|
||||
case 'PlayerB2': myStep = gm.stepB2Num; break;
|
||||
case 'PlayerB3': myStep = gm.stepB3Num; break;
|
||||
}
|
||||
}
|
||||
if ((this.node.name === 'Player' || this.node.name === gm.multPlayerRole) && !this.sendFinally) {
|
||||
const payload: ExternalResult = {
|
||||
isWin,
|
||||
stepNum: myStep,
|
||||
direction: this.direction,
|
||||
isInputEnd: gm.isInputEnd,
|
||||
};
|
||||
JsBridge.call('externalResult', JSON.stringify(payload));
|
||||
this.sendFinally = true;
|
||||
}
|
||||
if (gm.gameState !== GameState.Run) return;
|
||||
gm.setGameState(isWin ? GameState.ResultWin : GameState.ResultFail);
|
||||
}
|
||||
|
||||
private checkRide() {
|
||||
if (this.curGrid === GridType.Ride) {
|
||||
const obj = GameManager.instance!.getGameObject(this.node.worldPosition);
|
||||
if (obj) {
|
||||
this.vehicle = obj.getComponent(VehicleController);
|
||||
this.vehicle?.setDirection(this.direction);
|
||||
this.vehicle?.setPlayer(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user