squidGame/tgx-games-client/assets/module_arean/scripts/common/RoleManager.ts

181 lines
6.9 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { _decorator, Component, Node, Vec3, Prefab, instantiate, Label, Color, tween, SkeletalAnimation } from 'cc';
import { resLoader } from '../../../core_tgx/base/utils/ResLoader';
import { ModuleDef } from '../../../scripts/ModuleDef';
import { UserMgr } from 'db://assets/module_basic/scripts/UserMgr';
const { ccclass, property } = _decorator;
@ccclass('RoleManager')
export class RoleManager extends Component {
@property
private readonly maxPlayerCount: number = 36; // 人数上限
currentPlayerCount: number = 0; // 当前人数
private roles: Node[] = []; // 存储角色节点
@property
private readonly minRoleId: number = 1; // 最小角色ID
@property
private readonly maxRoleId: number = 5; // 最大角色ID
@property({ type: Label })
public playerCountLabel: Label; // 显示人数的Label
@property({ type: Node })
public roleManagerNode: Node; // RoleManager 的节点
private innerCirclePositions: Vec3[] = []; // 存储内圈角色位置
private outerCirclePositions: Vec3[] = []; // 存储外圈角色位置
start() {
this.initializeRolePositions();
this.schedule(() => {
this.createPlayer();
// 生成0.1到1秒之间的随机间隔包含两位小数
return Math.random() * 0.9 + 0.1;
}, 0.1); // 初始延迟0.1秒,后续使用随机间隔
}
private initializeRolePositions() {
const innerRadius = 4.5; // 内圈半径
const outerRadius = 6; // 外圈半径
const innerCount = 20; // 内圈角色数量
const outerCount = 16; // 外圈角色数量
// 生成内圈位置
const innerAngleStep = 360 / innerCount;
for (let i = 0; i < innerCount; i++) {
const angle = i * innerAngleStep;
const angleInRadians = angle * Math.PI / 180;
const x = Math.sin(angleInRadians) * innerRadius;
const z = Math.cos(angleInRadians) * innerRadius;
this.innerCirclePositions.push(new Vec3(x, 0, z));
}
// 生成外圈位置
const outerAngleStep = 360 / outerCount;
for (let i = 0; i < outerCount; i++) {
const angle = i * outerAngleStep;
const angleInRadians = angle * Math.PI / 180;
const x = Math.sin(angleInRadians) * outerRadius;
const z = Math.cos(angleInRadians) * outerRadius;
this.outerCirclePositions.push(new Vec3(x, 0, z));
}
}
private createPlayer() {
if (this.currentPlayerCount < this.maxPlayerCount) {
this.currentPlayerCount++;
this.animateNumber(this.currentPlayerCount, 0.8); // 动画更新人数
this.createRole(); // 创建角色
if (this.currentPlayerCount >= this.maxPlayerCount) {
{
this.scheduleOnce(() => {
this.clearRoles(); // 清除角色
this.currentPlayerCount = 0;
this.animateNumber(this.currentPlayerCount, 0.8); // 动画更新人数 // 清零
}, 10);
}
}
}
}
private createRole() {
// 随机选择内圈或外圈位置
const isInnerCircle = Math.random() < 0.5; // 50% 概率选择内圈
const positions = isInnerCircle ? this.innerCirclePositions : this.outerCirclePositions;
// 随机选择一个未使用的位置
const availablePositions = positions.filter(pos =>
!this.roles.some(role => Vec3.equals(role.position, pos))
);
if (availablePositions.length === 0) return;
const randomIndex = Math.floor(Math.random() * availablePositions.length);
const position = availablePositions[randomIndex];
// 随机角色ID1-5
const roleId = Math.floor(Math.random() * (this.maxRoleId - this.minRoleId + 1)) + this.minRoleId;
const roleIdStr = ('000' + roleId).slice(-3);
resLoader.load(ModuleDef.Arean, `common/role/Character${roleIdStr}`, (err: Error | null, prefab: Prefab) => {
if (!err && prefab) {
const role = instantiate(prefab);
role.setParent(this.node);
role.setPosition(position);
this.roles.push(role);
// 获取动画组件
const skelAnim = role.getComponentInChildren(SkeletalAnimation);
//skelAnim.crossFade("player_jump1", 0.5);
skelAnim.crossFade("player_idle1", 0.5);
skelAnim.once(SkeletalAnimation.EventType.FINISHED, () => { skelAnim.crossFade("player_idle1", 0.5); }, this);
// 计算朝向中心点的方向
const forward = new Vec3();
Vec3.subtract(forward, new Vec3(0, 0, 0), position);
forward.normalize();
// 设置角色朝向
const euler = new Vec3(0, Math.atan2(forward.x, forward.z) * 180 / Math.PI, 0);
role.eulerAngles = euler;
// 添加角色名字NameLabel
const nameLabel = role.getChildByName("NameLabel");
if (nameLabel) {
const labelComponent = nameLabel.getComponent(Label);
if (labelComponent) {
labelComponent.string = `player${this.currentPlayerCount}`;
labelComponent.color = new Color(255, 255, 255, 255);
}
}
}
});
}
private clearRoles() {
// 移除所有角色
this.roles.forEach(role => {
role.destroy();
});
this.roles = []; // 清空角色数组
}
private animateNumber(targetCount: number, duration: number) {
const startCount = parseInt(this.playerCountLabel.string.split('/')[0]); // 获取当前显示的数字
const tweenObj = { value: startCount };
// this.playerCountLabel.string = `${targetCount}/${this.maxPlayerCount}`;
tween(tweenObj)
.to(duration, { value: targetCount }, {
onUpdate: () => {
this.playerCountLabel.string = `${Math.round(tweenObj.value)}/${this.maxPlayerCount}`; // 更新显示
},
onComplete: () => {
this.playerCountLabel.string = `${targetCount}/${this.maxPlayerCount}`; // 确保最终值为目标值
}
})
.start();
}
onDestroy() {
// 停止所有定时器
this.unscheduleAllCallbacks();
// // 停止所有动画
// this.roles.forEach(role => {
// const skelAnim = role.getComponentInChildren(SkeletalAnimation);
// if (skelAnim) {
// skelAnim.stop(); // 停止动画
// }
// });
// // 清理角色
// this.clearRoles();
// 停止所有 tween
tween(this.node).stop();
}
}