cocos基础工程
This commit is contained in:
88
client-cocos/assets/scripts/Modules/Pinball/Core/EventBus.ts
Normal file
88
client-cocos/assets/scripts/Modules/Pinball/Core/EventBus.ts
Normal file
@@ -0,0 +1,88 @@
|
||||
/**
|
||||
* 简单的事件总线实现
|
||||
* 用于 Pinball 模块内部组件间通信
|
||||
*/
|
||||
|
||||
export type EventCallback<T = any> = (data: T) => void;
|
||||
|
||||
export class EventBus {
|
||||
private static instance: EventBus;
|
||||
private events: Map<string, EventCallback[]> = new Map();
|
||||
|
||||
private constructor() { }
|
||||
|
||||
/**
|
||||
* 获取单例实例
|
||||
*/
|
||||
static getInstance(): EventBus {
|
||||
if (!EventBus.instance) {
|
||||
EventBus.instance = new EventBus();
|
||||
}
|
||||
return EventBus.instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* 订阅事件
|
||||
*/
|
||||
on<T = any>(event: string, callback: EventCallback<T>): void {
|
||||
if (!this.events.has(event)) {
|
||||
this.events.set(event, []);
|
||||
}
|
||||
this.events.get(event)!.push(callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* 取消订阅事件
|
||||
*/
|
||||
off<T = any>(event: string, callback: EventCallback<T>): void {
|
||||
const callbacks = this.events.get(event);
|
||||
if (callbacks) {
|
||||
const index = callbacks.indexOf(callback);
|
||||
if (index > -1) {
|
||||
callbacks.splice(index, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 发射事件
|
||||
*/
|
||||
emit<T = any>(event: string, data?: T): void {
|
||||
const callbacks = this.events.get(event);
|
||||
if (callbacks) {
|
||||
callbacks.forEach(callback => {
|
||||
try {
|
||||
callback(data);
|
||||
} catch (error) {
|
||||
console.error(`Error in event callback for event '${event}':`, error);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 只订阅一次事件
|
||||
*/
|
||||
once<T = any>(event: string, callback: EventCallback<T>): void {
|
||||
const onceCallback: EventCallback<T> = (data: T) => {
|
||||
callback(data);
|
||||
this.off(event, onceCallback);
|
||||
};
|
||||
this.on(event, onceCallback);
|
||||
}
|
||||
|
||||
/**
|
||||
* 清理所有事件监听器
|
||||
*/
|
||||
clear(): void {
|
||||
this.events.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取事件监听器数量
|
||||
*/
|
||||
listenerCount(event: string): number {
|
||||
const callbacks = this.events.get(event);
|
||||
return callbacks ? callbacks.length : 0;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"ver": "4.0.23",
|
||||
"importer": "typescript",
|
||||
"imported": true,
|
||||
"uuid": "1dc34aed-d9d7-4cd7-8bf7-5d4a1564882f",
|
||||
"files": [],
|
||||
"subMetas": {},
|
||||
"userData": {}
|
||||
}
|
||||
74
client-cocos/assets/scripts/Modules/Pinball/Core/GameData.ts
Normal file
74
client-cocos/assets/scripts/Modules/Pinball/Core/GameData.ts
Normal file
@@ -0,0 +1,74 @@
|
||||
/**
|
||||
* Pinball 游戏核心数据结构定义
|
||||
*/
|
||||
|
||||
/** 2D 向量 */
|
||||
export interface Vector2 {
|
||||
x: number;
|
||||
y: number;
|
||||
}
|
||||
|
||||
/** 物理体 ID */
|
||||
export type BodyId = number;
|
||||
|
||||
/** 世界 ID */
|
||||
export type WorldId = number;
|
||||
|
||||
/** 物理体数据 */
|
||||
export interface PhysicsBodyData {
|
||||
id: BodyId;
|
||||
position: Vector2;
|
||||
velocity: Vector2;
|
||||
rotation: number;
|
||||
angularVelocity: number;
|
||||
bodyType: 'circle' | 'box';
|
||||
radius?: number;
|
||||
size?: Vector2;
|
||||
isStatic: boolean;
|
||||
}
|
||||
|
||||
/** 游戏状态 */
|
||||
export interface GameState {
|
||||
worldId: WorldId;
|
||||
bodies: Map<BodyId, PhysicsBodyData>;
|
||||
isPaused: boolean;
|
||||
timeStep: number;
|
||||
}
|
||||
|
||||
/** Pinball 配置 */
|
||||
export interface PinballConfig {
|
||||
mode: 'standalone' | 'client-multiplayer' | 'server-multiplayer';
|
||||
serverAddress?: string;
|
||||
wasmPath?: string;
|
||||
physicsSettings?: {
|
||||
gravity: Vector2;
|
||||
timeStep: number;
|
||||
};
|
||||
renderSettings?: {
|
||||
enableEffects: boolean;
|
||||
maxParticles: number;
|
||||
};
|
||||
}
|
||||
|
||||
/** 物理设置 */
|
||||
export interface PhysicsSettings {
|
||||
gravity: Vector2;
|
||||
timeStep: number;
|
||||
maxBodies: number;
|
||||
}
|
||||
|
||||
/** 游戏事件类型 */
|
||||
export enum GameEventType {
|
||||
PHYSICS_STEP = 'physics_step',
|
||||
BODY_CREATED = 'body_created',
|
||||
BODY_DESTROYED = 'body_destroyed',
|
||||
WORLD_RESET = 'world_reset',
|
||||
INPUT_RECEIVED = 'input_received'
|
||||
}
|
||||
|
||||
/** 游戏事件数据 */
|
||||
export interface GameEvent {
|
||||
type: GameEventType;
|
||||
data?: any;
|
||||
timestamp: number;
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"ver": "4.0.23",
|
||||
"importer": "typescript",
|
||||
"imported": true,
|
||||
"uuid": "ff4e5c1d-69eb-4234-9087-1b84b837d708",
|
||||
"files": [],
|
||||
"subMetas": {},
|
||||
"userData": {}
|
||||
}
|
||||
@@ -0,0 +1,116 @@
|
||||
/**
|
||||
* 物理引擎接口
|
||||
* 定义了不同物理引擎实现需要遵循的契约
|
||||
*/
|
||||
|
||||
import { BodyId, PhysicsBodyData, PhysicsSettings, Vector2, WorldId } from './GameData';
|
||||
|
||||
export interface CreateCircleOptions {
|
||||
position: Vector2;
|
||||
radius: number;
|
||||
isStatic: boolean;
|
||||
density?: number;
|
||||
restitution?: number;
|
||||
friction?: number;
|
||||
}
|
||||
|
||||
export interface CreateBoxOptions {
|
||||
position: Vector2;
|
||||
size: Vector2;
|
||||
isStatic: boolean;
|
||||
density?: number;
|
||||
restitution?: number;
|
||||
friction?: number;
|
||||
}
|
||||
|
||||
export interface IPhysicsEngine {
|
||||
/**
|
||||
* 初始化物理引擎
|
||||
*/
|
||||
initialize(settings?: PhysicsSettings): Promise<void>;
|
||||
|
||||
/**
|
||||
* 创建物理世界
|
||||
*/
|
||||
createWorld(gravity: Vector2): Promise<WorldId>;
|
||||
|
||||
/**
|
||||
* 销毁物理世界
|
||||
*/
|
||||
destroyWorld(worldId: WorldId): Promise<void>;
|
||||
|
||||
/**
|
||||
* 执行物理步进
|
||||
*/
|
||||
step(deltaTime: number, worldId?: WorldId): Promise<void>;
|
||||
|
||||
/**
|
||||
* 创建圆形刚体
|
||||
*/
|
||||
createCircle(options: CreateCircleOptions): BodyId;
|
||||
|
||||
/**
|
||||
* 创建矩形刚体
|
||||
*/
|
||||
createBox(options: CreateBoxOptions): BodyId;
|
||||
|
||||
/**
|
||||
* 创建动态刚体
|
||||
*/
|
||||
createDynamicBody(worldId: WorldId, position: Vector2, radius: number): Promise<BodyId>;
|
||||
|
||||
/**
|
||||
* 创建静态刚体
|
||||
*/
|
||||
createStaticBody(worldId: WorldId, position: Vector2, radius: number): Promise<BodyId>;
|
||||
|
||||
/**
|
||||
* 销毁刚体
|
||||
*/
|
||||
destroyBody(worldId: WorldId, bodyId: BodyId): Promise<void>;
|
||||
|
||||
/**
|
||||
* 移除刚体
|
||||
*/
|
||||
removeBody(bodyId: BodyId): void;
|
||||
|
||||
/**
|
||||
* 获取刚体位置
|
||||
*/
|
||||
getBodyPosition(worldId: WorldId, bodyId: BodyId): Promise<Vector2 | null>;
|
||||
|
||||
/**
|
||||
* 设置刚体位置
|
||||
*/
|
||||
setBodyPosition(worldId: WorldId, bodyId: BodyId, position: Vector2): Promise<void>;
|
||||
|
||||
/**
|
||||
* 获取刚体速度
|
||||
*/
|
||||
getBodyVelocity(worldId: WorldId, bodyId: BodyId): Promise<Vector2 | null>;
|
||||
|
||||
/**
|
||||
* 设置刚体速度
|
||||
*/
|
||||
setBodyVelocity(worldId: WorldId, bodyId: BodyId, velocity: Vector2): Promise<void>;
|
||||
|
||||
/**
|
||||
* 获取刚体数据
|
||||
*/
|
||||
getBodyData(bodyId: BodyId): PhysicsBodyData | null;
|
||||
|
||||
/**
|
||||
* 获取所有物理体数据
|
||||
*/
|
||||
getAllBodies(worldId: WorldId): Promise<PhysicsBodyData[]>;
|
||||
|
||||
/**
|
||||
* 清理资源
|
||||
*/
|
||||
cleanup(): void;
|
||||
|
||||
/**
|
||||
* 清理资源 (别名)
|
||||
*/
|
||||
dispose(): Promise<void>;
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"ver": "4.0.23",
|
||||
"importer": "typescript",
|
||||
"imported": true,
|
||||
"uuid": "b15a76bd-406d-4463-8a9c-1e82229ab995",
|
||||
"files": [],
|
||||
"subMetas": {},
|
||||
"userData": {}
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
/**
|
||||
* 渲染器接口
|
||||
* 定义了渲染系统需要实现的方法
|
||||
*/
|
||||
|
||||
import { PhysicsBodyData, Vector2 } from './GameData';
|
||||
|
||||
/** 渲染对象数据 */
|
||||
export interface RenderObject {
|
||||
id: string;
|
||||
position: Vector2;
|
||||
radius: number;
|
||||
color: { r: number; g: number; b: number; a: number };
|
||||
layer: number;
|
||||
}
|
||||
|
||||
/** 粒子效果数据 */
|
||||
export interface ParticleEffect {
|
||||
position: Vector2;
|
||||
velocity: Vector2;
|
||||
color: { r: number; g: number; b: number; a: number };
|
||||
lifetime: number;
|
||||
size: number;
|
||||
}
|
||||
|
||||
export interface IRenderer {
|
||||
/**
|
||||
* 初始化渲染器
|
||||
*/
|
||||
initialize(parentNode: any): Promise<void>;
|
||||
|
||||
/**
|
||||
* 渲染物理体
|
||||
*/
|
||||
renderBodies(bodies: PhysicsBodyData[]): void;
|
||||
|
||||
/**
|
||||
* 创建渲染对象
|
||||
*/
|
||||
createRenderObject(body: PhysicsBodyData): RenderObject;
|
||||
|
||||
/**
|
||||
* 更新渲染对象
|
||||
*/
|
||||
updateRenderObject(renderObject: RenderObject, body: PhysicsBodyData): void;
|
||||
|
||||
/**
|
||||
* 移除渲染对象
|
||||
*/
|
||||
removeRenderObject(bodyId: string): void;
|
||||
|
||||
/**
|
||||
* 播放粒子效果
|
||||
*/
|
||||
playParticleEffect(effect: ParticleEffect): void;
|
||||
|
||||
/**
|
||||
* 清除所有渲染对象
|
||||
*/
|
||||
clear(): void;
|
||||
|
||||
/**
|
||||
* 设置相机
|
||||
*/
|
||||
setCamera(camera: any): void;
|
||||
|
||||
/**
|
||||
* 设置世界边界
|
||||
*/
|
||||
setWorldBounds(width: number, height: number): void;
|
||||
|
||||
/**
|
||||
* 设置相机位置
|
||||
*/
|
||||
setCameraPosition(position: Vector2): void;
|
||||
|
||||
/**
|
||||
* 设置相机缩放
|
||||
*/
|
||||
setCameraZoom(zoom: number): void;
|
||||
|
||||
/**
|
||||
* 销毁渲染器
|
||||
*/
|
||||
dispose(): void;
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"ver": "4.0.23",
|
||||
"importer": "typescript",
|
||||
"imported": true,
|
||||
"uuid": "afa401be-4482-4d0a-ae6c-1b1b94b7b992",
|
||||
"files": [],
|
||||
"subMetas": {},
|
||||
"userData": {}
|
||||
}
|
||||
Reference in New Issue
Block a user