This commit is contained in:
sli97
2022-12-08 21:14:02 +08:00
parent 29104d4bed
commit 81a9a5a2f8
51 changed files with 1694 additions and 2815 deletions

View File

@@ -1,151 +1,160 @@
import { Node, Prefab, SpriteFrame, clamp } from 'cc'
import Singleton from '../Base/Singleton'
import { EntityTypeEnum, IBullet, IClientInput, InputTypeEnum, IRoom, IState, toFixed } from '../Common'
import { ActorManager } from '../Entity/Actor/ActorManager'
import { BulletManager } from '../Entity/Bullet/BulletManager'
import { EventEnum } from '../Enum'
import { JoyStickManager } from '../UI/JoyStickManager'
import EventManager from './EventManager'
import { Node, Prefab, SpriteFrame, clamp } from "cc";
import Singleton from "../Base/Singleton";
import { EntityTypeEnum, IBullet, IClientInput, InputTypeEnum, IRoom, IState, toFixed } from "../Common";
import { ActorManager } from "../Entity/Actor/ActorManager";
import { BulletManager } from "../Entity/Bullet/BulletManager";
import { EventEnum } from "../Enum";
import { JoyStickManager } from "../UI/JoyStickManager";
import EventManager from "./EventManager";
const PLAYER_SPEED = 100;
const BULLET_SPEED = 600;
const PLAYER_SPEED = 100
const BULLET_SPEED = 600
const WEAPON_DAMAGE = 5;
const WEAPON_DAMAGE = 5
const PLAYER_RADIUS = 50;
const BULLET_RADIUS = 10;
const PLAYER_RADIUS = 50
const BULLET_RADIUS = 10
const mapW = 960
const mapH = 640
const mapW = 960;
const mapH = 640;
export default class DataManager extends Singleton {
static get Instance() {
return super.GetInstance<DataManager>()
return super.GetInstance<DataManager>();
}
//登陆数据
myPlayerId = 1
myPlayerId = 1;
//大厅数据
roomInfo: IRoom
roomInfo: IRoom;
//游戏数据
stage: Node
jm: JoyStickManager
prefabMap: Map<string, Prefab> = new Map()
textureMap: Map<string, SpriteFrame[]> = new Map()
actorMap: Map<number, ActorManager> = new Map()
bulletMap: Map<number, BulletManager> = new Map()
stage: Node;
jm: JoyStickManager;
prefabMap: Map<string, Prefab> = new Map();
textureMap: Map<string, SpriteFrame[]> = new Map();
actorMap: Map<number, ActorManager> = new Map();
bulletMap: Map<number, BulletManager> = new Map();
reset() {
this.stage = null
this.jm = null
this.actorMap.clear()
this.bulletMap.clear()
this.prefabMap.clear()
this.textureMap.clear()
this.frameId = 0;
this.stage = null;
this.jm = null;
this.actorMap.clear();
this.bulletMap.clear();
this.prefabMap.clear();
this.textureMap.clear();
}
frameId = 0;
lastState: IState;
state: IState = {
players: [{
id: 2,
nickname: "哈哈1",
position: {
x: -200,
y: -200
actors: [
{
id: 2,
nickname: "哈哈1",
position: {
x: -200,
y: -200,
},
direction: {
x: 1,
y: 0,
},
hp: 100,
type: EntityTypeEnum.Actor1,
weaponType: EntityTypeEnum.Weapon1,
bulletType: EntityTypeEnum.Bullet1,
},
direction: {
x: 1,
y: 0
{
id: 1,
nickname: "哈哈2",
position: {
x: 200,
y: 200,
},
direction: {
x: 0,
y: -1,
},
hp: 100,
type: EntityTypeEnum.Actor2,
weaponType: EntityTypeEnum.Weapon2,
bulletType: EntityTypeEnum.Bullet2,
},
hp: 100,
type: EntityTypeEnum.Actor1,
weaponType: EntityTypeEnum.Weapon1,
bulletType: EntityTypeEnum.Bullet1,
}, {
id: 1,
nickname: "哈哈2",
position: {
x: 200,
y: 200
},
direction: {
x: 0,
y: -1
},
hp: 100,
type: EntityTypeEnum.Actor2,
weaponType: EntityTypeEnum.Weapon2,
bulletType: EntityTypeEnum.Bullet2,
}],
],
bullets: [],
nextBulletId: 1
}
nextBulletId: 1,
};
applyInput(input: IClientInput) {
switch (input.type) {
case InputTypeEnum.ActorMove: {
const { direction: { x, y }, dt, id } = input
const player = this.state.players.find(e => e.id === id)
const {
direction: { x, y },
dt,
id,
} = input;
const player = this.state.actors.find((e) => e.id === id);
if (!player) {
return
return;
}
player.position.x += toFixed(x * PLAYER_SPEED * dt)
player.position.y += toFixed(y * PLAYER_SPEED * dt)
player.position.x += toFixed(x * PLAYER_SPEED * dt);
player.position.y += toFixed(y * PLAYER_SPEED * dt);
player.position.x = clamp(player.position.x, -mapW / 2, mapW / 2)
player.position.y = clamp(player.position.y, -mapH / 2, mapH / 2)
player.position.x = clamp(player.position.x, -mapW / 2, mapW / 2);
player.position.y = clamp(player.position.y, -mapH / 2, mapH / 2);
player.direction = { x, y }
break
player.direction = { x, y };
break;
}
case InputTypeEnum.WeaponShoot: {
const { owner, position, direction } = input
const { owner, position, direction } = input;
const bullet: IBullet = {
id: this.state.nextBulletId++,
owner,
position,
direction,
type: this.actorMap.get(owner).bulletType
}
this.state.bullets.push(bullet)
type: this.actorMap.get(owner).bulletType,
};
this.state.bullets.push(bullet);
EventManager.Instance.emit(EventEnum.BulletBorn, owner)
break
EventManager.Instance.emit(EventEnum.BulletBorn, owner);
break;
}
case InputTypeEnum.TimePast: {
const { dt } = input
const { bullets, players } = this.state
const { dt } = input;
const { bullets, actors } = this.state;
for (let i = bullets.length - 1; i >= 0; i--) {
const bullet = bullets[i];
for (let j = players.length - 1; j >= 0; j--) {
const player = players[j];
if (((player.position.x - bullet.position.x) ** 2 + (player.position.y - bullet.position.y) ** 2) < (PLAYER_RADIUS + BULLET_RADIUS) ** 2) {
for (let j = actors.length - 1; j >= 0; j--) {
const player = actors[j];
if ((player.position.x - bullet.position.x) ** 2 + (player.position.y - bullet.position.y) ** 2 < (PLAYER_RADIUS + BULLET_RADIUS) ** 2) {
EventManager.Instance.emit(EventEnum.ExplosionBorn, bullet.id, {
x: toFixed((player.position.x + bullet.position.x) / 2),
y: toFixed((player.position.y + bullet.position.y) / 2),
})
});
player.hp -= WEAPON_DAMAGE
bullets.splice(i, 1)
break
player.hp -= WEAPON_DAMAGE;
bullets.splice(i, 1);
break;
}
}
if (Math.abs(bullet.position.x) > mapW / 2 || Math.abs(bullet.position.y) > mapH / 2) {
EventManager.Instance.emit(EventEnum.ExplosionBorn, bullet.id, {
x: bullet.position.x,
y: bullet.position.y,
})
bullets.splice(i, 1)
});
bullets.splice(i, 1);
}
}
for (const bullet of this.state.bullets) {
bullet.position.x += toFixed(bullet.direction.x * BULLET_SPEED * dt)
bullet.position.y += toFixed(bullet.direction.y * BULLET_SPEED * dt)
bullet.position.x += toFixed(bullet.direction.x * BULLET_SPEED * dt);
bullet.position.y += toFixed(bullet.direction.y * BULLET_SPEED * dt);
}
}
}

View File

@@ -1,5 +1,5 @@
import Singleton from '../Base/Singleton'
import { EventEnum } from '../Enum';
import Singleton from "../Base/Singleton";
import { EventEnum } from "../Enum";
interface IItem {
cb: Function;
@@ -23,7 +23,7 @@ export default class EventManager extends Singleton {
off(event: EventEnum, cb: Function, ctx: unknown) {
if (this.map.has(event)) {
const index = this.map.get(event).findIndex(i => cb === i.cb && i.ctx === ctx);
const index = this.map.get(event).findIndex((i) => cb === i.cb && i.ctx === ctx);
index > -1 && this.map.get(event).splice(index, 1);
}
}
@@ -31,7 +31,7 @@ export default class EventManager extends Singleton {
emit(event: EventEnum, ...params: unknown[]) {
if (this.map.has(event)) {
this.map.get(event).forEach(({ cb, ctx }) => {
cb.apply(ctx, params)
cb.apply(ctx, params);
});
}
}

View File

@@ -1,8 +1,8 @@
import Singleton from '../Base/Singleton'
import { ApiMsgEnum, IModel } from '../Common';
import { binaryEncode, binaryDecode } from '../Common/Binary';
import Singleton from "../Base/Singleton";
import { ApiMsgEnum, IModel } from "../Common";
import { binaryEncode, binaryDecode } from "../Common/Binary";
const TIMEOUT = 5000
const TIMEOUT = 5000;
interface IItem {
cb: Function;
@@ -12,109 +12,107 @@ interface IItem {
export interface ICallApiRet<T> {
success: boolean;
error?: Error;
res?: T
res?: T;
}
type aaa = keyof IModel
export default class NetworkManager extends Singleton {
static get Instance() {
return super.GetInstance<NetworkManager>()
return super.GetInstance<NetworkManager>();
}
ws: WebSocket
port = 8888
maps: Map<ApiMsgEnum, Array<IItem>> = new Map()
isConnected = false
ws: WebSocket;
port = 8888;
maps: Map<ApiMsgEnum, Array<IItem>> = new Map();
isConnected = false;
connect() {
return new Promise((resolve, reject) => {
if (this.isConnected) {
resolve(true)
return
resolve(true);
return;
}
this.ws = new WebSocket(`ws://localhost:${this.port}`)
this.ws = new WebSocket(`ws://localhost:${this.port}`);
//onmessage接受的数据类型只有在后端返回字节数组的时候才有效果
this.ws.binaryType = 'arraybuffer';
this.ws.binaryType = "arraybuffer";
this.ws.onopen = () => {
this.isConnected = true
resolve(true)
}
this.isConnected = true;
resolve(true);
};
this.ws.onerror = (e) => {
this.isConnected = false
console.log(e)
reject("ws onerror")
}
this.isConnected = false;
console.log(e);
reject("ws onerror");
};
this.ws.onclose = () => {
this.isConnected = false
reject("ws onclose")
}
this.isConnected = false;
reject("ws onclose");
};
this.ws.onmessage = (e) => {
try {
const json = binaryDecode(e.data)
const { name, data } = json
const json = binaryDecode(e.data);
const { name, data } = json;
try {
if (this.maps.has(name) && this.maps.get(name).length) {
console.log(json);
this.maps.get(name).forEach(({ cb, ctx }) => cb.call(ctx, data))
this.maps.get(name).forEach(({ cb, ctx }) => cb.call(ctx, data));
}
} catch (error) {
console.log("onmessage:", error)
console.log("onmessage:", error);
}
} catch (error) {
console.log('解析失败不是合法的JSON格式', error)
console.log("解析失败不是合法的JSON格式", error);
}
}
})
};
});
}
callApi<T extends keyof IModel['api']>(name: T, data: IModel['api'][T]['req']): Promise<ICallApiRet<IModel['api'][T]['res']>> {
callApi<T extends keyof IModel["api"]>(name: T, data: IModel["api"][T]["req"]): Promise<ICallApiRet<IModel["api"][T]["res"]>> {
return new Promise((resolve) => {
try {
// 超时处理
const timer = setTimeout(() => {
resolve({ success: false, error: new Error('timeout') })
this.unlistenMsg(name as any, cb, null)
}, TIMEOUT)
resolve({ success: false, error: new Error("timeout") });
this.unlistenMsg(name as any, cb, null);
}, TIMEOUT);
// 回调处理
const cb = (res) => {
resolve(res)
clearTimeout(timer)
this.unlistenMsg(name as any, cb, null)
}
this.listenMsg(name as any, cb, null)
resolve(res);
clearTimeout(timer);
this.unlistenMsg(name as any, cb, null);
};
this.listenMsg(name as any, cb, null);
this.sendMsg(name as any, data)
this.sendMsg(name as any, data);
} catch (error) {
resolve({ success: false, error: error as Error })
resolve({ success: false, error: error as Error });
}
})
});
}
async sendMsg<T extends keyof IModel['msg']>(name: T, data: IModel['msg'][T]) {
const view = binaryEncode(name, data)
let delay = parseInt(new URLSearchParams(location.search).get('delay') || '0') || 0;
await new Promise((r) => setTimeout(r, delay))
this.ws.send(view.buffer)
async sendMsg<T extends keyof IModel["msg"]>(name: T, data: IModel["msg"][T]) {
const view = binaryEncode(name, data);
let delay = parseInt(new URLSearchParams(location.search).get("delay") || "0") || 0;
await new Promise((r) => setTimeout(r, delay));
this.ws.send(view.buffer);
}
listenMsg<T extends keyof IModel['msg']>(name: T, cb: (args: IModel['msg'][T]) => void, ctx: unknown) {
listenMsg<T extends keyof IModel["msg"]>(name: T, cb: (args: IModel["msg"][T]) => void, ctx: unknown) {
if (this.maps.has(name)) {
this.maps.get(name).push({ ctx, cb })
this.maps.get(name).push({ ctx, cb });
} else {
this.maps.set(name, [{ ctx, cb }])
this.maps.set(name, [{ ctx, cb }]);
}
}
unlistenMsg<T extends keyof IModel['msg']>(name: T, cb: (args: IModel['msg'][T]) => void, ctx: unknown) {
unlistenMsg<T extends keyof IModel["msg"]>(name: T, cb: (args: IModel["msg"][T]) => void, ctx: unknown) {
if (this.maps.has(name)) {
const items = this.maps.get(name)
const index = items.findIndex(i => cb === i.cb && i.ctx === ctx);
index > -1 && items.splice(index, 1)
const items = this.maps.get(name);
const index = items.findIndex((i) => cb === i.cb && i.ctx === ctx);
index > -1 && items.splice(index, 1);
}
}
}

View File

@@ -1,55 +1,55 @@
import Singleton from '../Base/Singleton'
import { instantiate, Node } from 'cc'
import DataManager from './DataManager'
import { EntityTypeEnum } from '../Common'
import Singleton from "../Base/Singleton";
import { instantiate, Node } from "cc";
import DataManager from "./DataManager";
import { EntityTypeEnum } from "../Common";
export default class ObjectPoolManager extends Singleton {
static get Instance() {
return super.GetInstance<ObjectPoolManager>()
return super.GetInstance<ObjectPoolManager>();
}
private objectPool: Node = null
private map: Map<EntityTypeEnum, Node[]> = new Map()
private objectPool: Node = null;
private map: Map<EntityTypeEnum, Node[]> = new Map();
private getContainerName(objectName: EntityTypeEnum) {
return objectName + 'Pool'
return objectName + "Pool";
}
reset() {
this.objectPool = null
this.map.clear()
this.objectPool = null;
this.map.clear();
}
get(objectName: EntityTypeEnum) {
if (this.objectPool === null) {
this.objectPool = new Node("ObjectPool")
this.objectPool.setParent(DataManager.Instance.stage)
this.objectPool = new Node("ObjectPool");
this.objectPool.setParent(DataManager.Instance.stage);
}
if (!this.map.has(objectName)) {
this.map.set(objectName, [])
const container = new Node(this.getContainerName(objectName))
container.setParent(this.objectPool)
this.map.set(objectName, []);
const container = new Node(this.getContainerName(objectName));
container.setParent(this.objectPool);
}
let node: Node
const nodes = this.map.get(objectName)
let node: Node;
const nodes = this.map.get(objectName);
if (!nodes.length) {
const prefab = DataManager.Instance.prefabMap.get(objectName)
node = instantiate(prefab)
node.name = objectName
node.setParent(this.objectPool.getChildByName(this.getContainerName(objectName)))
const prefab = DataManager.Instance.prefabMap.get(objectName);
node = instantiate(prefab);
node.name = objectName;
node.setParent(this.objectPool.getChildByName(this.getContainerName(objectName)));
} else {
node = nodes.pop()
node = nodes.pop();
}
node.active = true
return node
node.active = true;
return node;
}
ret(object: Node) {
object.active = false
const objectName = object.name as EntityTypeEnum
this.map.get(objectName).push(object)
object.active = false;
const objectName = object.name as EntityTypeEnum;
this.map.get(objectName).push(object);
}
}

View File

@@ -1,32 +1,32 @@
import { _decorator, resources, Asset } from 'cc'
import Singleton from '../Base/Singleton'
import { _decorator, resources, Asset } from "cc";
import Singleton from "../Base/Singleton";
export class ResourceManager extends Singleton {
static get Instance() {
return super.GetInstance<ResourceManager>()
return super.GetInstance<ResourceManager>();
}
loadRes<T extends Asset>(path: string, type: new (...args: any[]) => T) {
return new Promise<T>((resolve, reject) => {
resources.load(path, type, (err, res) => {
if (err) {
reject(err)
return
reject(err);
return;
}
resolve(res)
})
})
resolve(res);
});
});
}
loadDir<T extends Asset>(path: string, type: new (...args: any[]) => T) {
return new Promise<T[]>((resolve, reject) => {
resources.loadDir(path, type, (err, res) => {
if (err) {
reject(err)
return
reject(err);
return;
}
resolve(res)
})
})
resolve(res);
});
});
}
}