HuaweiDemo/assets/script/core/playerLogic.ts
2023-11-07 09:17:57 +08:00

269 lines
10 KiB
TypeScript

import { VirtualPlayer } from './virtualPlayer';
import { _decorator, Component, Node, Vec3, Prefab, Quat, ModelComponent, geometry, Mat4, math } from 'cc';
import { Constant } from '../framework/constant';
import { PoolManager } from '../framework/poolManager';
import { Player, PropType } from './gameState';
import { LogicManager } from './logicManager';
import { GobeUtil } from './gobeUtil';
const { ccclass, property } = _decorator;
/**
* Predefined variables
* Name = PlayerLogic
* DateTime = Thu Sep 09 2021 15:46:05 GMT+0800 (中国标准时间)
* Author = yanli.huang
* FileBasename = playerLogic.ts
* FileBasenameNoExtension = playerLogic
* URL = db://assets/script/core/playerLogic.ts
* ManualUrl = https://docs.cocos.com/creator/3.3/manual/zh/
*
*/
let v3_1 = new Vec3();
let v3_2 = new Vec3();
@ccclass('PlayerLogic')
export class PlayerLogic extends Component {
@property(Prefab)
virtualPlayerPrefab: Prefab = null!;
@property(Node)
obstacleGroupNode: Node = null!;
private _dicPlayers: {[index: number]: Node} = {};//存放虚拟玩家节点的字典
private _dicScriptVirtualPlayers: {[index: number]: VirtualPlayer} = {};//存放虚拟玩家脚本的字典
private _parent: LogicManager = null!;
public init(parent: LogicManager) {
this._parent = parent;
}
/**
* 重置节点
*/
public reset() {
let keyArray: string[]= Object.keys(this._dicPlayers);
keyArray.forEach((element: string)=> {
PoolManager.instance.putNode(this._dicPlayers[parseInt(element)]);
delete this._dicPlayers[parseInt(element)];
});
}
/**
* 生成虚拟玩家
* @returns 虚拟玩家数据
*/
public initPlayer() {
let players: Array<Player>= [];
for(let i: number = 0; i < Constant.MAX_PLAYER; i++) {
let player: Player = {} as Player;
let pos: Vec3 = new Vec3(-50, 0, 0);
let eulerAngles: Vec3 = new Vec3(0, 90, 0);
switch (i) {
case 0:
break;
case 1:
pos.set(50, 0, 0);
eulerAngles.set(0, -90, 0);
break;
}
player.id = i;
player.position = pos;
player.eulerAngles = eulerAngles;
player.score = 0;
player.hammerCount = 0;
player.moveX = 0;
player.moveY = 0;
player.isShowReward = false;
player.isScoreLead = false;
players[i] = player;
let ndVirtualPlayer = PoolManager.instance.getNode(this.virtualPlayerPrefab, this.node);
ndVirtualPlayer.setPosition(pos);
ndVirtualPlayer.eulerAngles = eulerAngles;
this._dicPlayers[i] = ndVirtualPlayer;
let scriptVirtualPlayer = ndVirtualPlayer.getComponent(VirtualPlayer) as VirtualPlayer;
scriptVirtualPlayer.init(pos);
this._dicScriptVirtualPlayers[i] = scriptVirtualPlayer;
}
return players;
}
/**
* 处理虚拟玩家节点显示
* @param players 玩家数据
*/
public updatePlayerNode(players: Player[]) {
players.forEach((value: Player, index: number) => {
let playerNode: Node = this._dicPlayers[index];
if (value.channel) {
playerNode.active = true;
} else {
playerNode.active = false;
}
});
}
/**
* 玩家停止移动
* @param player
* @param horizontal
* @param vertical
* @param value
*/
public stopMove(player: Player, posX: number, posZ: number, angleY: number) {
this._dicScriptVirtualPlayers[player.id].playAction({action: Constant.ACTION.STOP_MOVE, posX: posX, posZ: posZ, angleY: angleY});
}
/**
* 玩家停止移动,并朝向敌人进行攻击
* @param player
* @param horizontal
* @param vertical
* @param value
*/
public stopMoveAndAttack(player: Player, posX: number, posZ: number, angleY: number) {
this._dicScriptVirtualPlayers[player.id].playAction({action: Constant.ACTION.IS_ATTACK_ED, posX: posX, posZ: posZ, angleY: angleY});
}
/**
* 玩家移动
* @param player 玩家数据
* @param horizontal 水平值
* @param vertical 垂直值
*/
public move(playerId: number, posX: number, posZ: number, angleY: number) {
this._dicScriptVirtualPlayers[playerId].playAction({action: Constant.ACTION.MOVE, posX: posX, posZ: posZ, angleY: angleY});
}
/**
* 更新玩家状态
*/
public updateStateRecovery () {
for (const i in this._dicScriptVirtualPlayers) {
if (Object.prototype.hasOwnProperty.call(this._dicScriptVirtualPlayers, i)) {
const scriptVirtualPlayer = this._dicScriptVirtualPlayers[i];
scriptVirtualPlayer.playActionRecovery();
}
}
}
/**
* 更新玩家状态
*/
public updateState () {
for (const i in this._dicScriptVirtualPlayers) {
if (Object.prototype.hasOwnProperty.call(this._dicScriptVirtualPlayers, i)) {
const scriptVirtualPlayer = this._dicScriptVirtualPlayers[i];
scriptVirtualPlayer.updateState(this._parent.currentGameState.players[i], this._parent);
}
}
}
/**
* 判断是否相交
* @returns
*/
public intersectWithObstacle(worldMatrix:Mat4, worldRotation:Quat, scale:Vec3, parentScale:Vec3) {
let modelArray: ModelComponent[] = this.obstacleGroupNode.getComponentsInChildren(ModelComponent);
let flag: boolean = false;
for(let i: number = 0; i < modelArray.length; i++) {
if (!modelArray[i].node.active) continue;
let model2: ModelComponent = modelArray[i];
let obb1: geometry.OBB = new geometry.OBB();
let obb2: geometry.OBB = new geometry.OBB();
obb1.halfExtents = Vec3.multiplyScalar(v3_1, scale, 0.5 * parentScale.x);
obb2.halfExtents = Vec3.multiplyScalar(v3_2, model2.node.scale, 0.5 * (model2.node.parent as Node).scale.x);
obb1.translateAndRotate(worldMatrix, worldRotation, obb1);
obb2.translateAndRotate(model2.node.worldMatrix, model2.node.worldRotation, obb2);
if (geometry.intersect.obbWithOBB(obb1, obb2)) {
return true;
}
}
return flag;
}
// /**
// * 处理攻击操作数据
// * @param player 攻击者数据
// * @returns
// */
// public checkAttack(player: Player) {
// if (!player.hammerCount) return;
// let enemy: Player = this.getNearestEnemy(player.channel.openId, player.position);
// if (!enemy || ((this._parent.currentGameState.frameTime - enemy.dizzyTime) < Constant.REVIVE_TIME * 1000)) return;
// let selfNode: Node = this._dicPlayers[player.id];
// //正前方3米处
// //半径为1米
// let hammerDistance = 3 * selfNode.scale.x;
// let hammerRange = 1 * selfNode.scale.x;
// let offset = enemy.position.clone().subtract(player.position).normalize();
// let posHammer = player.position.clone().add(offset.clone().multiplyScalar(hammerDistance));
// let dis = posHammer.clone().subtract(enemy.position).length();
// if (dis < hammerRange * 0.9 + Constant.INIT_COLLIDER_CIRCLE) {
// player.attackPos = posHammer.clone();
// player.attackPropType = PropType.HAMMER;
// let dis = posHammer.subtract(enemy.position).length();
// if (dis < hammerRange + Constant.INIT_COLLIDER_CIRCLE) {
// player.hammerCount--;
// player.attackId = enemy.id;
// enemy.dizzyTime = this._parent.currentGameState.frameTime;
// //设置眩晕结束时间,一秒攻击方动画播放秒数,一秒为受击动画播放秒数
// enemy.dizzyOverTime = this._parent.currentGameState.frameTime + Constant.DIZZY_TIME * 1000 + 1000;
// let num: number = Math.ceil(enemy.score / 2);
// num = num >= 20 ? 20 : num;
// enemy.score -= num;
// this._parent.propLogic.createCoinByHammer(num, enemy.position);
// }
// //朝向指定的敌人攻击
// GobeUtil.instance.sendFrame({'A': Constant.ACTION.IS_ATTACK_ED, 'I': enemy.channel.openId});
// }
// }
public getPlayerByIndex(index:number){
return this._dicPlayers[index];
}
/**
* 获取最近的其他玩家
* @param selfPlayerId
* @param position
* @returns
*/
public getNearestEnemy (selfPlayerId: string, position: Vec3) {
let sqr: number = math.bits.INT_MAX;
let nearestPlayer: Player = null!;
let players: Array<Player> = this._parent.currentGameState.players;
for (let pos in players) {
let player: Player = players[pos];
if (player.channel && player.channel.openId !== selfPlayerId) {
//判断距离
let lenSqr: number = Vec3.squaredDistance(player.position, position);
if (lenSqr < sqr) {
sqr = lenSqr;
nearestPlayer = player;
}
}
}
return nearestPlayer;
}
}
/**
* [1] Class member could be defined like this.
* [2] Use `property` decorator if your want the member to be serializable.
* [3] Your initialization goes here.
* [4] Your update function goes here.
*
* Learn more about scripting: https://docs.cocos.com/creator/3.3/manual/zh/scripting/
* Learn more about CCClass: https://docs.cocos.com/creator/3.3/manual/zh/scripting/ccclass.html
* Learn more about life-cycle callbacks: https://docs.cocos.com/creator/3.3/manual/zh/scripting/life-cycle-callbacks.html
*/