完善配表

建筑物升级界面逻辑
This commit is contained in:
2026-03-17 10:50:43 +08:00
parent 5fbf76323a
commit 5933c11df1
80 changed files with 10962 additions and 2852 deletions

View File

@@ -20,7 +20,7 @@ export default class ResMgr implements IResMgr {
// 如果请求的是SpriteFrame类型先加载ImageAsset再转换为SpriteFrame
// 使用js.isChildClassOf来判断type是否是SpriteFrame的子类
if (js.isChildClassOf(type, SpriteFrame)) {
asset = await _this.loadWithName(assetName, ImageAsset, onLoaded) as Asset;
asset = await _this.loadWithName(assetName, ImageAsset) as Asset;
}else{
asset = await _this.loadWithName(assetName, type, onLoaded) as Asset;
}
@@ -31,6 +31,7 @@ export default class ResMgr implements IResMgr {
_this._tagMap.get(tag).push(asset);
if (js.isChildClassOf(type, SpriteFrame)) {
let spriteFrame = SpriteFrame.createWithImage(asset as ImageAsset)
onLoaded && onLoaded(spriteFrame as T)
return spriteFrame as T
}
return asset as T;

View File

@@ -7,8 +7,8 @@ export default abstract class BTLeafNode extends BTNode {
super.start();
this.onStart();
if(this.constructor.name.includes("Employee"))
console.log(this.constructor.name,BTNodeStatus[this.status])
// if(this.constructor.name.includes("Employee"))
// console.log(this.constructor.name,BTNodeStatus[this.status])
}
tick(): void {

View File

@@ -26,6 +26,15 @@ export enum BuilderConst {
Table11 = "Table11",
Table12 = "Table12",
Table13 = "Table13",
Table14 = "Table14",
Table15 = "Table15",
Table16 = "Table16",
Table17 = "Table17",
Table18 = "Table18",
Table19 = "Table19",
Table20 = "Table20",
Office1 = "Office1",
Office2 = "Office2",

View File

@@ -3,4 +3,5 @@ export enum ViewConst {
MainView = "MainView",
EmployeeView = "EmployeeView",
UpgradeView = "UpgradeView",
BuildUpgradeView = "BuildUpgradeView",
}

View File

@@ -13,6 +13,12 @@ export enum WorldEvent {
TaskTableDirtyChange = "World_TaskTableDirtyChange",
/** 等级提升 */
LevelUp = "World_LevelUp",
/** 建筑预览事件,参数: builderConst, level, modelIndex */
WorldBuildPreview = "WorldBuildPreview",
/** 建筑选择事件,参数: builderConst, level, modelIndex, modelName */
BuildSelect = "World_BuildSelect",
/** 建筑模型还原事件,参数: builderConst, level */
BuildModelRestore = "World_BuildModelRestore",
}
export enum TriggerActionType {
@@ -144,10 +150,18 @@ export const WorldInfoMap: { [key: string]: { x: number, y: number, z: number, p
[BuilderConst.Pack]: { x: 8.9, y: 0, z: -1.8, p: "Pack", c: "Pack", is2D: false },
[BuilderConst.BSDCashier]: { x: 6.3, y: 0, z: -6.5, p: "BSDCashier", c: "BSDCashier", is2D: false },
// 未实现
[BuilderConst.ColaMachine1]: { x: 8.5, y: 0.55, z: 1.8, p: "ColaMachine", c: "ColaMachine", is2D: false },
[BuilderConst.ColaMachine2]: { x: 8.5, y: 0.55, z: 5.1, p: "ColaMachine", c: "ColaMachine", is2D: false },
[BuilderConst.Cashier2]: { x: 8.5, y: 0.55, z: 5.1, p: "Cashier", c: "Cashier", is2D: false },
[BuilderConst.Cashier2]: { x: 4.3, y: 0.55, z: 15.5, p: "Cashier", c: "Cashier", is2D: false },
[BuilderConst.ColaMachine1]: { x: 8.5, y: 0.55, z: 13.85, p: "ColaMachine", c: "ColaMachine", is2D: false },
[BuilderConst.ColaMachine2]: { x: 8.5, y: 0.55, z: 17.25, p: "ColaMachine", c: "ColaMachine", is2D: false },
[BuilderConst.Table13]: { x: 0, y: 0, z: 13.5, p: "Table1", c: "Table", is2D: false },
[BuilderConst.Table14]: { x: -4.3, y: 0, z: 17.2, p: "Table1", c: "Table", is2D: false },
[BuilderConst.Table15]: { x: -4.3, y: 0, z: 13.5, p: "Table1", c: "Table", is2D: false },
[BuilderConst.Table16]: { x: -0.9, y: 0, z: 21.4, p: "Table3", c: "Table", is2D: false },
[BuilderConst.Table17]: { x: -0.9, y: 0, z: 23.5, p: "Table3", c: "Table", is2D: false },
[BuilderConst.Table18]: { x: -9.5, y: 0, z: 18.5, p: "Table5", c: "Table", is2D: false },
[BuilderConst.Table19]: { x: -0.9, y: 0, z: 21, p: "Table5", c: "Table", is2D: false },
[BuilderConst.Table20]: { x: -0.9, y: 0, z: 23.5, p: "Table5", c: "Table", is2D: false },
}
export enum BuilderPosEnum {

View File

@@ -13,6 +13,8 @@ import { BaseBuilder } from "./builder/BaseBuilder";
import { TableBuilder } from "./builder/TableBuilder";
import { Customer } from "./character/Customer";
import NodeUtils from "../../../base/utility/node/NodeUtils";
import { ViewConst } from "../../../define/ViewConst";
import { LayerConst } from "../../../define/LayerConst";
declare global {
interface Window {
@@ -36,8 +38,8 @@ export default class WorldModel extends BaseModel {
worldCapacityMap: { [key: string]: number } = {
[BuilderConst.DoorMoneyHeap]: 999980,
}
worldWorkMap: { [key: string]: boolean } = { }
worldWorkMap: { [key: string]: boolean } = {}
worldMap: { [key: string]: Node } = {}
@@ -60,7 +62,7 @@ export default class WorldModel extends BaseModel {
}
registerView(): void {
// App.UIViewMgr.register(ViewConst.LoadingView, LayerConst.UI, "LoadingView");
App.UIViewMgr.register(ViewConst.BuildUpgradeView, LayerConst.UI, "BuildUpgradeView");
}
initConfig(): void {
@@ -147,7 +149,7 @@ export default class WorldModel extends BaseModel {
let exp = this.worldVo.exp;
let maxLevel = this._WorldLevelConfig.length > 0 ? this._WorldLevelConfig[this._WorldLevelConfig.length - 1].id + 1 : 1;
let newLevel = 1;
// 遍历等级配置,找到当前经验对应的等级
for (let i = 0; i < this._WorldLevelConfig.length; i++) {
if (exp >= this._WorldLevelConfig[i].exp) {
@@ -157,12 +159,12 @@ export default class WorldModel extends BaseModel {
break;
}
}
// 限制最大等级
if (newLevel > maxLevel) {
newLevel = maxLevel;
}
// 等级提升时更新
if (newLevel > this.worldVo.level) {
this.worldVo.level = newLevel;
@@ -170,9 +172,12 @@ export default class WorldModel extends BaseModel {
}
}
upgradeWorldBuilderLevel(builderKey: string) {
upgradeWorldBuilderLevel(builderKey: string,isBuildUpgrade:boolean) {
let level = this.worldVo.buildLevelMap[builderKey] ?? 0
this.worldVo.buildLevelMap[builderKey] = level + 1
if (level > 0 && isBuildUpgrade) {
App.UIViewMgr.open(ViewConst.BuildUpgradeView, builderKey)
}
App.EventMgr.emit(WorldEvent.upgradeWorldBuilderLevel, builderKey)
}
@@ -226,7 +231,7 @@ export default class WorldModel extends BaseModel {
getCustomerMoveSpeed(customerType: CustomerConst): number {
let config = this._CustomerConfig[customerType]
if (!config) return 1
// 从config配置表中获取BaseSpeed然后乘以顾客的速度倍率
let baseSpeed = this._SceneLevelConfig["BaseSpeed"] || 100
return baseSpeed * config.moveSpeed
@@ -242,7 +247,7 @@ export default class WorldModel extends BaseModel {
if (!config) return 1
return config.moveSpeed
}
/**
* 计算移动时间(秒)
* @param distance 距离
@@ -272,7 +277,7 @@ export default class WorldModel extends BaseModel {
let targetTable: TableBuilder = null
let maxCustomerCount = -1
let targetSeatIndex = -1
// 遍历所有桌子,找出顾客数最多且还有空位的桌子
for (let i = 0; i < this.tableList.length; i++) {
let comp = this.tableList[i].getComponent(TableBuilder)
@@ -283,7 +288,7 @@ export default class WorldModel extends BaseModel {
for (let j = 0; j < comp.customerList.length; j++) {
if (comp.customerList[j] != null) curCustomerCount++
}
// 优先选择顾客数最多的桌子
if (curCustomerCount > maxCustomerCount) {
maxCustomerCount = curCustomerCount
@@ -292,7 +297,7 @@ export default class WorldModel extends BaseModel {
}
}
}
// 如果找到了合适的桌子,分配座位
if (targetTable && targetSeatIndex >= 0) {
targetTable.customerList[targetSeatIndex] = customer
@@ -330,12 +335,12 @@ export default class WorldModel extends BaseModel {
return NodeUtils.S.worldToLocal(worldPos, this.AStarNavNode)
}
changeWorldCapacityMap(key: string, v: number,isEmitEvent = true) {
changeWorldCapacityMap(key: string, v: number, isEmitEvent = true) {
if (!this.worldCapacityMap[key]) this.worldCapacityMap[key] = 0
this.worldCapacityMap[key] += v
isEmitEvent && App.EventMgr.emit(WorldEvent.ChangeCapacity,key,this.worldCapacityMap[key])
isEmitEvent && App.EventMgr.emit(WorldEvent.ChangeCapacity, key, this.worldCapacityMap[key])
}
worldCapacityTempMap: { [key: string]: number } = {}
changeWorldCapacityTempMap(key: string, v: number) {
@@ -343,11 +348,11 @@ export default class WorldModel extends BaseModel {
this.worldCapacityTempMap[key] += v
}
getTipMoney(){
getTipMoney() {
return this._SceneLevelConfig["TipMoney"]
}
getSalesMooney(){
getSalesMooney() {
return this._SceneLevelConfig["SalesMoney"]
}

View File

@@ -1,4 +1,4 @@
import { _decorator, Enum, Node, Vec3 } from 'cc';
import { _decorator, Enum, Node, sp, Vec3 } from 'cc';
import { ItemType } from 'db://assets/scripts/define/ItemConst';
import TimerUtils from 'db://assets/scripts/base/utility/time/TimerUtils';
import WorldModel from '../WorldModel';
@@ -23,6 +23,10 @@ export class AutoCreateBuilder extends BaseBuilder {
@property({ type: GameItemTrigger })
itemTrigger: GameItemTrigger = null;
/** 模型更换组件 - 使用Skeleton显示模型 */
@property({ type: sp.Skeleton, tooltip: "模型Skeleton组件" })
modelSkeleton: sp.Skeleton = null;
tiemrId: string = null;
unuse(...p: any[]): void {
@@ -66,7 +70,6 @@ export class AutoCreateBuilder extends BaseBuilder {
let info = WorldInfoMap[this.builderType]
this.node.setPosition(new Vec3(info.x, info.y, info.z))
this.createTiemr();
// await TimerUtils.S.WaitForOneFrame()
WorldModel.S.builderPosMap[this.builderType] = this.putNode.getWorldPosition()
}
@@ -98,4 +101,22 @@ export class AutoCreateBuilder extends BaseBuilder {
this.updateLayout3DComp();
}
}
/**
* 更换模型 - 使用Skeleton更换模型
* @param builderConst 建筑类型
* @param level 等级
* @param modelIndex 模型索引
*/
protected updateModelImage(builderConst: BuilderConst, level: number, modelIndex: number): void {
if (!this.modelSkeleton) return;
const modelName = `${WorldInfoMap[builderConst].p}_L${level}_${modelIndex}`;
App.ResMgr.load("common", modelName, sp.SkeletonData, (skeletonData: sp.SkeletonData) => {
if (skeletonData && this.modelSkeleton) {
this.modelSkeleton.skeletonData = skeletonData;
}
});
}
}

View File

@@ -1,5 +1,6 @@
import { _decorator, Node, Vec3 } from 'cc';
import { _decorator, Node, Sprite, SpriteFrame, SpriteRenderer, Vec3 } from 'cc';
import { WorldEvent, WorldInfoMap } from '../WorldConst';
import { BuilderConst } from 'db://assets/scripts/define/TriggerConst';
import { GamePickUpTrigger } from '../trigger/GamePickUpTrigger';
import { BaseOptBuilder } from './BaseOptBuilder';
import WorldModel from '../WorldModel';
@@ -29,6 +30,10 @@ export class BSDCashierBuilder extends BaseOptBuilder {
@property({ type: Node })
StoreNode: Node = null;
/** 模型图片更换组件 */
@property({ type: SpriteRenderer, tooltip: "模型图片更换组件" })
modelSprite: SpriteRenderer = null;
async onBuiderTypeChange() {
let info = WorldInfoMap[this.builderType]
this.node.setPosition(new Vec3(info.x, info.y, info.z))
@@ -72,6 +77,24 @@ export class BSDCashierBuilder extends BaseOptBuilder {
this.updateUI();
}
/**
* 更换模型图片
* @param builderConst 建筑类型
* @param level 等级
* @param modelIndex 模型索引
*/
protected updateModelImage(builderConst: BuilderConst, level: number, modelIndex: number): void {
if (!this.modelSprite) return;
const modelName = `${WorldInfoMap[builderConst].p}_L${level}_${modelIndex}`;
App.ResMgr.load("common", modelName, SpriteFrame, (spriteFrame: SpriteFrame) => {
if (spriteFrame && this.modelSprite) {
this.modelSprite.spriteFrame = spriteFrame;
}
});
}
}

View File

@@ -1,4 +1,4 @@
import { _decorator, Node, Vec3, tween, director } from 'cc';
import { _decorator, Node, Sprite, SpriteFrame, Vec3, tween, director, SpriteRenderer } from 'cc';
import { BaseOptBuilder } from './BaseOptBuilder';
import MathUtils from 'db://assets/scripts/base/utility/math/MathUtils';
import TimerUtils from 'db://assets/scripts/base/utility/time/TimerUtils';
@@ -52,6 +52,10 @@ export class BSDPackBuilder extends BaseOptBuilder {
@property({ type: GameItemTrigger })
boxItemTrigger: GameItemTrigger = null;
/** 模型图片更换组件 */
@property({ type: SpriteRenderer, tooltip: "模型图片更换组件" })
modelSprite: SpriteRenderer = null;
// ========== 状态 ==========
canPack: boolean = false;
@@ -330,4 +334,22 @@ export class BSDPackBuilder extends BaseOptBuilder {
this.cashier.active = this.forceActivePickUp
this.updateUI();
}
/**
* 更换模型图片
* @param builderConst 建筑类型
* @param level 等级
* @param modelIndex 模型索引
*/
protected updateModelImage(builderConst: BuilderConst, level: number, modelIndex: number): void {
if (!this.modelSprite) return;
const modelName = `${WorldInfoMap[builderConst].p}_L${level}_${modelIndex}`;
App.ResMgr.load("common", modelName, SpriteFrame, (spriteFrame: SpriteFrame) => {
if (spriteFrame && this.modelSprite) {
this.modelSprite.spriteFrame = spriteFrame;
}
});
}
}

View File

@@ -2,6 +2,8 @@ import { _decorator, Component, Enum, Node, Vec3 } from 'cc';
import IPoolItem from 'db://assets/scripts/base/system/pool/interface/IPoolItem';
import { BuilderConst } from 'db://assets/scripts/define/TriggerConst';
import { Layout3DComp } from '../comp/Layout3DComp';
import { WorldEvent, WorldInfoMap } from '../WorldConst';
import WorldModel from '../WorldModel';
const { ccclass, property } = _decorator;
@ccclass('BaseBuilder')
@@ -9,10 +11,14 @@ export abstract class BaseBuilder extends Component implements IPoolItem{
@property({type:[Layout3DComp]})
layout3DComps: Layout3DComp[] = [];
abstract unuse(...p: any[]): void
abstract reuse(...p: any[]): void
reuse(...p: any[]): void {
this.addEventListener()
}
unuse(...p: any[]): void {
this.removeEventListener()
}
abstract onBuiderTypeChange():void
@@ -20,6 +26,7 @@ export abstract class BaseBuilder extends Component implements IPoolItem{
public set builderType(v : BuilderConst) {
this._builderType = v;
this.addEventListener()
this.onBuiderTypeChange();
}
@@ -32,6 +39,80 @@ export abstract class BaseBuilder extends Component implements IPoolItem{
this.layout3DComps[i].updateLayoutNodes()
}
}
/**
* 基础事件监听 - WorldBuildPreview
* 子类可重写实现图片更换逻辑
*/
protected onWorldBuildPreviewEvent(builderConst: BuilderConst, level: number, modelIndex: number) {
// 如果不是当前建筑类型,不处理
if (this._builderType !== builderConst) return;
// 子类实现具体的预览逻辑
this.updateModelImage(builderConst, level, modelIndex);
}
/**
* 基础事件监听 - BuildSelect
* 子类可重写实现图片更换逻辑
*/
protected onBuildSelectEvent(builderConst: BuilderConst, level: number, modelIndex: number, modelName: string) {
// 如果不是当前建筑类型,不处理
if (this._builderType !== builderConst) return;
// 子类实现具体的选中逻辑
this.updateModelImage(builderConst, level, modelIndex);
}
/**
* 还原建筑模型 - 默认调用updateModelImage子类可重写
*/
protected onRestoreModel(builderConst: BuilderConst, level: number, modelIndex: number, modelName: string) {
// 默认调用updateModelImage进行图片更换
this.updateModelImage(builderConst, level, modelIndex);
}
/**
* 更换模型图片 - 子类可重写实现具体的图片更换逻辑
* @param builderConst 建筑类型
* @param level 等级
* @param modelIndex 模型索引
*/
protected updateModelImage(builderConst: BuilderConst, level: number, modelIndex: number) {
// 子类实现具体的图片更换逻辑
}
/** 基础事件监听 - BuildModelRestore */
protected onBuildModelRestoreEvent(builderConst: BuilderConst, level: number) {
// 如果不是当前建筑类型,不处理
if (this._builderType !== builderConst) return;
// 从vo中获取保存的模型选择
const key = `${builderConst}_${level}`;
const savedModelIndex = WorldModel.S.worldVo.buildModelSelectMap[key];
// 如果有保存的模型索引,还原成对应的模型
if (savedModelIndex) {
const modelName = `${WorldInfoMap[builderConst].p}_L${level}_${savedModelIndex}`;
this.onRestoreModel(builderConst, level, savedModelIndex, modelName);
}
}
/** 添加基础事件监听 - WorldBuildPreview和BuildSelect和BuildModelRestore */
protected addEventListener() {
App.EventMgr.on(WorldEvent.WorldBuildPreview, this.onWorldBuildPreviewEvent, this)
App.EventMgr.on(WorldEvent.BuildSelect, this.onBuildSelectEvent, this)
App.EventMgr.on(WorldEvent.BuildModelRestore, this.onBuildModelRestoreEvent, this)
}
/** 移除基础事件监听 */
protected removeEventListener() {
App.EventMgr.off(WorldEvent.WorldBuildPreview, this.onWorldBuildPreviewEvent, this)
App.EventMgr.off(WorldEvent.BuildSelect, this.onBuildSelectEvent, this)
App.EventMgr.off(WorldEvent.BuildModelRestore, this.onBuildModelRestoreEvent, this)
}
protected onDestroy(): void {
this.removeEventListener()
}
}

View File

@@ -1,5 +1,6 @@
import { _decorator, Node, Vec3 } from 'cc';
import { _decorator, Node, Sprite, SpriteFrame, SpriteRenderer, Vec3 } from 'cc';
import { WorldEvent, WorldInfoMap } from '../WorldConst';
import { BuilderConst } from 'db://assets/scripts/define/TriggerConst';
import { GamePickUpTrigger } from '../trigger/GamePickUpTrigger';
import { BaseOptBuilder } from './BaseOptBuilder';
import WorldModel from '../WorldModel';
@@ -27,8 +28,12 @@ export class CashierBuilder extends BaseOptBuilder {
@property({ type: Node })
StoreNode: Node = null;
canPickUp: boolean = false
/** 模型图片更换组件 */
@property({ type: SpriteRenderer, tooltip: "模型图片更换组件" })
modelSprite: SpriteRenderer = null;
canPickUp: boolean = false
0
async onBuiderTypeChange() {
let info = WorldInfoMap[this.builderType]
this.node.setPosition(new Vec3(info.x, info.y, info.z))
@@ -80,6 +85,24 @@ export class CashierBuilder extends BaseOptBuilder {
this.updateUI();
}
/**
* 更换模型图片
* @param builderConst 建筑类型
* @param level 等级
* @param modelIndex 模型索引
*/
protected updateModelImage(builderConst: BuilderConst, level: number, modelIndex: number): void {
if (!this.modelSprite) return;
const modelName = `${WorldInfoMap[builderConst].p}_L${level}_${modelIndex}`;
App.ResMgr.load("common", modelName, SpriteFrame, (spriteFrame: SpriteFrame) => {
if (spriteFrame && this.modelSprite) {
this.modelSprite.spriteFrame = spriteFrame;
}
});
}
}

View File

@@ -1,5 +1,6 @@
import { _decorator, CCInteger, Node, Vec2, Vec3 } from 'cc';
import { _decorator, CCInteger, Node, Sprite, SpriteFrame, SpriteRenderer, Vec2, Vec3 } from 'cc';
import { CustomerBehaviorConst, WorldEvent, WorldInfoMap } from '../WorldConst';
import { BuilderConst } from 'db://assets/scripts/define/TriggerConst';
import { BaseBuilder } from './BaseBuilder';
import { GameItemTrigger } from '../trigger/GameItemTrigger';
import { Customer } from '../character/Customer';
@@ -24,12 +25,17 @@ export class TableBuilder extends BaseBuilder {
@property({ type: Node })
dirtySeatNode: Node = null
@property({ type: GameItemTrigger })
pickupTrigger: GameItemTrigger = null;
@property({ type: GameRubbishTrigger })
rubbishTrigger: GameRubbishTrigger = null;
/** 模型图片更换组件 */
@property({ type: SpriteRenderer, tooltip: "模型图片更换组件" })
modelSprite: SpriteRenderer = null;
customerList: Customer[] = []
public get isDirty() : boolean {
@@ -44,7 +50,7 @@ export class TableBuilder extends BaseBuilder {
this.initTableCustomer();
this.updateUI();
WorldModel.S.tableList.push(this)
WorldModel.S.upgradeWorldBuilderLevel(this._builderType+"MoneyHeap")
WorldModel.S.upgradeWorldBuilderLevel(this._builderType+"MoneyHeap",false)
App.EventMgr.on(WorldEvent.ChangeCapacity, this.onChangeCapacityEvent, this)
App.EventMgr.on(WorldEvent.CleanTable, this.onCleanTableEvent, this)
App.EventMgr.on(WorldEvent.upgradeWorldBuilderLevel, this.onUpgradeWorldBuilderLevelEvent, this)
@@ -159,6 +165,24 @@ export class TableBuilder extends BaseBuilder {
this.rubbishTrigger.dirtyNum++
}
/**
* 更换模型图片
* @param builderConst 建筑类型
* @param level 等级
* @param modelIndex 模型索引
*/
protected updateModelImage(builderConst: BuilderConst, level: number, modelIndex: number): void {
if (!this.modelSprite) return;
const modelName = `${WorldInfoMap[builderConst].p}_L${level}_${modelIndex}`;
App.ResMgr.load("common", modelName, SpriteFrame, (spriteFrame: SpriteFrame) => {
if (spriteFrame && this.modelSprite) {
this.modelSprite.spriteFrame = spriteFrame;
}
});
}
}

View File

@@ -20,7 +20,6 @@ export default class ActionsQueue extends BTActionNode {
onStart(): void {
this.curCustomer.customerBehaviorConst = CustomerBehaviorConst.Queue
this.queueMove();
console.log("Queue")
}
onExecute(): void {
@@ -42,10 +41,8 @@ export default class ActionsQueue extends BTActionNode {
if (curPos.x != endPos.x || curPos.y != endPos.y) {
this.isMoving = true
this.curCustomer.changeAnim(CharacterAnimEnum.Run);
console.log("移动")
tween(this.curCustomer.node).to(1, { x: endPos.x, z: endPos.z })
.call(() => {
console.log("站稳")
this.curCustomer.changeAnim(CharacterAnimEnum.Idle);
this.isMoving = false
})

View File

@@ -180,7 +180,7 @@ export class UnlockComp extends Component {
if (this.info.triggerType == 1) { //走到指定位置
WorldModel.S.worldVo.unlocProgressMap[this.info.id] = curFinishMoney + t
this.tryFinishTask();
} else if (this.info.triggerType == 2) { //投钱解锁
} else if (this.info.triggerType == 2 || this.info.triggerType == 3) { //投钱解锁
let stepNum = Math.min(this.info.p - curFinishMoney, Math.floor(this.info.p * 0.2))
let canStepNum = Math.min(WorldModel.S.worldVo.money, stepNum)
if (canStepNum > 0) {
@@ -188,9 +188,7 @@ export class UnlockComp extends Component {
WorldModel.S.worldVo.unlocProgressMap[this.info.id] = curFinishMoney + canStepNum
this.tweenProgress(t, curFinishMoney, curFinishMoney + canStepNum)
}
} else if (this.info.triggerType == 3) { //升级:设备
}
}
}
public checkFinish() {
@@ -225,9 +223,9 @@ export class UnlockComp extends Component {
if (this.info.triggerType == 1) { //走到指定位置
} else if (this.info.triggerType == 2) { //投钱解锁
WorldModel.S.upgradeWorldBuilderLevel(this.info.unlockBuild)
WorldModel.S.upgradeWorldBuilderLevel(this.info.unlockBuild,false)
} else if (this.info.triggerType == 3) { //升级:设备
WorldModel.S.upgradeWorldBuilderLevel(this.info.unlockBuild)
WorldModel.S.upgradeWorldBuilderLevel(this.info.unlockBuild,true)
}
this.node.setParent(App.getPersistRootNode())
@@ -248,7 +246,7 @@ export class UnlockComp extends Component {
try {
// 加载ImageAssetbundle中存储的图片类型
let spriteFrame = await App.ResMgr.load("world", spriteName, SpriteFrame)
this.normalLockTagSprite.spriteFrame = spriteFrame
this.normalLockTagSprite.spriteFrame = spriteFrame
} catch (e) {
console.warn(`Failed to load sprite: ${spriteName}`, e)
}

View File

@@ -1,14 +1,213 @@
import { _decorator, Component, Node } from 'cc';
const { ccclass, property } = _decorator;
@ccclass('BuildUpgradeItem')
export class BuildUpgradeItem extends Component {
start() {
}
update(deltaTime: number) {
}
}
import { _decorator, Component, Sprite, Button, Node, SpriteFrame } from 'cc';
import { BuilderConst } from 'db://assets/scripts/define/TriggerConst';
import { WorldEvent, WorldInfoMap } from '../WorldConst';
import WorldModel from '../WorldModel';
import { ViewConst } from 'db://assets/scripts/define/ViewConst';
const { ccclass, property } = _decorator;
@ccclass('BuildUpgradeItem')
export class BuildUpgradeItem extends Component {
@property({ type: Sprite, tooltip: "模型图片" })
private iconSprite: Sprite = null;
@property({ type: Button, tooltip: "免费选择按钮" })
private freeBtn: Button = null;
@property({ type: Button, tooltip: "看广告选择按钮" })
private adBtn: Button = null;
@property({ type: Node, tooltip: "选中指示节点,预览时显示" })
private selectNode: Node = null;
private _builderConst: BuilderConst = null;
private _level: number = 0;
private _modelIndex: number = 0;
/**
* 初始化组件数据
* @param builderConst 建筑类型
* @param level 当前等级
* @param modelIndex 模型索引 (1, 2, 或 3)
*/
init(builderConst: BuilderConst, level: number, modelIndex: number): void {
this._builderConst = builderConst;
this._level = level;
this._modelIndex = modelIndex;
// 初始化时隐藏选中节点
this.hideSelectNode();
// 根据modelIndex显示对应按钮
// 模型1/2: 显示freeBtn
// 模型3: 显示adBtn或freeBtn如果已解锁
this.refreshButtons();
// 加载图片
this.loadIcon();
}
/**
* 显示选中节点
*/
public showSelectNode(): void {
if (this.selectNode) {
this.selectNode.active = true;
}
}
/**
* 隐藏选中节点
*/
public hideSelectNode(): void {
if (this.selectNode) {
this.selectNode.active = false;
}
}
/**
* 刷新按钮显示状态
*/
private refreshButtons(): void {
if (this._modelIndex === 3) {
// 模型3需要检查解锁状态
if (this.isUnlocked()) {
// 已解锁显示freeBtn隐藏adBtn和lockMask
this.freeBtn && (this.freeBtn.node.active = true);
this.adBtn && (this.adBtn.node.active = false);
} else {
// 未解锁显示adBtn和lockMask隐藏freeBtn
this.freeBtn && (this.freeBtn.node.active = false);
this.adBtn && (this.adBtn.node.active = true);
}
} else {
// 模型1/2显示freeBtn
this.freeBtn && (this.freeBtn.node.active = true);
this.adBtn && (this.adBtn.node.active = false);
}
}
/**
* 加载图标图片
* 图片名称规则: ${BuilderConst}_L${level}_${modelIndex}
* 例如: Table1_L2_1, Table1_L2_2, Table1_L2_3
*/
private loadIcon(): void {
this.iconSprite.spriteFrame = null;
const modelName = this.getModelName();
// 使用App.ResMgr加载图片资源
// 注意这里假设资源已经存在于resources目录中
// 实际使用可能需要根据项目资源组织方式调整
if (this.iconSprite) {
App.ResMgr.load("common", modelName, SpriteFrame, (spriteFrame: any) => {
if (spriteFrame && this.iconSprite) {
this.iconSprite.spriteFrame = spriteFrame;
}
});
}
}
/**
* 预览按钮点击回调
*/
onPreview(): void {
// 显示选中节点
this.showSelectNode();
const modelName = this.getModelName();
App.EventMgr.emit(WorldEvent.WorldBuildPreview, this._builderConst, this._level, this._modelIndex, modelName);
}
/**
* 免费选择按钮点击回调
*/
onFreeSelect(): void {
// 保存选择到vo
this.saveModelSelection();
const modelName = this.getModelName();
App.EventMgr.emit(WorldEvent.BuildSelect, this._builderConst, this._level, this._modelIndex, modelName);
App.UIViewMgr.close(ViewConst.BuildUpgradeView)
}
/**
* 看广告选择按钮点击回调(预留接口)
* 您实现看广告逻辑后调用unlockModel()
*/
onAdSelect(): void {
// TODO: 实现看广告逻辑
// 看广告成功后调用 unlockModel() 解锁模型
// 示例:
// App.AdsMgr.showRewardAd(() => {
// this.unlockModel();
// });
console.log("BuildUpgradeItem: 看广告选择 - 需要实现看广告逻辑");
// 暂时直接解锁用于测试
this.unlockModel();
// 保存选择到vo
this.saveModelSelection();
const modelName = this.getModelName();
App.EventMgr.emit(WorldEvent.BuildSelect, this._builderConst, this._level, this._modelIndex, modelName);
App.UIViewMgr.close(ViewConst.BuildUpgradeView)
}
/**
* 保存模型选择到vo
*/
private saveModelSelection(): void {
const key = `${this._builderConst}_${this._level}`;
WorldModel.S.worldVo.buildModelSelectMap[key] = this._modelIndex;
}
/**
* 解锁模型
* 保存解锁状态到WorldVo.superModelUnlockMap
*/
unlockModel(): void {
if (this._modelIndex !== 3) return;
const unlockKey = `${this._builderConst}_${this._level}_3`;
WorldModel.S.worldVo.superModelUnlockMap[unlockKey] = true;
// 显示freeBtn隐藏adBtn
if (this.freeBtn) {
this.freeBtn.node.active = true;
}
if (this.adBtn) {
this.adBtn.node.active = false;
}
}
/**
* 检查当前模型是否已解锁
* @returns 是否已解锁
*/
isUnlocked(): boolean {
if (this._modelIndex !== 3) return true; // 模型1/2默认已解锁
const unlockKey = `${this._builderConst}_${this._level}_3`;
return WorldModel.S.worldVo.superModelUnlockMap[unlockKey] === true;
}
/**
* 获取模型名称
* @returns 模型名称
*/
private getModelName(): string {
return `${WorldInfoMap[this._builderConst].p}_L${this._level}_${this._modelIndex}`;
// // 模型3使用Super前缀
// if (this._modelIndex === 3) {
// return `Super${this._builderConst}_${this._level}`;
// }
// // 模型1/2使用普通名称
// return `${this._builderConst}_${this._level}`;
}
}

View File

@@ -1,14 +1,136 @@
import { _decorator, Component, Node } from 'cc';
const { ccclass, property } = _decorator;
@ccclass('BuildUpgradeView')
export class BuildUpgradeView extends Component {
start() {
}
update(deltaTime: number) {
}
}
import { _decorator, Label } from 'cc';
import BaseView from 'db://assets/scripts/base/app/mamager/preset/uiViewMgr/BaseView';
import { BuilderConst } from 'db://assets/scripts/define/TriggerConst';
import WorldModel from '../WorldModel';
import { BuildUpgradeItem } from './BuildUpgradeItem';
import { WorldEvent } from '../WorldConst';
const { ccclass, property } = _decorator;
@ccclass('BuildUpgradeView')
export default class BuildUpgradeView extends BaseView {
@property({ type: Label, tooltip: "当前建筑等级Label" })
private levelLabel: Label = null;
@property({ type: BuildUpgradeItem, tooltip: "模型1" })
private item1: BuildUpgradeItem = null;
@property({ type: BuildUpgradeItem, tooltip: "模型2" })
private item2: BuildUpgradeItem = null;
@property({ type: BuildUpgradeItem, tooltip: "模型3" })
private item3: BuildUpgradeItem = null;
private _builderConst: BuilderConst = null;
/**
* 打开视图
* @param builderConst 建筑类型
*/
public open(builderConst: BuilderConst): void {
super.open(builderConst);
this._builderConst = builderConst;
this.refreshUI();
}
/**
* 刷新UI显示
*/
public refreshUI(): void {
if (!this._builderConst) return;
// 获取当前建筑等级
const level = WorldModel.S.worldVo.buildLevelMap[this._builderConst] ?? 0;
// 更新等级Label显示
if (this.levelLabel) {
this.levelLabel.string = `当前等级: ${level}`;
}
// 初始化3个BuildUpgradeItem
if (this.item1) {
this.item1.init(this._builderConst, level, 1);
}
if (this.item2) {
this.item2.init(this._builderConst, level, 2);
}
if (this.item3) {
this.item3.init(this._builderConst, level, 3);
}
// 默认选中当前使用的皮肤
this.setDefaultSelectedSkin(level);
}
/**
* 设置默认选中的皮肤
* @param level 建筑等级
*/
private setDefaultSelectedSkin(level: number): void {
// 从vo中获取保存的模型选择
const key = `${this._builderConst}_${level}`;
const savedModelIndex = WorldModel.S.worldVo.buildModelSelectMap[key];
// 检查保存的模型索引是否有效1、2、3中的一个
const isValidModelIndex = savedModelIndex === 1 || savedModelIndex === 2 || savedModelIndex === 3;
// 如果有保存的模型索引且有效选中对应的item
if (savedModelIndex && isValidModelIndex) {
if (savedModelIndex === 1 && this.item1) {
this.item1.showSelectNode();
} else if (savedModelIndex === 2 && this.item2) {
this.item2.showSelectNode();
} else if (savedModelIndex === 3 && this.item3) {
this.item3.showSelectNode();
}
} else {
// 没有保存的模型选择或模型索引无效,默认选中第一个,并将数据修改为第一个
// 更新vo数据为第一个模型
WorldModel.S.worldVo.buildModelSelectMap[key] = 1;
if (this.item1) {
this.item1.onPreview();
}
}
}
public addEventListener(): void {
// 监听预览事件,隐藏所有选中节点后显示当前预览的选中节点
App.EventMgr.on(WorldEvent.WorldBuildPreview, this.onBuildPreviewEvent, this);
}
public removeEventListener(): void {
App.EventMgr.off(WorldEvent.WorldBuildPreview, this.onBuildPreviewEvent, this);
}
/**
* 预览事件回调 - 隐藏所有item的选中节点
*/
private onBuildPreviewEvent(builderConst: BuilderConst, level: number, modelIndex: number): void {
// 隐藏所有item的选中节点
this.item1 && this.item1.hideSelectNode();
this.item2 && this.item2.hideSelectNode();
this.item3 && this.item3.hideSelectNode();
// 显示当前预览的item的选中节点
if (modelIndex === 1 && this.item1) {
this.item1.showSelectNode();
} else if (modelIndex === 2 && this.item2) {
this.item2.showSelectNode();
} else if (modelIndex === 3 && this.item3) {
this.item3.showSelectNode();
}
}
public close(...params: any[]): void {
super.close(...params);
// 关闭时触发建筑模型还原事件让世界场景中的建筑还原成vo中对应的模型
const level = WorldModel.S.worldVo.buildLevelMap[this._builderConst] ?? 0;
if (level > 0) {
App.EventMgr.emit(WorldEvent.BuildModelRestore, this._builderConst, level);
}
}
}

View File

@@ -5,7 +5,7 @@ let TAG: string = "WorldVo";
export default class WorldVo extends BaseVo {
// @AutoSave(TAG, "level", 0)
// @AutoSave(TAG, "level", 1)
level: number = 1;
// @AutoSave(TAG, "exp", 0)
@@ -20,7 +20,16 @@ export default class WorldVo extends BaseVo {
// @AutoSave(TAG, "buildLevelMap", {})
buildLevelMap:{[key:string]:number} = {}
// @AutoSave(TAG, "unlocProgressMap", 0)
// @AutoSave(TAG, "unlocProgressMap", {})
unlocProgressMap:{[key:number]:number} = {}
// 付费模型解锁状态存储Key规则: ${builderConst}_${level}_3例如: Table1_2_3
// @AutoSave(TAG, "superModelUnlockMap", {})
superModelUnlockMap: { [key: string]: boolean } = {};
// 建筑模型选择存储Key规则: ${builderConst}_${level}Value: modelIndex
// 例如: Table1_2 -> 2 表示Table1在2级时选择了模型2
// @AutoSave(TAG, "buildModelSelectMap", {})
buildModelSelectMap: { [key: string]: number } = {};
}