消消方块阵换皮表情
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

413 lines
15 KiB

import { _decorator, CCBoolean, ccenum, CCString, Component, Enum, EventTouch, Input, Label, math, Node, Sprite, SpriteFrame, Vec2, Vec3 } from 'cc';
import { GBundle, GPath, UIID } from '../../game/ConfigRes';
import { SpriteLoad } from 'db://assets/mx/components/SpriteLoad';
import { MapGrid } from './MapGrid';
import { GEvent } from 'db://assets/mx/module/event/GEvent';
import { TableNames } from '../../game/ConfigTableData';
import { EDITOR } from 'cc/env';
import { BattleType } from '../../manager/ChapterDataManager';
/**
* 障碍物类型
*/
export enum ObstacleType {
/**无 */
= 999999,
/**静态障碍物 */
= 0,
/**普通 */
= 1,
/**炸弹 */
= 2,
/**银币 */
= 3,
/**减速 */
= 4,
/**火炉 */
= 5,
/**吹风机 */
= 6,
/**灯塔 */
= 7,
/**藤蔓 */
= 8,
/**加速门 */
= 9,//占用格子,可通行
/**血包 */
= 10,
/**屏蔽 */
= 11,
}
const { ccclass, property, executeInEditMode } = _decorator;
@ccclass('MapObstacle')
@executeInEditMode
export class MapObstacle extends Component {
/** 标记:本帧/本次操作里 tryEditAction 是否触发了“银币获取弹窗” */
private static _openedCoinPanelByEditAction: boolean = false;
public static consumeOpenedCoinPanelByEditAction(): boolean {
const v = MapObstacle._openedCoinPanelByEditAction;
MapObstacle._openedCoinPanelByEditAction = false;
return v;
}
@property({ type: Enum(ObstacleType) })
type: ObstacleType = ObstacleType.;
@property({ type: SpriteFrame })
set img(value: SpriteFrame) {
this._img = value;
this.icon.spriteFrame = value;
}
get img(): SpriteFrame {
return this._img
}
@property({ type: SpriteFrame })
private _img: SpriteFrame = null;
icon: Sprite = null;
/**所在地图格子对象 */
Grid: MapGrid = null;
/**生成的障碍物节点(具体的机制逻辑所在节点) */
ObstacleNode: Node = null;
/**障碍物数据 */
Data: ITableObstacle = null;
/**机制数据 */
MechanismData: ITablePlaymode = null;
/**铲除前的障碍物类型 */
oldType: ObstacleType = ObstacleType.;
/**进入编辑前格子状态快照(用于取消编辑完整回滚) */
oldIsCanWalk: boolean = true;
oldIsCanPutObstacle: boolean = true;
oldIsCanRemove: boolean = false;
oldIsCanBeThunder: boolean = false;
oldIsBroken: boolean = false;
/**本次编辑已经放置该位置 */
private _isEditPlace: boolean = false;
/**本次在本格放置障碍物时,从本格挤走的怪物及其放置前世界坐标(移除障碍时还原) */
private _displacedMonsters: { node: Node; worldPos: Vec3 }[] = [];
protected onLoad(): void {
this.icon = this.node.getChildByName('icon').getComponent(Sprite);
this.Grid = this.getComponent(MapGrid);
if (this.img) {
this.icon.spriteFrame = this.img;
}
if (this.type == ObstacleType. && this.Grid.isCanWalk)
this.type = ObstacleType.;
}
protected start(): void {
if (EDITOR) return;
this.init();
}
protected onEnable(): void {
this.node.on(Input.EventType.TOUCH_START, this.onTouchStart, this);
this.node.on(Input.EventType.TOUCH_END, this.onTouchEnd, this);
this.node.on(Input.EventType.TOUCH_CANCEL, this.onTouchEnd, this);
GEvent.Ins.on(GEvent.EnterEdit, this.enterEdit, this);
GEvent.Ins.on(GEvent.EndEdit, this.EndEdit, this);
}
protected onDisable(): void {
this.node.off(Input.EventType.TOUCH_START, this.onTouchStart, this);
this.node.off(Input.EventType.TOUCH_END, this.onTouchEnd, this);
this.node.off(Input.EventType.TOUCH_CANCEL, this.onTouchEnd, this);
GEvent.Ins.off(GEvent.EnterEdit, this.enterEdit, this);
GEvent.Ins.off(GEvent.EndEdit, this.EndEdit, this);
}
private onTouchStart(event: EventTouch) {
}
// 触摸结束事件
private onTouchEnd(event: EventTouch) {
this.tryEditAction(true);
}
/** 编辑态单格操作;单点/滑动均复用,保证规则一致 */
public tryEditAction(reportClick: boolean) {
// console.log("触摸结束事件", this.Grid);
if (!gg.game.CurentBattle.IsEdit) return;
if (this.Grid.isCanPutObstacle && this.Grid.isCanWalk) {
this.Grid.isCanWalk = false;
gg.game.CurentBattle.Map.notifyMapWalkStateChanged();
let nothavePath = gg.game.CurentBattle.checkMonsterAndSpawnerReachEnd(this.Grid);
this.Grid.isCanWalk = true;
gg.game.CurentBattle.Map.notifyMapWalkStateChanged();
if (!nothavePath) {
gg.ui.showToast(gg.lang.get("不可将路堵死"));
return;
}
if (gg.game.CurentBattle.BattleType == BattleType.GachaMode) {
if (gg.game.CurentBattle.GachaModeObstacleNum <= 0) {
gg.ui.showToast(gg.lang.get("次数不够"));
return;
}
} else {
if (gg.game.CurentBattle.CurentCoinNum < gg.game.CurentBattle.CurEditObstacleConfig.price) {
if (gg.game.CurentBattle.CurentVideoAddCoinTimes > 0) {
MapObstacle._openedCoinPanelByEditAction = true;
if (gg.ui.panelIsShow(UIID.BattleGetCoin)) return;
gg.ui.openPanel(UIID.BattleGetCoin)
} else {
gg.ui.showToast(gg.lang.get("银币数不够"));
}
return;
}
}
this.placeObstacle();
return;
} else {
if (this.Grid.isCanRemove) {
if (gg.game.CurentBattle.BattleType == BattleType.GachaMode) {
if (gg.game.CurentBattle.GachaModeShovelNum <= 0) {
gg.ui.showToast(gg.lang.get("次数不够"));
return;
} else {
gg.game.CurentBattle.GachaModeShovelNum--;
GEvent.Ins.emit(GEvent.UpdateShovelNum)
}
}
this.remove();
this.updateGrid();
} else {
gg.ui.showToast(gg.lang.get("不可放置!"));
}
}
}
init() {
this.node.getComponent(Sprite).spriteFrame = null;
this.setObstacle(this.type, true);
}
/**放置障碍物 */
placeObstacle() {
if (!this.Grid.isCanPutObstacle) {
// gg.ui.showToast("不可放置!");
return
}
if (!gg.game.CurentBattle.CurEditObstacleConfig) return;
this.Grid.isCanPutObstacle = false;
this.Grid.isCanRemove = true;
this.Grid.isCanBeThunder = true;
this.type = gg.game.CurentBattle.CurEditObstacleConfig.id;
this.Grid.isBroken = false;
console.log(this.Grid.isBroken, '放置后状态为修复状态');
gg.audio.playEffect({ name: "放置障碍物", path: "sound/" });
this._isEditPlace = true;
this.setObstacle(this.type);
this.Grid.isCanWalk = false;
gg.game.CurentBattle.Map.notifyMapWalkStateChanged();
if (gg.game.CurentBattle.GachaModeObstacleNum > 0) {
gg.game.CurentBattle.GachaModeObstacleNum--;
GEvent.Ins.emit(GEvent.UpdateObstacleNum)
} else {
gg.game.CurentBattle.CurentCoinNum -= this.Data.price;
GEvent.Ins.emit(GEvent.UpdateCoin);
}
//放置后状态为修复状态
gg.game.CurentBattle.showWallLinePath();
GEvent.Ins.emit(GEvent.UpdateBestPlace);
this._displacedMonsters.length = 0;
const preMove = this.getMonsterNodesOnThisGrid();
for (let i = 0; i < preMove.length; i++) {
const n = preMove[i];
this._displacedMonsters.push({ node: n, worldPos: n.worldPosition.clone() });
}
this.moveMonster();
}
/**雷击障碍物 */
thunderAtk() {
this.remove();
}
/**设置障碍物 */
setObstacle(type: ObstacleType, remove = false) {
if (this.type == ObstacleType.) return;
this.type = type;
// if (type == ObstacleType.无) {
// if (!remove)
// this.remove();
// } else {
// this.Data = gg.data.table.getTableData<ITableObstacle>(TableNames.Obstacle, this.type);
// this.MechanismData = gg.data.table.getTableData<ITablePlaymode>(TableNames.Playmode, this.Data.playMode);
// this.Grid.isCanWalk = this.Data.canPass == 1;
// if (this.type == ObstacleType.普通障碍物) {
// let name = gg.game.CurentBattle.DefaultBarrier;
// this.setIcon(name);
// if (this.ObstacleNode) {
// gg.res.putNode(this.ObstacleNode);
// }
// } else {
// this.icon.node.active = false;
// console.log(this.Grid.isBroken, 'isBroken状态为修复状态');
// this.ObstacleNode = gg.res.getNode('prefab/障碍物/', this.Data.res, GBundle.BattleMap);
// this.ObstacleNode.parent = this.node;
// this.ObstacleNode.setSiblingIndex(0);
// }
// }
this.updateGrid();
}
/**设置障碍物 */
setIcon(name: string) {
if (!this.icon) {
return;
}
this.icon.node.active = true;
this.icon.node.getOrAddComponent(SpriteLoad).setSprite(GPath.ObstacleItem(name), GBundle.BattleMap);
}
/**移除障碍物 */
remove() {
if (this._isEditPlace) {
this._isEditPlace = false;
gg.game.CurentBattle.CurentCoinNum += this.Data.price;
GEvent.Ins.emit(GEvent.UpdateCoin);
}
if (this.icon) {
this.icon.spriteFrame = null;
//console.log("移除障碍物", this.Grid);
this.icon.node.getComponent(SpriteLoad)?.clear();
}
if (this.ObstacleNode) {
gg.res.putNode(this.ObstacleNode);
this.ObstacleNode = null;
}
this.type = ObstacleType.;
this.Grid.isCanWalk = true;
gg.game.CurentBattle.Map.notifyMapWalkStateChanged();
this.Grid.isCanPutObstacle = true;
this.Grid.isCanRemove = false;
this.Grid.isCanBeThunder = false;
this.Grid.isBroken = false;
if (gg.game.CurentBattle.IsEdit){
gg.game.CurentBattle.showWallLinePath();
GEvent.Ins.emit(GEvent.UpdateBestPlace);
}
if (gg.game.CurentBattle.IsEdit && this._displacedMonsters.length > 0) {
for (let i = 0; i < this._displacedMonsters.length; i++) {
const it = this._displacedMonsters[i];
if (it.node && it.node.isValid) {
it.node.setWorldPosition(it.worldPos);
}
}
this._displacedMonsters.length = 0;
}
}
enterEdit() {
this.oldType = this.type;
this.oldIsCanWalk = this.Grid.isCanWalk;
this.oldIsCanPutObstacle = this.Grid.isCanPutObstacle;
this.oldIsCanRemove = this.Grid.isCanRemove;
this.oldIsCanBeThunder = this.Grid.isCanBeThunder;
this.oldIsBroken = this.Grid.isBroken;
this.updateGrid();
}
EndEdit(isSave: boolean) {
if (isSave) {
this._displacedMonsters.length = 0;
}
if (!isSave) {
// 仅在“本格本次编辑发生过变化”时回滚。
// 1) type 变化:表示放置/铲除后最终类型已不同
// 2) _isEditPlace=true:表示本次发生过放置扣费(即使最终 type 与 oldType 相同,也要退款)
const needRollback = this.type != this.oldType || this._isEditPlace;
if (needRollback) {
// 先移除当前编辑态结果(若本次放置过会在 remove 内自动退款)
this.remove();
// 再恢复到进入编辑前的障碍物类型与表现
this.setObstacle(this.oldType, true);
}
// 取消编辑时完整恢复进入编辑前的格子状态,避免 type 回滚后标志位残留
this.Grid.isCanWalk = this.oldIsCanWalk;
this.Grid.isCanPutObstacle = this.oldIsCanPutObstacle;
this.Grid.isCanRemove = this.oldIsCanRemove;
this.Grid.isCanBeThunder = this.oldIsCanBeThunder;
this.Grid.isBroken = this.oldIsBroken;
this._displacedMonsters.length = 0;
}
this._isEditPlace = false;
this.updateGrid();
}
updateGrid() {
this.getComponent(MapGrid).updateGrid();
}
/**候选落脚格必须能寻路到任一终点 */
private canReachAnyEnd(escapeGrid: MapGrid): boolean {
if (!escapeGrid || !escapeGrid.isCanWalk) return false;
const map = gg.game.CurentBattle.Map;
const endPosArr = map.mapTargetParent.children.map(x => x.worldPosition);
return map.checkAllStartsCanReachAnyEnd([escapeGrid.node.worldPosition], endPosArr, false, this.Grid);
}
/** 与原先顺序一致:上、左、右、下(行列相邻四格),且目标格可达终点 */
moveMonster() {
const map = gg.game.CurentBattle.Map;
const neighbors: [number, number][] = [
[this.Grid.Row - 1, this.Grid.Col],
[this.Grid.Row, this.Grid.Col - 1],
[this.Grid.Row, this.Grid.Col + 1],
[this.Grid.Row + 1, this.Grid.Col],
];
// 同一次放置里,所有怪物的落脚格规则一致,先计算一次目标格再批量移动
let targetGrid: MapGrid = null;
for (let j = 0; j < neighbors.length; j++) {
const [r, c] = neighbors[j];
const grid = map.getMapGrid(r, c);
if (grid && grid.isCanWalk && this.canReachAnyEnd(grid)) {
targetGrid = grid;
break;
}
}
if (!targetGrid) return;
const wp = targetGrid.node.worldPosition;
const arr = this.getMonsterNodesOnThisGrid();
for (let i = 0; i < arr.length; i++) {
const element = arr[i];
element.setWorldPosition(wp.x, wp.y, element.worldPosition.z);
}
}
/**获取当前格上的所有怪物节点 */
getMonsterNodesOnThisGrid() {
let arr: Node[] = [];
let allMonsters = gg.game.CurentBattle.MonsterSpawner.node.children;
for (let i = 0; i < allMonsters.length; i++) {
const element = allMonsters[i];
let g = gg.game.CurentBattle.Map.getMapGridByWorldPos(element.worldPosition);
if (g == this.Grid) {
arr.push(element);
}
}
return arr
}
}