Compare commits
2 Commits
748f901e01
...
f841779e94
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f841779e94 | ||
|
|
31f5340866 |
9
assets/Scripts.meta
Normal file
9
assets/Scripts.meta
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"ver": "1.2.0",
|
||||||
|
"importer": "directory",
|
||||||
|
"imported": true,
|
||||||
|
"uuid": "3e36fd17-8df9-4f4f-8904-61ad60e7a3e9",
|
||||||
|
"files": [],
|
||||||
|
"subMetas": {},
|
||||||
|
"userData": {}
|
||||||
|
}
|
||||||
9
assets/Scripts/wx_clound_client_api.meta
Normal file
9
assets/Scripts/wx_clound_client_api.meta
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"ver": "1.2.0",
|
||||||
|
"importer": "directory",
|
||||||
|
"imported": true,
|
||||||
|
"uuid": "91afed13-a3a6-4666-8f0a-c3259c5f6fa5",
|
||||||
|
"files": [],
|
||||||
|
"subMetas": {},
|
||||||
|
"userData": {}
|
||||||
|
}
|
||||||
84
assets/Scripts/wx_clound_client_api/WxCloudApi.ts
Normal file
84
assets/Scripts/wx_clound_client_api/WxCloudApi.ts
Normal file
@@ -0,0 +1,84 @@
|
|||||||
|
export type CloudReturnType<T = any> = {
|
||||||
|
code: number,// 200成功
|
||||||
|
msg?:string,
|
||||||
|
data?:T
|
||||||
|
}
|
||||||
|
|
||||||
|
export class WxCloudApi{
|
||||||
|
/**
|
||||||
|
* @en init the cloud
|
||||||
|
* @zh 初始化云客户端(只调用一次即可)
|
||||||
|
* @param {string} env 云环境名称
|
||||||
|
*/
|
||||||
|
public static init(env:string){
|
||||||
|
wx?.cloud.init({
|
||||||
|
env: env
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @en Login to the cloud
|
||||||
|
* @zh 登录云
|
||||||
|
* @return 返回结果
|
||||||
|
* 参考:
|
||||||
|
* result.result = {
|
||||||
|
* code: number, // 200成功,其他都是失败
|
||||||
|
* msg: string, // 如果失败,这里是失败原因等信息
|
||||||
|
* data: { // 成功才有
|
||||||
|
* openid: string, // 用户微信平台openid
|
||||||
|
* regist_time: number, // 时间戳,用户注册时间
|
||||||
|
* game_data: object, // 开发者自己保存的数据
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
* 如果这个泛型令你报错(一般是因为你删了wx.api.d.ts导致),请使用以下签名:
|
||||||
|
* login():Promise<{result: CloudReturnType<{openid: string, regist_time: number, game_data: object}>}>
|
||||||
|
* 或者你是个“不拘小节”的老哥,可以用以下简洁版签名(参考上方的数据结构例子使用即可)
|
||||||
|
* login():Promise<any>
|
||||||
|
*/
|
||||||
|
public static async login(): Promise<CloudCallFunctionResult<CloudReturnType<{
|
||||||
|
openid:string,
|
||||||
|
regist_time:number,
|
||||||
|
game_data:any
|
||||||
|
}>>>{
|
||||||
|
return await wx?.cloud.callFunction({
|
||||||
|
name: 'cocos_cloud',
|
||||||
|
data: {
|
||||||
|
cmd: "login"
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @en Save game data to the cloud
|
||||||
|
* @zh 把客户端数据写入云,此为全覆盖写入,请自行管理完整数据
|
||||||
|
* @return 返回结果
|
||||||
|
* 参考:
|
||||||
|
* result.result = {
|
||||||
|
* code: number, // 200成功,其他都是失败
|
||||||
|
* msg: string, // 如果失败,这里是失败原因等信息
|
||||||
|
* data: {
|
||||||
|
* errMsg: "document.update:ok", // 数据库返回结果
|
||||||
|
* stats: {
|
||||||
|
* updated: number, // 更新了几条数据(正常是1)
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
* 如果这个泛型令你报错(一般是因为你删了wx.api.d.ts导致),请使用以下签名:
|
||||||
|
* save(gameData: any): Promise<{resoult:CloudReturnType}>
|
||||||
|
* 或者你是个“不拘小节”的老哥,可以用以下简洁版签名(参考上方的数据结构例子使用即可)
|
||||||
|
* login():Promise<any>
|
||||||
|
*/
|
||||||
|
public static async save(gameData: any): Promise<CloudCallFunctionResult<CloudReturnType<{
|
||||||
|
errMsg: string,
|
||||||
|
status:{
|
||||||
|
updated: number
|
||||||
|
}
|
||||||
|
}>>> {
|
||||||
|
return await wx?.cloud.callFunction({
|
||||||
|
name: 'cocos_cloud',
|
||||||
|
data: {
|
||||||
|
cmd: 'save',
|
||||||
|
data: gameData
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
"ver": "4.0.24",
|
"ver": "4.0.24",
|
||||||
"importer": "typescript",
|
"importer": "typescript",
|
||||||
"imported": true,
|
"imported": true,
|
||||||
"uuid": "25122cff-7274-4f86-9f74-f82258b39fab",
|
"uuid": "6cae54d1-19a6-458d-ba26-92e6ada39b58",
|
||||||
"files": [],
|
"files": [],
|
||||||
"subMetas": {},
|
"subMetas": {},
|
||||||
"userData": {}
|
"userData": {}
|
||||||
29
assets/Scripts/wx_clound_client_api/wx.aip.d.ts
vendored
Normal file
29
assets/Scripts/wx_clound_client_api/wx.aip.d.ts
vendored
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
// 注意:此文件是为了引入微信接口
|
||||||
|
// !!如果这个文件,与你的wx.d.ts因为定义重复报错,你可以删除本文件!!
|
||||||
|
|
||||||
|
// @ts-ignore
|
||||||
|
declare class wx {
|
||||||
|
public static cloud: Cloud;
|
||||||
|
}
|
||||||
|
// @ts-ignore
|
||||||
|
declare class Cloud {
|
||||||
|
public init(options: {
|
||||||
|
env?: string | {
|
||||||
|
database?: string
|
||||||
|
storage?: string
|
||||||
|
functions?: string
|
||||||
|
},
|
||||||
|
traceUser?: boolean//default true
|
||||||
|
});
|
||||||
|
public callFunction(obj: {
|
||||||
|
name: string,
|
||||||
|
data?: any,
|
||||||
|
config?: { env: string },
|
||||||
|
}): Promise<CloudCallFunctionResult>;
|
||||||
|
}
|
||||||
|
// @ts-ignore
|
||||||
|
declare type CloudCallFunctionResult<T = any> = {
|
||||||
|
result: T,
|
||||||
|
errMsg: string,
|
||||||
|
requestID: string
|
||||||
|
}
|
||||||
9
assets/Scripts/wx_clound_client_api/wx.aip.d.ts.meta
Normal file
9
assets/Scripts/wx_clound_client_api/wx.aip.d.ts.meta
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"ver": "4.0.24",
|
||||||
|
"importer": "typescript",
|
||||||
|
"imported": true,
|
||||||
|
"uuid": "c0e94674-fd35-4f37-a57c-694b85dddbd0",
|
||||||
|
"files": [],
|
||||||
|
"subMetas": {},
|
||||||
|
"userData": {}
|
||||||
|
}
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -1,13 +0,0 @@
|
|||||||
{
|
|
||||||
"ver": "1.1.50",
|
|
||||||
"importer": "prefab",
|
|
||||||
"imported": true,
|
|
||||||
"uuid": "93fda804-b794-4119-a287-952a70be15cb",
|
|
||||||
"files": [
|
|
||||||
".json"
|
|
||||||
],
|
|
||||||
"subMetas": {},
|
|
||||||
"userData": {
|
|
||||||
"syncNodeName": "guide1"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -1,13 +0,0 @@
|
|||||||
{
|
|
||||||
"ver": "1.1.50",
|
|
||||||
"importer": "prefab",
|
|
||||||
"imported": true,
|
|
||||||
"uuid": "26b4ba5a-c5e4-405a-8ce9-27be21f86171",
|
|
||||||
"files": [
|
|
||||||
".json"
|
|
||||||
],
|
|
||||||
"subMetas": {},
|
|
||||||
"userData": {
|
|
||||||
"syncNodeName": "guide2"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -1,13 +0,0 @@
|
|||||||
{
|
|
||||||
"ver": "1.1.50",
|
|
||||||
"importer": "prefab",
|
|
||||||
"imported": true,
|
|
||||||
"uuid": "9864952d-1b4a-4fb8-9e10-05ae52a1befb",
|
|
||||||
"files": [
|
|
||||||
".json"
|
|
||||||
],
|
|
||||||
"subMetas": {},
|
|
||||||
"userData": {
|
|
||||||
"syncNodeName": "guide3"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -1,13 +0,0 @@
|
|||||||
{
|
|
||||||
"ver": "1.1.50",
|
|
||||||
"importer": "prefab",
|
|
||||||
"imported": true,
|
|
||||||
"uuid": "d2dcd02d-b49b-45ea-8e20-1cc474837da9",
|
|
||||||
"files": [
|
|
||||||
".json"
|
|
||||||
],
|
|
||||||
"subMetas": {},
|
|
||||||
"userData": {
|
|
||||||
"syncNodeName": "guide4"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -48,7 +48,6 @@ export class SingletonModuleComp extends ecs.Comp {
|
|||||||
heroGrid: [-1, -1, -1, -1, -1, -1],
|
heroGrid: [-1, -1, -1, -1, -1, -1],
|
||||||
monGrid: [-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1],
|
monGrid: [-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1],
|
||||||
};
|
};
|
||||||
finish_guides: number[] = [0]
|
|
||||||
data: any = {
|
data: any = {
|
||||||
score: 0,
|
score: 0,
|
||||||
mission: 1,
|
mission: 1,
|
||||||
@@ -57,12 +56,16 @@ export class SingletonModuleComp extends ecs.Comp {
|
|||||||
task: 0,
|
task: 0,
|
||||||
noStop: false,
|
noStop: false,
|
||||||
showInfo: true,
|
showInfo: true,
|
||||||
|
/** 新手指引完成标记:false=需要提醒,true=已提醒过(仅提醒 1 次) */
|
||||||
|
tip_done: {
|
||||||
|
start: false, // 主页开始按钮
|
||||||
|
hero: false, // 召唤英雄面板按钮
|
||||||
|
equip: false, // 购买装备面板按钮
|
||||||
|
skill: false, // 购买技能卷轴面板按钮
|
||||||
|
shop: false, // 购买药品面板按钮
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
guides: any = [0, 0, 0, 0, 0]
|
|
||||||
current_guide: number = 0
|
|
||||||
|
|
||||||
vmdata: any = {
|
vmdata: any = {
|
||||||
game_over: false,
|
game_over: false,
|
||||||
game_pause: false,
|
game_pause: false,
|
||||||
|
|||||||
@@ -26,10 +26,6 @@ export enum UIID {
|
|||||||
HInfo,
|
HInfo,
|
||||||
/** 技能卡牌系统核心控制器 */
|
/** 技能卡牌系统核心控制器 */
|
||||||
SkillBox,
|
SkillBox,
|
||||||
Guide1,
|
|
||||||
Guide2,
|
|
||||||
Guide3,
|
|
||||||
Guide4,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 打开界面方式的配置数据 */
|
/** 打开界面方式的配置数据 */
|
||||||
@@ -47,8 +43,5 @@ export var UIConfigData: { [key: number]: UIConfig } = {
|
|||||||
[UIID.Mission]: { layer: LayerType.UI, prefab: "gui/element/mission" },
|
[UIID.Mission]: { layer: LayerType.UI, prefab: "gui/element/mission" },
|
||||||
[UIID.HInfo]: { layer: LayerType.UI, prefab: "gui/element/hnode" },
|
[UIID.HInfo]: { layer: LayerType.UI, prefab: "gui/element/hnode" },
|
||||||
[UIID.SkillBox]: { layer: LayerType.UI, prefab: "gui/element/skillbox" },
|
[UIID.SkillBox]: { layer: LayerType.UI, prefab: "gui/element/skillbox" },
|
||||||
[UIID.Guide1]: { layer: LayerType.PopUp, prefab: "gui/element/guide1" },
|
|
||||||
[UIID.Guide2]: { layer: LayerType.PopUp, prefab: "gui/element/guide2" },
|
|
||||||
[UIID.Guide3]: { layer: LayerType.PopUp, prefab: "gui/element/guide3" },
|
|
||||||
[UIID.Guide4]: { layer: LayerType.PopUp, prefab: "gui/element/guide4" },
|
|
||||||
}
|
}
|
||||||
@@ -1,74 +0,0 @@
|
|||||||
|
|
||||||
import { mLogger } from "../common/Logger";
|
|
||||||
import { _decorator, Animation, AnimationClip, EventTouch, Label, Node, NodeEventType, Sprite, SpriteAtlas, Tween, tween, UIOpacity, Vec3, resources, Light, UITransform, Widget, CCInteger, CCString, Component } from "cc";
|
|
||||||
import { smc } from "../common/SingletonModuleComp";
|
|
||||||
import { UIID } from "../common/config/GameUIConfig";
|
|
||||||
import { oops } from "db://oops-framework/core/Oops";
|
|
||||||
|
|
||||||
const { ccclass, property } = _decorator;
|
|
||||||
|
|
||||||
@ccclass('GuideComp')
|
|
||||||
export class GuideComp extends Component {
|
|
||||||
/** 是否开启调试日志 */
|
|
||||||
private debugMode: boolean = true;
|
|
||||||
|
|
||||||
// ======================== 编辑器绑定节点 ========================
|
|
||||||
|
|
||||||
/** 引导编号 ID */
|
|
||||||
@property({ type: CCInteger })
|
|
||||||
guide_id: number = 0
|
|
||||||
|
|
||||||
onLoad() {
|
|
||||||
// 监听自身节点(即弹窗任意位置)的点击事件
|
|
||||||
this.node.on(NodeEventType.TOUCH_START, this.onTouchStart, this);
|
|
||||||
this.node.on(NodeEventType.TOUCH_END, this.onGuideClick, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
private onTouchStart(event: EventTouch) {
|
|
||||||
// 允许事件穿透,确保底层的实际功能按钮能正常接收到 TOUCH_START 事件
|
|
||||||
event.preventSwallow = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private onGuideClick(event: EventTouch) {
|
|
||||||
// 记录该引导 ID 已完成
|
|
||||||
if (!smc.finish_guides.includes(this.guide_id)) {
|
|
||||||
smc.finish_guides.push(this.guide_id);
|
|
||||||
mLogger.log(this.debugMode, 'Guide', `完成引导 ID: ${this.guide_id}`);
|
|
||||||
|
|
||||||
// TODO: 若需要持久化保存,可在此处调用本地存储或同步到服务器的方法
|
|
||||||
// oops.storage.set("finish_guides", smc.finish_guides);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 允许事件穿透,确保底层的实际功能按钮能正常接收到点击事件
|
|
||||||
event.preventSwallow = true;
|
|
||||||
|
|
||||||
// 因为通过 oops.gui.open(UIID) 弹出的界面,根节点可能会带有一个阻挡点击的遮罩组件(BlockInputEvents)
|
|
||||||
// 所以应当通过 oops.gui.remove 彻底从框架的层级管理中移除当前界面。
|
|
||||||
let targetUIID = -1;
|
|
||||||
if (this.guide_id === 1) targetUIID = UIID.Guide1;
|
|
||||||
if (this.guide_id === 2) targetUIID = UIID.Guide2;
|
|
||||||
if (this.guide_id === 3) targetUIID = UIID.Guide3;
|
|
||||||
if (this.guide_id === 4) targetUIID = UIID.Guide4;
|
|
||||||
|
|
||||||
if (targetUIID !== -1) {
|
|
||||||
oops.gui.remove(targetUIID);
|
|
||||||
} else {
|
|
||||||
// 兜底方案
|
|
||||||
this.node.active = false;
|
|
||||||
this.node.destroy();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 组件销毁时解绑所有事件,防止残留回调 */
|
|
||||||
onDestroy() {
|
|
||||||
if (this.node && this.node.isValid) {
|
|
||||||
this.node.off(NodeEventType.TOUCH_START, this.onTouchStart, this);
|
|
||||||
this.node.off(NodeEventType.TOUCH_END, this.onGuideClick, this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 外部初始化入口(由 MissionGuideComp 调用) */
|
|
||||||
init() {
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -226,20 +226,18 @@ export class MissionCardComp extends CCComp {
|
|||||||
|
|
||||||
// ======================== 新手按钮指引 ========================
|
// ======================== 新手按钮指引 ========================
|
||||||
|
|
||||||
/** 新手按钮指引 ID(写入 finish_guides,已占用 0~4,此处用 5) */
|
|
||||||
private static readonly BUTTON_GUIDE_ID: number = 5;
|
|
||||||
/** 新手按钮指引抖动最大角度(度) */
|
/** 新手按钮指引抖动最大角度(度) */
|
||||||
private static readonly BUTTON_GUIDE_SHAKE_ANGLE: number = 10;
|
private static readonly BUTTON_GUIDE_SHAKE_ANGLE: number = 10;
|
||||||
/** 新手按钮指引每步时长(秒) */
|
/** 新手按钮指引每步时长(秒) */
|
||||||
private static readonly BUTTON_GUIDE_STEP_DURATION: number = 4.2;
|
private static readonly BUTTON_GUIDE_STEP_DURATION: number = 4.2;
|
||||||
/** 新手按钮指引气泡停留时长(秒) */
|
/** 新手按钮指引气泡停留时长(秒) */
|
||||||
private static readonly BUTTON_GUIDE_TIP_STAY: number = 3.4;
|
private static readonly BUTTON_GUIDE_TIP_STAY: number = 3.4;
|
||||||
/** 指引步骤配置:按钮节点取值器 + 气泡文案 */
|
/** 指引步骤配置:完成标记键(smc.data.tip_done)+ 按钮节点取值器 + 气泡文案 */
|
||||||
private readonly guideSteps: Array<{ getBtn: () => Node | null, text: string }> = [
|
private readonly guideSteps: Array<{ key: "hero" | "equip" | "skill" | "shop", getBtn: () => Node | null, text: string }> = [
|
||||||
{ getBtn: () => this.showHeros, text: "这里召唤英雄" },
|
{ key: "hero", getBtn: () => this.showHeros, text: "这里召唤英雄" },
|
||||||
{ getBtn: () => this.showEquips, text: "这里购买装备" },
|
{ key: "equip", getBtn: () => this.showEquips, text: "这里购买装备" },
|
||||||
{ getBtn: () => this.showSkills, text: "这里购买技能卷轴" },
|
{ key: "skill", getBtn: () => this.showSkills, text: "这里购买技能卷轴" },
|
||||||
{ getBtn: () => this.showShop, text: "这里购买药品" },
|
{ key: "shop", getBtn: () => this.showShop, text: "这里购买药品" },
|
||||||
];
|
];
|
||||||
/** 当前指引下标(-1 = 未在指引中) */
|
/** 当前指引下标(-1 = 未在指引中) */
|
||||||
private guideStepIndex: number = -1;
|
private guideStepIndex: number = -1;
|
||||||
@@ -488,14 +486,10 @@ export class MissionCardComp extends CCComp {
|
|||||||
private onFightStart() {
|
private onFightStart() {
|
||||||
this.enterBattlePhase();
|
this.enterBattlePhase();
|
||||||
|
|
||||||
// 第一次进入战斗阶段,关闭guide4
|
|
||||||
if (!smc.finish_guides.includes(4)) {
|
|
||||||
smc.finish_guides.push(4);
|
|
||||||
oops.gui.remove(UIID.Guide4);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 首次进入战斗阶段:启动按钮逐个指引(仅提醒 1 次)
|
// 首次进入战斗阶段:启动按钮逐个指引(仅提醒 1 次,全部完成则自动跳过)
|
||||||
if (!smc.finish_guides.includes(MissionCardComp.BUTTON_GUIDE_ID)) {
|
const tips = smc.data.tip_done;
|
||||||
|
if (!tips.hero || !tips.equip || !tips.skill || !tips.shop) {
|
||||||
this.playButtonGuide();
|
this.playButtonGuide();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -749,12 +743,7 @@ export class MissionCardComp extends CCComp {
|
|||||||
this.updatePanelButtonsInteractable();
|
this.updatePanelButtonsInteractable();
|
||||||
}
|
}
|
||||||
|
|
||||||
// 第一次召唤英雄后,关闭guide3
|
|
||||||
// 注:首个英雄召唤后战斗自动开始(见 MissionComp),不再需要 Guide4 引导点击开始按钮
|
|
||||||
if (!smc.finish_guides.includes(3)) {
|
|
||||||
smc.finish_guides.push(3);
|
|
||||||
oops.gui.remove(UIID.Guide3);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 英雄登场后同步英雄信息盒
|
// 英雄登场后同步英雄信息盒
|
||||||
this.refreshHeroBoxSlots();
|
this.refreshHeroBoxSlots();
|
||||||
@@ -941,12 +930,27 @@ export class MissionCardComp extends CCComp {
|
|||||||
/**
|
/**
|
||||||
* 启动新手按钮指引:依次指引 英雄→装备→技能→药品 四个面板按钮。
|
* 启动新手按钮指引:依次指引 英雄→装备→技能→药品 四个面板按钮。
|
||||||
* 每步播放 bg/icon 循环抖动 + smalltip 气泡文案,
|
* 每步播放 bg/icon 循环抖动 + smalltip 气泡文案,
|
||||||
* 全部播放完成后写入 smc.finish_guides,仅提醒 1 次。
|
* 已完成的步骤(smc.data.tip_done 对应键为 true)自动跳过,仅提醒 1 次。
|
||||||
*/
|
*/
|
||||||
private playButtonGuide() {
|
private playButtonGuide() {
|
||||||
// 确保无旧指引残留,再从头开始
|
// 确保无旧指引残留,再从头开始
|
||||||
this.stopButtonGuide();
|
this.stopButtonGuide();
|
||||||
this.guideStepIndex = 0;
|
this.guideStepIndex = -1;
|
||||||
|
this.nextButtonGuideStep();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 推进到下一个未完成指引的步骤;全部完成则结束 */
|
||||||
|
private nextButtonGuideStep() {
|
||||||
|
this.guideStepIndex++;
|
||||||
|
// 跳过已完成的步骤
|
||||||
|
while (this.guideStepIndex < this.guideSteps.length
|
||||||
|
&& smc.data.tip_done[this.guideSteps[this.guideStepIndex].key]) {
|
||||||
|
this.guideStepIndex++;
|
||||||
|
}
|
||||||
|
if (this.guideStepIndex >= this.guideSteps.length) {
|
||||||
|
this.finishButtonGuide();
|
||||||
|
return;
|
||||||
|
}
|
||||||
this.playButtonGuideStep();
|
this.playButtonGuideStep();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -961,22 +965,16 @@ export class MissionCardComp extends CCComp {
|
|||||||
}
|
}
|
||||||
this.scheduleOnce(() => {
|
this.scheduleOnce(() => {
|
||||||
this.stopGuideShake(btn);
|
this.stopGuideShake(btn);
|
||||||
this.guideStepIndex++;
|
// 本步提醒完成:记录完成标记(即使中止也只标记已播完的步骤)
|
||||||
if (this.guideStepIndex < this.guideSteps.length) {
|
smc.data.tip_done[step.key] = true;
|
||||||
this.playButtonGuideStep();
|
this.nextButtonGuideStep();
|
||||||
} else {
|
|
||||||
this.finishButtonGuide();
|
|
||||||
}
|
|
||||||
}, MissionCardComp.BUTTON_GUIDE_STEP_DURATION);
|
}, MissionCardComp.BUTTON_GUIDE_STEP_DURATION);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 指引全部完成:还原气泡文案并记录引导完成标记 */
|
/** 指引全部完成:还原气泡文案 */
|
||||||
private finishButtonGuide() {
|
private finishButtonGuide() {
|
||||||
this.restoreGuideTipTexts();
|
this.restoreGuideTipTexts();
|
||||||
this.guideStepIndex = -1;
|
this.guideStepIndex = -1;
|
||||||
if (!smc.finish_guides.includes(MissionCardComp.BUTTON_GUIDE_ID)) {
|
|
||||||
smc.finish_guides.push(MissionCardComp.BUTTON_GUIDE_ID);
|
|
||||||
}
|
|
||||||
mLogger.log(this.debugMode, "MissionCardComp", "button guide finished");
|
mLogger.log(this.debugMode, "MissionCardComp", "button guide finished");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1019,11 +1017,12 @@ export class MissionCardComp extends CCComp {
|
|||||||
if (!child || !child.isValid) continue;
|
if (!child || !child.isValid) continue;
|
||||||
Tween.stopAllByTarget(child);
|
Tween.stopAllByTarget(child);
|
||||||
child.angle = 0;
|
child.angle = 0;
|
||||||
|
// 单轮抖动约 0.94s(含间歇),节奏放慢避免高频晃动过刺眼
|
||||||
let t = tween(child)
|
let t = tween(child)
|
||||||
.to(0.07, { angle: angle })
|
.to(0.15, { angle: angle })
|
||||||
.to(0.14, { angle: -angle })
|
.to(0.3, { angle: -angle })
|
||||||
.to(0.07, { angle: 0 })
|
.to(0.15, { angle: 0 })
|
||||||
.delay(0.12);
|
.delay(0.34);
|
||||||
if (repeat) {
|
if (repeat) {
|
||||||
t = t.repeatForever();
|
t = t.repeatForever();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,7 +17,7 @@
|
|||||||
* - GameEvent.MissionStart / MissionEnd —— 游戏生命周期事件
|
* - GameEvent.MissionStart / MissionEnd —— 游戏生命周期事件
|
||||||
* - UIID.Mission —— 战斗界面 ID
|
* - UIID.Mission —— 战斗界面 ID
|
||||||
*/
|
*/
|
||||||
import { _decorator, instantiate, Prefab, resources, Sprite, SpriteAtlas, UITransform ,Node} from "cc";
|
import { _decorator, instantiate, Label, Prefab, resources, Sprite, SpriteAtlas, Tween, tween, UITransform, Vec3, Node } from "cc";
|
||||||
import { ecs } from "../../../../extensions/oops-plugin-framework/assets/libs/ecs/ECS";
|
import { ecs } from "../../../../extensions/oops-plugin-framework/assets/libs/ecs/ECS";
|
||||||
import { CCComp } from "../../../../extensions/oops-plugin-framework/assets/module/common/CCComp";
|
import { CCComp } from "../../../../extensions/oops-plugin-framework/assets/module/common/CCComp";
|
||||||
import { oops } from "../../../../extensions/oops-plugin-framework/assets/core/Oops";
|
import { oops } from "../../../../extensions/oops-plugin-framework/assets/core/Oops";
|
||||||
@@ -39,7 +39,9 @@ const { ccclass, property } = _decorator;
|
|||||||
export class MissionHomeComp extends CCComp {
|
export class MissionHomeComp extends CCComp {
|
||||||
/** 调试日志开关 */
|
/** 调试日志开关 */
|
||||||
debugMode: boolean = false;
|
debugMode: boolean = false;
|
||||||
|
/** 开始游戏按钮节点(预留) */
|
||||||
|
@property(Node)
|
||||||
|
start_btn=null!
|
||||||
/** 主页按钮节点(预留) */
|
/** 主页按钮节点(预留) */
|
||||||
@property(Node)
|
@property(Node)
|
||||||
home_btn=null!
|
home_btn=null!
|
||||||
@@ -61,6 +63,20 @@ export class MissionHomeComp extends CCComp {
|
|||||||
@property(Node)
|
@property(Node)
|
||||||
ranks_page=null!
|
ranks_page=null!
|
||||||
|
|
||||||
|
// ======================== 新手指引(开始按钮抖动 + 气泡) ========================
|
||||||
|
|
||||||
|
/** 抖动最大角度(度) */
|
||||||
|
private static readonly SHAKE_ANGLE: number = 10;
|
||||||
|
/** 气泡文案 */
|
||||||
|
private static readonly TIP_TEXT: string = "点击开始游戏";
|
||||||
|
/** 气泡弹出/停留/收起节奏(秒) */
|
||||||
|
private static readonly TIP_STAY: number = 3.4;
|
||||||
|
|
||||||
|
/** 指引进行中标记(避免重复启动) */
|
||||||
|
private guiding: boolean = false;
|
||||||
|
/** 气泡原文缓存(指引结束后还原) */
|
||||||
|
private guideTipOriginText: string = "";
|
||||||
|
|
||||||
|
|
||||||
/** 注册任务结束事件 */
|
/** 注册任务结束事件 */
|
||||||
protected onLoad(): void {
|
protected onLoad(): void {
|
||||||
@@ -70,10 +86,10 @@ export class MissionHomeComp extends CCComp {
|
|||||||
/** 启动时显示主页 */
|
/** 启动时显示主页 */
|
||||||
start() {
|
start() {
|
||||||
this.home_active()
|
this.home_active()
|
||||||
|
|
||||||
// 首次打开游戏打开guide1
|
// 新玩家:start_btn 抖动 + smalltip 气泡引导点击开始(仅 1 次)
|
||||||
if (!smc.finish_guides.includes(1)) {
|
if (!smc.data.tip_done.start) {
|
||||||
oops.gui.open(UIID.Guide1);
|
this.playStartGuide();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -93,19 +109,91 @@ export class MissionHomeComp extends CCComp {
|
|||||||
*/
|
*/
|
||||||
start_mission() {
|
start_mission() {
|
||||||
mLogger.log(this.debugMode, 'MissionHomeComp', "start_mission")
|
mLogger.log(this.debugMode, 'MissionHomeComp', "start_mission")
|
||||||
|
|
||||||
// 进入战斗后,关闭guide1
|
// 点击开始后完成指引:停止抖动/气泡并记录完成标记
|
||||||
if (!smc.finish_guides.includes(1)) {
|
this.stopStartGuide();
|
||||||
smc.finish_guides.push(1);
|
smc.data.tip_done.start = true;
|
||||||
oops.gui.remove(UIID.Guide1);
|
|
||||||
}
|
|
||||||
|
|
||||||
oops.gui.open(UIID.Mission)
|
oops.gui.open(UIID.Mission)
|
||||||
this.node.active=false;
|
this.node.active=false;
|
||||||
|
|
||||||
// 隐藏 mapLayer 下的 main 节点
|
// 隐藏 mapLayer 下的 main 节点
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// ======================== 新手指引实现 ========================
|
||||||
|
|
||||||
|
/** 启动指引:button 子节点循环抖动 + smalltip 气泡弹出 */
|
||||||
|
private playStartGuide() {
|
||||||
|
const btn = this.start_btn;
|
||||||
|
if (!btn || !btn.isValid) return;
|
||||||
|
if (this.guiding) return;
|
||||||
|
this.guiding = true;
|
||||||
|
|
||||||
|
// start_btn 下名为 "Button" 的子节点循环抖动(angle 往复,不触碰 position,避免与布局冲突)
|
||||||
|
const shakeNode = this.getShakeNode();
|
||||||
|
if (shakeNode) {
|
||||||
|
Tween.stopAllByTarget(shakeNode);
|
||||||
|
shakeNode.angle = 0;
|
||||||
|
tween(shakeNode)
|
||||||
|
.to(0.15, { angle: MissionHomeComp.SHAKE_ANGLE })
|
||||||
|
.to(0.3, { angle: -MissionHomeComp.SHAKE_ANGLE })
|
||||||
|
.to(0.15, { angle: 0 })
|
||||||
|
.delay(0.34)
|
||||||
|
.repeatForever()
|
||||||
|
.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
// smalltip 气泡:缓存原文后覆盖文案,弹出后保持显示直至点击
|
||||||
|
const tip = btn.getChildByName("smalltip");
|
||||||
|
if (tip) {
|
||||||
|
const label = tip.getComponentInChildren(Label);
|
||||||
|
if (label) {
|
||||||
|
this.guideTipOriginText = label.string;
|
||||||
|
label.string = MissionHomeComp.TIP_TEXT;
|
||||||
|
}
|
||||||
|
tip.active = true;
|
||||||
|
Tween.stopAllByTarget(tip);
|
||||||
|
tip.setScale(0, 0, 1);
|
||||||
|
tween(tip)
|
||||||
|
.to(0.15, { scale: new Vec3(1.1, 1.1, 1) }, { easing: 'quadOut' })
|
||||||
|
.to(0.05, { scale: new Vec3(1, 1, 1) })
|
||||||
|
.start();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 停止指引:抖动复位、气泡收起并还原原文 */
|
||||||
|
private stopStartGuide() {
|
||||||
|
if (!this.guiding) return;
|
||||||
|
this.guiding = false;
|
||||||
|
|
||||||
|
const btn = this.start_btn;
|
||||||
|
if (btn && btn.isValid) {
|
||||||
|
const shakeNode = this.getShakeNode();
|
||||||
|
if (shakeNode && shakeNode.isValid) {
|
||||||
|
Tween.stopAllByTarget(shakeNode);
|
||||||
|
shakeNode.angle = 0;
|
||||||
|
}
|
||||||
|
const tip = btn.getChildByName("smalltip");
|
||||||
|
if (tip && tip.isValid) {
|
||||||
|
Tween.stopAllByTarget(tip);
|
||||||
|
const label = tip.getComponentInChildren(Label);
|
||||||
|
if (label) label.string = this.guideTipOriginText;
|
||||||
|
tip.active = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取 start_btn 下名为 "Button" 的子节点(即要抖动的节点)。
|
||||||
|
* @returns Button 子节点;未找到返回 null
|
||||||
|
*/
|
||||||
|
private getShakeNode(): Node | null {
|
||||||
|
const btn = this.start_btn;
|
||||||
|
if (!btn || !btn.isValid) return null;
|
||||||
|
const node = btn.getChildByName("Button");
|
||||||
|
return node && node.isValid ? node : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private showPage(page: Node) {
|
private showPage(page: Node) {
|
||||||
@@ -153,6 +241,8 @@ export class MissionHomeComp extends CCComp {
|
|||||||
|
|
||||||
/** 激活主页显示:刷新数据并显示节点 */
|
/** 激活主页显示:刷新数据并显示节点 */
|
||||||
home_active(){
|
home_active(){
|
||||||
|
// 任务结束回到主页:确保指引动画与气泡无残留
|
||||||
|
this.stopStartGuide();
|
||||||
this.uodate_data()
|
this.uodate_data()
|
||||||
this.hideAllPages()
|
this.hideAllPages()
|
||||||
this.node.active=true
|
this.node.active=true
|
||||||
@@ -177,6 +267,8 @@ export class MissionHomeComp extends CCComp {
|
|||||||
|
|
||||||
/** ECS 组件移除时销毁节点 */
|
/** ECS 组件移除时销毁节点 */
|
||||||
reset() {
|
reset() {
|
||||||
|
// 销毁前清理指引 tween,防止回调残留
|
||||||
|
this.stopStartGuide();
|
||||||
this.node.destroy();
|
this.node.destroy();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -48,13 +48,8 @@ exports.main = async (event, context) => {
|
|||||||
msg: `Save fail, ${JSON.stringify(saveDataRes)}`
|
msg: `Save fail, ${JSON.stringify(saveDataRes)}`
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}else if (event?.cmd === "get") {
|
|
||||||
let user = await getOrCreaterUser(db, wxContext.OPENID);
|
|
||||||
return {
|
|
||||||
code: 200,
|
|
||||||
data: user,
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
code: -2,
|
code: -2,
|
||||||
msg: `Unknow cmd: ${event?.cmd}`,
|
msg: `Unknow cmd: ${event?.cmd}`,
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user