378 lines
13 KiB
TypeScript
378 lines
13 KiB
TypeScript
|
import { _decorator, Component, Node, Vec3, ModelComponent, geometry, Prefab, clamp } from 'cc';
|
|||
|
import { PoolManager } from '../framework/poolManager';
|
|||
|
import { Player, Prop, PropType } from './gameState';
|
|||
|
import { LogicManager } from './logicManager';
|
|||
|
import { Util } from '../framework/util';
|
|||
|
import { Constant } from '../framework/constant';
|
|||
|
import { EffectManager } from '../framework/effectManager';
|
|||
|
import { GobeUtil } from './gobeUtil';
|
|||
|
const { ccclass, property } = _decorator;
|
|||
|
|
|||
|
/**
|
|||
|
* Predefined variables
|
|||
|
* Name = PropLogic
|
|||
|
* DateTime = Thu Sep 09 2021 15:45:54 GMT+0800 (中国标准时间)
|
|||
|
* Author = yanli.huang
|
|||
|
* FileBasename = propLogic.ts
|
|||
|
* FileBasenameNoExtension = propLogic
|
|||
|
* URL = db://assets/script/core/propLogic.ts
|
|||
|
* ManualUrl = https://docs.cocos.com/creator/3.3/manual/zh/
|
|||
|
*/
|
|||
|
let v3_1: Vec3 = new Vec3();
|
|||
|
let v3_2: Vec3 = new Vec3();
|
|||
|
let coinWorPos: Vec3 = new Vec3();
|
|||
|
@ccclass('PropLogic')
|
|||
|
export class PropLogic extends Component {
|
|||
|
@property(Prefab)
|
|||
|
virtualCoinPrefab: Prefab = null!;
|
|||
|
|
|||
|
@property(Prefab)
|
|||
|
virtualHammerPrefab: Prefab = null!;
|
|||
|
|
|||
|
public indexProp: number = 0;
|
|||
|
private _dicProps: {[index: number]: Node} = {};
|
|||
|
private _parent: LogicManager = null!;
|
|||
|
|
|||
|
public init(parent: LogicManager) {
|
|||
|
this._parent = parent;
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* 重置节点
|
|||
|
*/
|
|||
|
public reset() {
|
|||
|
let keyArray: string[]= Object.keys(this._dicProps);
|
|||
|
keyArray.forEach((element: string)=> {
|
|||
|
PoolManager.instance.putNode(this._dicProps[parseInt(element)]);
|
|||
|
delete this._dicProps[parseInt(element)];
|
|||
|
});
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* 生成虚拟道具
|
|||
|
* @returns 虚拟道具数据
|
|||
|
*/
|
|||
|
public initProps() {
|
|||
|
let props: Array<Prop>= [];
|
|||
|
this.indexProp = 0;
|
|||
|
|
|||
|
for (let idx: number = 0; idx < 36; idx++) {
|
|||
|
let row = Math.floor(idx / 6);
|
|||
|
let col = Math.floor(idx % 6);
|
|||
|
|
|||
|
if (row >= 2 && row <= 3 && col >= 2 && col <= 3) { //中间空出来
|
|||
|
continue;
|
|||
|
}
|
|||
|
props[this.indexProp] = this.generateProp(new Vec3(-9 + col * 3.5, 1, 6 - row * 3));
|
|||
|
this.indexProp++;
|
|||
|
}
|
|||
|
|
|||
|
//两横
|
|||
|
for (let idx: number= 0; idx < 7; idx++) {
|
|||
|
props[this.indexProp] = this.generateProp(new Vec3(-18 + idx * 6, 1, -16));
|
|||
|
this.indexProp++;
|
|||
|
props[this.indexProp] = this.generateProp(new Vec3(-18 + idx * 6, 1, 14));
|
|||
|
this.indexProp++;
|
|||
|
}
|
|||
|
|
|||
|
//两横
|
|||
|
for (let idx: number= 0; idx < 12; idx++) {
|
|||
|
props[this.indexProp] = this.generateProp(new Vec3(-29 + idx * 5, 1, -24));
|
|||
|
this.indexProp++;
|
|||
|
props[this.indexProp] = this.generateProp(new Vec3(-29 + idx * 5, 1, 22.5));
|
|||
|
this.indexProp++;
|
|||
|
}
|
|||
|
|
|||
|
//两竖
|
|||
|
for (let idx: number= 0; idx < 4; idx++) {
|
|||
|
props[this.indexProp] = this.generateProp(new Vec3(-18, 1, -10 + idx * 6));
|
|||
|
this.indexProp++;
|
|||
|
props[this.indexProp] = this.generateProp(new Vec3(18, 1, -10 + idx * 6));
|
|||
|
this.indexProp++;
|
|||
|
}
|
|||
|
|
|||
|
//两竖
|
|||
|
for (let idx: number= 0; idx < 5; idx++) {
|
|||
|
props[this.indexProp] = this.generateProp(new Vec3(-29, 1, -10 + idx * 5));
|
|||
|
this.indexProp++;
|
|||
|
props[this.indexProp] = this.generateProp(new Vec3(29, 1, -10 + idx * 5));
|
|||
|
this.indexProp++;
|
|||
|
}
|
|||
|
|
|||
|
//两竖
|
|||
|
for (let idx: number= 0; idx < 9; idx++) {
|
|||
|
props[this.indexProp] = this.generateProp(new Vec3(-36, 1, -21 + idx * 5));
|
|||
|
this.indexProp++;
|
|||
|
props[this.indexProp] = this.generateProp(new Vec3(36, 1, -21 + idx * 5));
|
|||
|
this.indexProp++;
|
|||
|
}
|
|||
|
|
|||
|
return props;
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* 移除多余道具
|
|||
|
* @param length 移除数值
|
|||
|
*/
|
|||
|
public removeOverProp(length: number) {
|
|||
|
let keyArray = Object.keys(this._dicProps);
|
|||
|
for(let i = length; i < keyArray.length; i++) {
|
|||
|
if (this._dicProps[i]) {
|
|||
|
PoolManager.instance.putNode(this._dicProps[i]);
|
|||
|
delete this._dicProps[i];
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* 删除指定道具
|
|||
|
*
|
|||
|
* @memberof PropLogic
|
|||
|
*/
|
|||
|
public removePropId (propId: number) {
|
|||
|
var prop:Prop = this._parent.currentGameState.props[propId];
|
|||
|
if(prop){
|
|||
|
prop.exist = false;
|
|||
|
|
|||
|
if(this._dicProps[prop.id]){
|
|||
|
PoolManager.instance.putNode(this._dicProps[prop.id]);
|
|||
|
delete this._dicProps[prop.id];
|
|||
|
|
|||
|
return true;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
return false;
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* 删除指定道具
|
|||
|
*
|
|||
|
* @memberof PropLogic
|
|||
|
*/
|
|||
|
public removeProp (prop: Prop) {
|
|||
|
PoolManager.instance.putNode(this._dicProps[prop.id]);
|
|||
|
delete this._dicProps[prop.id];
|
|||
|
prop.exist = false;
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* 生成道具数据
|
|||
|
* @param pos 位置
|
|||
|
* @param scale 大小
|
|||
|
* @param type 类型
|
|||
|
* @param belongOpenId 指定玩家才能拾取道具,为""则表示谁都可以拾取
|
|||
|
* @param delay 延迟(金币雨产生的金币会每隔150毫秒展示)
|
|||
|
* @returns
|
|||
|
*/
|
|||
|
public generateProp(pos: Vec3, scale: number = 1, type: PropType = PropType.COIN, belongOpenId: string = "", delay: number = 0) {
|
|||
|
let prop: Prop = {} as Prop;
|
|||
|
prop.id = this.indexProp;
|
|||
|
prop.position = pos;
|
|||
|
prop.scale = scale;
|
|||
|
prop.exist = true;
|
|||
|
prop.type = type;
|
|||
|
this._dicProps[this.indexProp] = this._generatePropNode(prop) as Node;
|
|||
|
return prop;
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* 生成道具节点
|
|||
|
* @param prop 道具数据
|
|||
|
* @returns
|
|||
|
*/
|
|||
|
private _generatePropNode(prop: Prop) {
|
|||
|
let prefab: Prefab = this.virtualCoinPrefab;if (prop.type === PropType.HAMMER) {
|
|||
|
prefab = this.virtualHammerPrefab;
|
|||
|
}
|
|||
|
let node: Node = PoolManager.instance.getNode(prefab, this.node);
|
|||
|
node.setWorldPosition(prop.position);
|
|||
|
return node;
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* 处理人物碰到道具
|
|||
|
* @param player 玩家数据
|
|||
|
* @param ndVirtualPlayer 玩家节点
|
|||
|
*/
|
|||
|
public handleProp(player: Player, ndVirtualPlayer: Node, isAi: boolean) {
|
|||
|
let props: {[index: number]: Prop} = this._parent.currentGameState.props;
|
|||
|
let keyPropsArray: Array<string> = Object.keys(this._dicProps);
|
|||
|
let model1: ModelComponent = ndVirtualPlayer.getComponentInChildren(ModelComponent) as ModelComponent;
|
|||
|
|
|||
|
keyPropsArray.forEach((value: string) => {
|
|||
|
let prop: Prop = props[parseInt(value)];
|
|||
|
if (prop.type === PropType.HAMMER && player.hammerCount || prop.removed) {
|
|||
|
return;
|
|||
|
}
|
|||
|
let ndProp: Node = this._dicProps[parseInt(value)];
|
|||
|
let distance = Util.getTwoNodeXZLength(ndProp, ndVirtualPlayer);
|
|||
|
if (distance >= 5) {
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
let model2: ModelComponent = ndProp.getComponentInChildren(ModelComponent) as ModelComponent;
|
|||
|
let obb1: geometry.OBB = new geometry.OBB();
|
|||
|
let obb2: geometry.OBB = new geometry.OBB();
|
|||
|
obb1.halfExtents = Vec3.multiplyScalar(v3_1, model1.node.scale, 0.5 * (model1.node.parent as Node).scale.x);
|
|||
|
obb2.halfExtents = Vec3.multiplyScalar(v3_2, model2.node.scale, 0.5 * (model2.node.parent as Node).scale.x);
|
|||
|
obb1.translateAndRotate(model1.node.worldMatrix, model1.node.worldRotation, obb1);
|
|||
|
obb2.translateAndRotate(model2.node.worldMatrix, model2.node.worldRotation, obb2);
|
|||
|
if (geometry.intersect.obbWithOBB(obb1, obb2)) {if (prop.type === PropType.HAMMER && player.hammerCount !== 0) {
|
|||
|
return;
|
|||
|
}
|
|||
|
if (prop.type === PropType.HAMMER) {
|
|||
|
prop.removed = true;
|
|||
|
if(isAi){
|
|||
|
GobeUtil.instance.sendFrame({'A': Constant.ACTION.HAMMER, 'V': prop.id, 'AI' : 1});
|
|||
|
}else{
|
|||
|
GobeUtil.instance.sendFrame({'A': Constant.ACTION.HAMMER, 'V': prop.id});
|
|||
|
}
|
|||
|
} else if (prop.type === PropType.COIN) {
|
|||
|
if(this._dicProps[prop.id]){
|
|||
|
prop.removed = true;
|
|||
|
if(isAi){
|
|||
|
GobeUtil.instance.sendFrame({'A': Constant.ACTION.ICON, 'V': prop.id, 'AI' : 1});
|
|||
|
}else{
|
|||
|
GobeUtil.instance.sendFrame({'A': Constant.ACTION.ICON, 'V': prop.id});
|
|||
|
}
|
|||
|
}else{
|
|||
|
return;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
});
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* 获取随机道具、金币掉落位置
|
|||
|
* @param posWorld
|
|||
|
* @returns
|
|||
|
*/
|
|||
|
public randomDropPos(posWorld: Vec3, propType: number, radius: number = 6) {
|
|||
|
let posNew: Vec3 | null = new Vec3();
|
|||
|
let i = 0;
|
|||
|
let data: any;
|
|||
|
if (propType === PropType.COIN) {
|
|||
|
data = this.virtualCoinPrefab.data;
|
|||
|
} else if (propType === PropType.HAMMER) {
|
|||
|
data = this.virtualHammerPrefab.data;
|
|||
|
}
|
|||
|
|
|||
|
do {
|
|||
|
//范围逐渐扩大
|
|||
|
let r_1 = (radius + i / 10);
|
|||
|
let r_2 = (radius + i / 10);
|
|||
|
|
|||
|
let x = -r_1 + Math.random() * r_1 * 2;
|
|||
|
let z = -r_2 + Math.random() * r_2 * 2;
|
|||
|
|
|||
|
x = x + posWorld.x;
|
|||
|
z = z + posWorld.z;
|
|||
|
|
|||
|
//限制范围
|
|||
|
x = clamp(x, -28, 28);
|
|||
|
z = clamp(z, -24, 24);
|
|||
|
|
|||
|
posNew.set(x, 1, z);
|
|||
|
|
|||
|
i++;
|
|||
|
//防止死循环
|
|||
|
if (i >= 50) {
|
|||
|
console.log("randomDropPos,posNew", posNew, "posWorld", posWorld, "propType", propType, "radius", radius);
|
|||
|
|
|||
|
posNew = null;
|
|||
|
break;
|
|||
|
}
|
|||
|
} while (!!this._canPlaced(posNew, data));
|
|||
|
return posNew;
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* 判断位置是否可放置
|
|||
|
* @param pos 位置
|
|||
|
* @param node 放置物体
|
|||
|
* @returns
|
|||
|
*/
|
|||
|
private _canPlaced(pos: Vec3, node: Node) {
|
|||
|
let modelArray: ModelComponent[] = this.node.parent?.getComponentsInChildren(ModelComponent) as ModelComponent[];
|
|||
|
let flag: boolean = false;
|
|||
|
let model1: ModelComponent = node.getComponentInChildren(ModelComponent) as ModelComponent;
|
|||
|
node.setWorldPosition(pos);
|
|||
|
|
|||
|
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, model1.node.scale, 0.5 *(model1.node.parent as Node).scale.x);
|
|||
|
obb1.halfExtents.y *= 2;
|
|||
|
obb2.halfExtents = Vec3.multiplyScalar(v3_2, model2.node.scale, 0.5 * (model2.node.parent as Node).scale.x);
|
|||
|
obb1.translateAndRotate(model1.node.worldMatrix, model1.node.worldRotation, obb1);
|
|||
|
obb2.translateAndRotate(model2.node.worldMatrix, model2.node.worldRotation, obb2);
|
|||
|
if (geometry.intersect.obbWithOBB(obb1, obb2)) {
|
|||
|
return true;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
return flag;
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* 获取场景金币数
|
|||
|
* @param props 道具数据
|
|||
|
* @returns
|
|||
|
*/
|
|||
|
public getCoinNum(props: Prop[]) {
|
|||
|
let result: Prop[] = props.filter((value: Prop) => {
|
|||
|
return value.type === PropType.COIN && value.exist;
|
|||
|
});
|
|||
|
return result.length;
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* 获取场景锤头数
|
|||
|
* @param props 道具数据
|
|||
|
* @returns
|
|||
|
*/
|
|||
|
public getHammerNum(props: Prop[]) {
|
|||
|
let result: Prop[] = props.filter((value: Prop) => {
|
|||
|
return value.type === PropType.HAMMER && value.exist;
|
|||
|
});
|
|||
|
return result.length;
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* 生成被锤子打击后掉落的金币坐标
|
|||
|
* @param num 金币数
|
|||
|
* @param position 掉落位置
|
|||
|
*/
|
|||
|
public createCoinByHammer(num: number, position: Vec3, radius: number = 6) {
|
|||
|
var pos:number[][] = [];
|
|||
|
|
|||
|
for(let i: number = 0; i < num; i++) {
|
|||
|
let randomPos = this.randomDropPos(position, PropType.COIN, radius);
|
|||
|
if (randomPos) {
|
|||
|
pos.push([randomPos.x, randomPos.y, randomPos.z]);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
GobeUtil.instance.createCoin(pos);
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* 创建金币
|
|||
|
* @param pos
|
|||
|
*/
|
|||
|
public createCoinServer(pos:number[][]){
|
|||
|
for(var index:number = 0; index < pos.length; index ++){
|
|||
|
let prop: Prop = this.generateProp(new Vec3(pos[index][0], pos[index][1], pos[index][2]));
|
|||
|
this._parent.currentGameState.props[this.indexProp] = prop;
|
|||
|
prop.dropPosition = new Vec3(pos[index][0], pos[index][1], pos[index][2]);
|
|||
|
this._dicProps[this.indexProp].setWorldPosition(prop.dropPosition);
|
|||
|
this.indexProp++;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|