feat: 完善关卡
This commit is contained in:
@@ -23,7 +23,7 @@
|
|||||||
"_active": true,
|
"_active": true,
|
||||||
"_components": [],
|
"_components": [],
|
||||||
"_prefab": {
|
"_prefab": {
|
||||||
"__id__": 17
|
"__id__": 19
|
||||||
},
|
},
|
||||||
"_lpos": {
|
"_lpos": {
|
||||||
"__type__": "cc.Vec3",
|
"__type__": "cc.Vec3",
|
||||||
@@ -54,7 +54,7 @@
|
|||||||
},
|
},
|
||||||
"autoReleaseAssets": false,
|
"autoReleaseAssets": false,
|
||||||
"_globals": {
|
"_globals": {
|
||||||
"__id__": 18
|
"__id__": 20
|
||||||
},
|
},
|
||||||
"_id": "d60530e8-06be-4ac4-8613-9cc604c77f32"
|
"_id": "d60530e8-06be-4ac4-8613-9cc604c77f32"
|
||||||
},
|
},
|
||||||
@@ -72,21 +72,24 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"__id__": 5
|
"__id__": 5
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"__id__": 13
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"_active": true,
|
"_active": true,
|
||||||
"_components": [
|
"_components": [
|
||||||
{
|
|
||||||
"__id__": 13
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"__id__": 14
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"__id__": 15
|
"__id__": 15
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"__id__": 16
|
"__id__": 16
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"__id__": 17
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"__id__": 18
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"_prefab": null,
|
"_prefab": null,
|
||||||
@@ -321,6 +324,70 @@
|
|||||||
"z": 0
|
"z": 0
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"__type__": "cc.Node",
|
||||||
|
"_name": "BgMusic",
|
||||||
|
"_objFlags": 0,
|
||||||
|
"__editorExtras__": {},
|
||||||
|
"_parent": {
|
||||||
|
"__id__": 2
|
||||||
|
},
|
||||||
|
"_children": [],
|
||||||
|
"_active": true,
|
||||||
|
"_components": [
|
||||||
|
{
|
||||||
|
"__id__": 14
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"_prefab": null,
|
||||||
|
"_lpos": {
|
||||||
|
"__type__": "cc.Vec3",
|
||||||
|
"x": 0,
|
||||||
|
"y": 0,
|
||||||
|
"z": 0
|
||||||
|
},
|
||||||
|
"_lrot": {
|
||||||
|
"__type__": "cc.Quat",
|
||||||
|
"x": 0,
|
||||||
|
"y": 0,
|
||||||
|
"z": 0,
|
||||||
|
"w": 1
|
||||||
|
},
|
||||||
|
"_lscale": {
|
||||||
|
"__type__": "cc.Vec3",
|
||||||
|
"x": 1,
|
||||||
|
"y": 1,
|
||||||
|
"z": 1
|
||||||
|
},
|
||||||
|
"_mobility": 0,
|
||||||
|
"_layer": 33554432,
|
||||||
|
"_euler": {
|
||||||
|
"__type__": "cc.Vec3",
|
||||||
|
"x": 0,
|
||||||
|
"y": 0,
|
||||||
|
"z": 0
|
||||||
|
},
|
||||||
|
"_id": "38VfS7SylM/aQYEpxbnNlx"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"__type__": "cc.AudioSource",
|
||||||
|
"_name": "",
|
||||||
|
"_objFlags": 0,
|
||||||
|
"__editorExtras__": {},
|
||||||
|
"node": {
|
||||||
|
"__id__": 13
|
||||||
|
},
|
||||||
|
"_enabled": true,
|
||||||
|
"__prefab": null,
|
||||||
|
"_clip": {
|
||||||
|
"__uuid__": "c33517cc-3f49-493c-8315-150f27cfb40c",
|
||||||
|
"__expectedType__": "cc.AudioClip"
|
||||||
|
},
|
||||||
|
"_loop": true,
|
||||||
|
"_playOnAwake": true,
|
||||||
|
"_volume": 1,
|
||||||
|
"_id": "b5d8rMHKVGLp1OkTMz/YRL"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"__type__": "cc.UITransform",
|
"__type__": "cc.UITransform",
|
||||||
"_name": "",
|
"_name": "",
|
||||||
@@ -425,29 +492,29 @@
|
|||||||
{
|
{
|
||||||
"__type__": "cc.SceneGlobals",
|
"__type__": "cc.SceneGlobals",
|
||||||
"ambient": {
|
"ambient": {
|
||||||
"__id__": 19
|
|
||||||
},
|
|
||||||
"shadows": {
|
|
||||||
"__id__": 20
|
|
||||||
},
|
|
||||||
"_skybox": {
|
|
||||||
"__id__": 21
|
"__id__": 21
|
||||||
},
|
},
|
||||||
"fog": {
|
"shadows": {
|
||||||
"__id__": 22
|
"__id__": 22
|
||||||
},
|
},
|
||||||
"octree": {
|
"_skybox": {
|
||||||
"__id__": 23
|
"__id__": 23
|
||||||
},
|
},
|
||||||
"skin": {
|
"fog": {
|
||||||
"__id__": 24
|
"__id__": 24
|
||||||
},
|
},
|
||||||
"lightProbeInfo": {
|
"octree": {
|
||||||
"__id__": 25
|
"__id__": 25
|
||||||
},
|
},
|
||||||
"postSettings": {
|
"skin": {
|
||||||
"__id__": 26
|
"__id__": 26
|
||||||
},
|
},
|
||||||
|
"lightProbeInfo": {
|
||||||
|
"__id__": 27
|
||||||
|
},
|
||||||
|
"postSettings": {
|
||||||
|
"__id__": 28
|
||||||
|
},
|
||||||
"bakedWithStationaryMainLight": false,
|
"bakedWithStationaryMainLight": false,
|
||||||
"bakedWithHighpLightmap": false
|
"bakedWithHighpLightmap": false
|
||||||
},
|
},
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -1,16 +1,27 @@
|
|||||||
import { _decorator, Node, EditBox, instantiate, Vec3, Button } from 'cc';
|
import { _decorator, Node, EditBox, instantiate, Vec3, Button, Label, Sprite, SpriteFrame, AudioClip, AudioSource } from 'cc';
|
||||||
import { BaseView } from 'db://assets/scripts/core/BaseView';
|
import { BaseView } from 'db://assets/scripts/core/BaseView';
|
||||||
import { ViewManager } from 'db://assets/scripts/core/ViewManager';
|
import { ViewManager } from 'db://assets/scripts/core/ViewManager';
|
||||||
const { ccclass, property } = _decorator;
|
const { ccclass, property } = _decorator;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 关卡配置接口
|
* 关卡配置类
|
||||||
*/
|
*/
|
||||||
export interface LevelConfig {
|
@ccclass('LevelConfig')
|
||||||
/** 需要的输入框数量 */
|
export class LevelConfig {
|
||||||
inputCount: number;
|
@property(SpriteFrame)
|
||||||
/** 题目文本 */
|
mainImage: SpriteFrame | null = null;
|
||||||
questionText?: string;
|
|
||||||
|
@property({ tooltip: '线索1内容(默认解锁)' })
|
||||||
|
clue1: string = '';
|
||||||
|
|
||||||
|
@property({ tooltip: '线索2内容' })
|
||||||
|
clue2: string = '';
|
||||||
|
|
||||||
|
@property({ tooltip: '线索3内容' })
|
||||||
|
clue3: string = '';
|
||||||
|
|
||||||
|
@property({ tooltip: '答案(用于确定输入框数量和验证)' })
|
||||||
|
answer: string = '';
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -35,23 +46,58 @@ export class PageLevel extends BaseView {
|
|||||||
@property(Node)
|
@property(Node)
|
||||||
iconSetting: Node | null = null;
|
iconSetting: Node | null = null;
|
||||||
|
|
||||||
|
@property(Node)
|
||||||
|
tipsLayout: Node | null = null;
|
||||||
|
|
||||||
|
@property(Node)
|
||||||
|
mainImage: Node | null = null;
|
||||||
|
|
||||||
|
@property(Node)
|
||||||
|
tipsItem1: Node | null = null;
|
||||||
|
|
||||||
|
@property(Node)
|
||||||
|
tipsItem2: Node | null = null;
|
||||||
|
|
||||||
|
@property(Node)
|
||||||
|
tipsItem3: Node | null = null;
|
||||||
|
|
||||||
|
@property(Node)
|
||||||
|
unLockItem2: Node | null = null;
|
||||||
|
|
||||||
|
@property(Node)
|
||||||
|
unLockItem3: Node | null = null;
|
||||||
|
|
||||||
|
@property(Label)
|
||||||
|
clockLabel: Label | null = null;
|
||||||
|
|
||||||
// ========== 配置属性 ==========
|
// ========== 配置属性 ==========
|
||||||
|
@property([LevelConfig])
|
||||||
|
levelConfigs: LevelConfig[] = [];
|
||||||
|
|
||||||
@property({
|
@property({
|
||||||
tooltip: '默认输入框数量',
|
min: 0,
|
||||||
min: 1,
|
tooltip: '当前关卡索引'
|
||||||
max: 10
|
|
||||||
})
|
})
|
||||||
defaultInputCount: number = 2;
|
currentLevelIndex: number = 0;
|
||||||
|
|
||||||
|
@property(AudioClip)
|
||||||
|
clickAudio: AudioClip | null = null;
|
||||||
|
|
||||||
|
@property(AudioClip)
|
||||||
|
successAudio: AudioClip | null = null;
|
||||||
|
|
||||||
|
@property(AudioClip)
|
||||||
|
failAudio: AudioClip | null = null;
|
||||||
|
|
||||||
// ========== 内部状态 ==========
|
// ========== 内部状态 ==========
|
||||||
/** 当前输入框数量 */
|
|
||||||
private _inputCount: number = 0;
|
|
||||||
|
|
||||||
/** 当前创建的输入框节点数组 */
|
/** 当前创建的输入框节点数组 */
|
||||||
private _inputNodes: Node[] = [];
|
private _inputNodes: Node[] = [];
|
||||||
|
|
||||||
/** 当前关卡配置 */
|
/** 倒计时剩余秒数 */
|
||||||
private _levelConfig: LevelConfig | null = null;
|
private _countdown: number = 60;
|
||||||
|
|
||||||
|
/** 倒计时是否结束 */
|
||||||
|
private _isTimeUp: boolean = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 页面首次加载时调用
|
* 页面首次加载时调用
|
||||||
@@ -60,6 +106,9 @@ export class PageLevel extends BaseView {
|
|||||||
console.log('[PageLevel] onViewLoad');
|
console.log('[PageLevel] onViewLoad');
|
||||||
this.initLevel();
|
this.initLevel();
|
||||||
this.initIconSetting();
|
this.initIconSetting();
|
||||||
|
this.initUnlockButtons();
|
||||||
|
this.initSubmitButton();
|
||||||
|
this.startCountdown();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -82,30 +131,50 @@ export class PageLevel extends BaseView {
|
|||||||
onViewDestroy(): void {
|
onViewDestroy(): void {
|
||||||
console.log('[PageLevel] onViewDestroy');
|
console.log('[PageLevel] onViewDestroy');
|
||||||
this.clearInputNodes();
|
this.clearInputNodes();
|
||||||
}
|
this.stopCountdown();
|
||||||
|
|
||||||
/**
|
|
||||||
* 设置关卡配置
|
|
||||||
*/
|
|
||||||
setLevelConfig(config: LevelConfig): void {
|
|
||||||
this._levelConfig = config;
|
|
||||||
this.initLevel();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 初始化关卡
|
* 初始化关卡
|
||||||
*/
|
*/
|
||||||
private initLevel(): void {
|
private initLevel(): void {
|
||||||
// 使用配置或默认值
|
const config = this.levelConfigs[this.currentLevelIndex];
|
||||||
const inputCount = this._levelConfig?.inputCount ?? this.defaultInputCount;
|
if (!config) {
|
||||||
|
console.warn('[PageLevel] 没有找到关卡配置');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 重置倒计时状态
|
||||||
|
this._isTimeUp = false;
|
||||||
|
this._countdown = 60;
|
||||||
|
|
||||||
|
// 设置主图
|
||||||
|
this.setMainImage(config.mainImage);
|
||||||
|
|
||||||
|
// 设置线索1(默认解锁)
|
||||||
|
this.setClue(1, config.clue1);
|
||||||
|
|
||||||
|
// 隐藏线索2、3
|
||||||
|
this.hideClue(2);
|
||||||
|
this.hideClue(3);
|
||||||
|
|
||||||
|
// 显示解锁按钮2、3
|
||||||
|
this.showUnlockButton(2);
|
||||||
|
this.showUnlockButton(3);
|
||||||
|
|
||||||
|
// 根据答案长度创建输入框
|
||||||
|
const inputCount = config.answer.length;
|
||||||
|
this.createInputs(inputCount);
|
||||||
|
|
||||||
// 隐藏提交按钮
|
// 隐藏提交按钮
|
||||||
if (this.submitButton) {
|
if (this.submitButton) {
|
||||||
this.submitButton.active = false;
|
this.submitButton.active = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 创建输入框
|
// 更新倒计时显示
|
||||||
this.createInputs(inputCount);
|
this.updateClockLabel();
|
||||||
|
|
||||||
|
console.log(`[PageLevel] 初始化关卡 ${this.currentLevelIndex + 1}, 答案长度: ${inputCount}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -120,8 +189,6 @@ export class PageLevel extends BaseView {
|
|||||||
// 清理现有输入框
|
// 清理现有输入框
|
||||||
this.clearInputNodes();
|
this.clearInputNodes();
|
||||||
|
|
||||||
this._inputCount = count;
|
|
||||||
|
|
||||||
// 隐藏模板节点
|
// 隐藏模板节点
|
||||||
this.inputTemplate.active = false;
|
this.inputTemplate.active = false;
|
||||||
|
|
||||||
@@ -162,7 +229,6 @@ export class PageLevel extends BaseView {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
this._inputNodes = [];
|
this._inputNodes = [];
|
||||||
this._inputCount = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -194,7 +260,9 @@ export class PageLevel extends BaseView {
|
|||||||
const values: string[] = [];
|
const values: string[] = [];
|
||||||
for (const node of this._inputNodes) {
|
for (const node of this._inputNodes) {
|
||||||
const editBox = node.getComponent(EditBox);
|
const editBox = node.getComponent(EditBox);
|
||||||
values.push(editBox?.string ?? '');
|
// 只取第一个字符,去除空格
|
||||||
|
const str = (editBox?.string ?? '').trim();
|
||||||
|
values.push(str.charAt(0));
|
||||||
}
|
}
|
||||||
return values;
|
return values;
|
||||||
}
|
}
|
||||||
@@ -208,17 +276,64 @@ export class PageLevel extends BaseView {
|
|||||||
|
|
||||||
// ========== EditBox 事件回调 ==========
|
// ========== EditBox 事件回调 ==========
|
||||||
|
|
||||||
|
/** 是否正在处理输入(防止递归) */
|
||||||
|
private _isHandlingInput: boolean = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 输入框文本变化回调
|
* 输入框文本变化回调
|
||||||
*/
|
*/
|
||||||
private onInputTextChanged(editBox: EditBox): void {
|
private onInputTextChanged(editBox: EditBox): void {
|
||||||
|
// 防止递归调用
|
||||||
|
if (this._isHandlingInput) return;
|
||||||
|
|
||||||
|
// 处理多字符输入,自动分配到后续输入框
|
||||||
|
this.handleMultiCharInput(editBox);
|
||||||
this.checkAllInputsFilled();
|
this.checkAllInputsFilled();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理多字符输入,自动分配到后续输入框
|
||||||
|
*/
|
||||||
|
private handleMultiCharInput(editBox: EditBox): void {
|
||||||
|
const text = editBox.string;
|
||||||
|
if (text.length <= 1) return;
|
||||||
|
|
||||||
|
// 找到当前输入框的索引
|
||||||
|
const currentIndex = this._inputNodes.findIndex(node => node.getComponent(EditBox) === editBox);
|
||||||
|
if (currentIndex === -1) return;
|
||||||
|
|
||||||
|
// 标记正在处理输入
|
||||||
|
this._isHandlingInput = true;
|
||||||
|
|
||||||
|
// 保留第一个字符在当前输入框
|
||||||
|
const firstChar = text[0];
|
||||||
|
const remainingChars = text.slice(1);
|
||||||
|
|
||||||
|
// 设置当前输入框只保留第一个字符
|
||||||
|
editBox.string = firstChar;
|
||||||
|
|
||||||
|
// 将剩余字符分配到后续输入框
|
||||||
|
for (let i = 0; i < remainingChars.length; i++) {
|
||||||
|
const nextIndex = currentIndex + 1 + i;
|
||||||
|
if (nextIndex < this._inputNodes.length) {
|
||||||
|
const nextEditBox = this._inputNodes[nextIndex].getComponent(EditBox);
|
||||||
|
if (nextEditBox) {
|
||||||
|
// 只在目标输入框为空时填入
|
||||||
|
if (nextEditBox.string === '') {
|
||||||
|
nextEditBox.string = remainingChars[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理完成
|
||||||
|
this._isHandlingInput = false;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 输入框编辑结束回调
|
* 输入框编辑结束回调
|
||||||
*/
|
*/
|
||||||
private onInputEditingEnded(editBox: EditBox): void {
|
private onInputEditingEnded(_editBox: EditBox): void {
|
||||||
this.checkAllInputsFilled();
|
this.checkAllInputsFilled();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -248,8 +363,319 @@ export class PageLevel extends BaseView {
|
|||||||
*/
|
*/
|
||||||
private onIconSettingClick(): void {
|
private onIconSettingClick(): void {
|
||||||
console.log('[PageLevel] IconSetting 点击,返回主页');
|
console.log('[PageLevel] IconSetting 点击,返回主页');
|
||||||
|
this.playClickSound();
|
||||||
ViewManager.instance.back();
|
ViewManager.instance.back();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ========== 线索相关方法 ==========
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取线索节点
|
||||||
|
*/
|
||||||
|
private getTipsItem(index: number): Node | null {
|
||||||
|
switch (index) {
|
||||||
|
case 1: return this.tipsItem1;
|
||||||
|
case 2: return this.tipsItem2;
|
||||||
|
case 3: return this.tipsItem3;
|
||||||
|
default: return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置线索内容
|
||||||
|
*/
|
||||||
|
private setClue(index: number, content: string): void {
|
||||||
|
const tipsItem = this.getTipsItem(index);
|
||||||
|
if (!tipsItem) return;
|
||||||
|
|
||||||
|
// 查找 TipsLabel 节点:Content -> TipsLabel
|
||||||
|
const contentNode = tipsItem.getChildByName('Content');
|
||||||
|
if (!contentNode) return;
|
||||||
|
|
||||||
|
const tipsLabelNode = contentNode.getChildByName('TipsLabel');
|
||||||
|
if (!tipsLabelNode) return;
|
||||||
|
|
||||||
|
const label = tipsLabelNode.getComponent(Label);
|
||||||
|
if (label) {
|
||||||
|
label.string = `提示 ${index}: ${content}`;
|
||||||
|
console.log(`[PageLevel] 设置线索${index}: ${content}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 显示线索
|
||||||
|
*/
|
||||||
|
private showClue(index: number): void {
|
||||||
|
const tipsItem = this.getTipsItem(index);
|
||||||
|
if (tipsItem) {
|
||||||
|
tipsItem.active = true;
|
||||||
|
console.log(`[PageLevel] 显示线索${index}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 隐藏线索
|
||||||
|
*/
|
||||||
|
private hideClue(index: number): void {
|
||||||
|
const tipsItem = this.getTipsItem(index);
|
||||||
|
if (tipsItem) {
|
||||||
|
tipsItem.active = false;
|
||||||
|
console.log(`[PageLevel] 隐藏线索${index}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 显示解锁按钮
|
||||||
|
*/
|
||||||
|
private showUnlockButton(index: number): void {
|
||||||
|
const unlockItem = index === 2 ? this.unLockItem2 : this.unLockItem3;
|
||||||
|
if (unlockItem) {
|
||||||
|
unlockItem.active = true;
|
||||||
|
console.log(`[PageLevel] 显示解锁按钮${index}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 隐藏解锁按钮
|
||||||
|
*/
|
||||||
|
private hideUnlockButton(index: number): void {
|
||||||
|
const unlockItem = index === 2 ? this.unLockItem2 : this.unLockItem3;
|
||||||
|
if (unlockItem) {
|
||||||
|
unlockItem.active = false;
|
||||||
|
console.log(`[PageLevel] 隐藏解锁按钮${index}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 初始化解锁按钮事件
|
||||||
|
*/
|
||||||
|
private initUnlockButtons(): void {
|
||||||
|
// 解锁按钮2
|
||||||
|
if (this.unLockItem2) {
|
||||||
|
this.unLockItem2.on(Node.EventType.TOUCH_END, () => this.onUnlockClue(2), this);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 解锁按钮3
|
||||||
|
if (this.unLockItem3) {
|
||||||
|
this.unLockItem3.on(Node.EventType.TOUCH_END, () => this.onUnlockClue(3), this);
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('[PageLevel] 解锁按钮事件已绑定');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 初始化提交按钮事件
|
||||||
|
*/
|
||||||
|
private initSubmitButton(): void {
|
||||||
|
if (!this.submitButton) {
|
||||||
|
console.warn('[PageLevel] submitButton 节点未设置');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.submitButton.on(Node.EventType.TOUCH_END, this.onSubmitAnswer, this);
|
||||||
|
console.log('[PageLevel] 提交按钮事件已绑定');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 点击解锁线索
|
||||||
|
*/
|
||||||
|
private onUnlockClue(index: number): void {
|
||||||
|
// 播放点击音效
|
||||||
|
this.playClickSound();
|
||||||
|
|
||||||
|
// 隐藏解锁按钮
|
||||||
|
this.hideUnlockButton(index);
|
||||||
|
|
||||||
|
// 显示线索
|
||||||
|
this.showClue(index);
|
||||||
|
|
||||||
|
// 设置线索内容
|
||||||
|
const config = this.levelConfigs[this.currentLevelIndex];
|
||||||
|
if (config) {
|
||||||
|
const clueContent = index === 2 ? config.clue2 : config.clue3;
|
||||||
|
this.setClue(index, clueContent);
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(`[PageLevel] 解锁线索${index}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ========== 主图相关方法 ==========
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置主图
|
||||||
|
*/
|
||||||
|
private setMainImage(spriteFrame: SpriteFrame | null): void {
|
||||||
|
if (!this.mainImage) return;
|
||||||
|
|
||||||
|
const sprite = this.mainImage.getComponent(Sprite);
|
||||||
|
if (sprite && spriteFrame) {
|
||||||
|
sprite.spriteFrame = spriteFrame;
|
||||||
|
console.log('[PageLevel] 设置主图');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ========== 音效相关方法 ==========
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 播放点击音效
|
||||||
|
*/
|
||||||
|
private playClickSound(): void {
|
||||||
|
if (this.clickAudio) {
|
||||||
|
// 使用 audioSource 组件播放一次性音效
|
||||||
|
const audioSource = this.node.getComponent(AudioSource);
|
||||||
|
if (audioSource) {
|
||||||
|
audioSource.playOneShot(this.clickAudio);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 播放成功音效
|
||||||
|
*/
|
||||||
|
private playSuccessSound(): void {
|
||||||
|
if (this.successAudio) {
|
||||||
|
const audioSource = this.node.getComponent(AudioSource);
|
||||||
|
if (audioSource) {
|
||||||
|
audioSource.playOneShot(this.successAudio);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 播放失败音效
|
||||||
|
*/
|
||||||
|
private playFailSound(): void {
|
||||||
|
if (this.failAudio) {
|
||||||
|
const audioSource = this.node.getComponent(AudioSource);
|
||||||
|
if (audioSource) {
|
||||||
|
audioSource.playOneShot(this.failAudio);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ========== 倒计时相关方法 ==========
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 开始倒计时
|
||||||
|
*/
|
||||||
|
private startCountdown(): void {
|
||||||
|
this._countdown = 60;
|
||||||
|
this._isTimeUp = false;
|
||||||
|
this.updateClockLabel();
|
||||||
|
this.schedule(this.onCountdownTick, 1);
|
||||||
|
console.log('[PageLevel] 开始倒计时 60 秒');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 停止倒计时
|
||||||
|
*/
|
||||||
|
private stopCountdown(): void {
|
||||||
|
this.unschedule(this.onCountdownTick);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 倒计时每秒回调
|
||||||
|
*/
|
||||||
|
private onCountdownTick(): void {
|
||||||
|
if (this._isTimeUp) return;
|
||||||
|
|
||||||
|
this._countdown--;
|
||||||
|
this.updateClockLabel();
|
||||||
|
|
||||||
|
if (this._countdown <= 0) {
|
||||||
|
this._isTimeUp = true;
|
||||||
|
this.stopCountdown();
|
||||||
|
this.onTimeUp();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新倒计时显示
|
||||||
|
*/
|
||||||
|
private updateClockLabel(): void {
|
||||||
|
if (this.clockLabel) {
|
||||||
|
this.clockLabel.string = `${this._countdown}s`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 倒计时结束
|
||||||
|
*/
|
||||||
|
private onTimeUp(): void {
|
||||||
|
console.log('[PageLevel] 倒计时结束!');
|
||||||
|
this.playFailSound();
|
||||||
|
// 可以在这里添加游戏结束逻辑
|
||||||
|
}
|
||||||
|
|
||||||
|
// ========== 答案提交与关卡切换 ==========
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 提交答案
|
||||||
|
*/
|
||||||
|
onSubmitAnswer(): void {
|
||||||
|
const config = this.levelConfigs[this.currentLevelIndex];
|
||||||
|
if (!config) return;
|
||||||
|
|
||||||
|
const userAnswer = this.getAnswer();
|
||||||
|
console.log(`[PageLevel] 提交答案: ${userAnswer}, 正确答案: ${config.answer}`);
|
||||||
|
|
||||||
|
if (userAnswer === config.answer) {
|
||||||
|
// 答案正确
|
||||||
|
this.playClickSound();
|
||||||
|
this.showSuccess();
|
||||||
|
} else {
|
||||||
|
// 答案错误
|
||||||
|
this.showError();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 显示成功提示
|
||||||
|
*/
|
||||||
|
private showSuccess(): void {
|
||||||
|
console.log('[PageLevel] 答案正确!');
|
||||||
|
|
||||||
|
// 停止倒计时
|
||||||
|
this.stopCountdown();
|
||||||
|
|
||||||
|
// 播放成功音效
|
||||||
|
this.playSuccessSound();
|
||||||
|
|
||||||
|
// 延迟后进入下一关
|
||||||
|
this.scheduleOnce(() => {
|
||||||
|
this.nextLevel();
|
||||||
|
}, 1.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 显示错误提示
|
||||||
|
*/
|
||||||
|
private showError(): void {
|
||||||
|
console.log('[PageLevel] 答案错误!');
|
||||||
|
|
||||||
|
// 播放失败音效
|
||||||
|
this.playFailSound();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 进入下一关
|
||||||
|
*/
|
||||||
|
private nextLevel(): void {
|
||||||
|
this.currentLevelIndex++;
|
||||||
|
|
||||||
|
if (this.currentLevelIndex >= this.levelConfigs.length) {
|
||||||
|
// 所有关卡完成
|
||||||
|
console.log('[PageLevel] 恭喜通关!');
|
||||||
|
this.stopCountdown();
|
||||||
|
ViewManager.instance.back();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 重置并加载下一关,重新开始倒计时
|
||||||
|
this.initLevel();
|
||||||
|
this.startCountdown();
|
||||||
|
console.log(`[PageLevel] 进入关卡 ${this.currentLevelIndex + 1}`);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
9
assets/resources/audios.meta
Normal file
9
assets/resources/audios.meta
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"ver": "1.2.0",
|
||||||
|
"importer": "directory",
|
||||||
|
"imported": true,
|
||||||
|
"uuid": "526215f4-c04a-453c-aabd-830284972d91",
|
||||||
|
"files": [],
|
||||||
|
"subMetas": {},
|
||||||
|
"userData": {}
|
||||||
|
}
|
||||||
BIN
assets/resources/audios/BgMusic.mp3
Normal file
BIN
assets/resources/audios/BgMusic.mp3
Normal file
Binary file not shown.
14
assets/resources/audios/BgMusic.mp3.meta
Normal file
14
assets/resources/audios/BgMusic.mp3.meta
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
{
|
||||||
|
"ver": "1.0.0",
|
||||||
|
"importer": "audio-clip",
|
||||||
|
"imported": true,
|
||||||
|
"uuid": "c33517cc-3f49-493c-8315-150f27cfb40c",
|
||||||
|
"files": [
|
||||||
|
".json",
|
||||||
|
".mp3"
|
||||||
|
],
|
||||||
|
"subMetas": {},
|
||||||
|
"userData": {
|
||||||
|
"downloadMode": 0
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
assets/resources/audios/Click.mp3
Normal file
BIN
assets/resources/audios/Click.mp3
Normal file
Binary file not shown.
14
assets/resources/audios/Click.mp3.meta
Normal file
14
assets/resources/audios/Click.mp3.meta
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
{
|
||||||
|
"ver": "1.0.0",
|
||||||
|
"importer": "audio-clip",
|
||||||
|
"imported": true,
|
||||||
|
"uuid": "a68a6314-fb7c-48a9-bd6c-0a65ef665d50",
|
||||||
|
"files": [
|
||||||
|
".json",
|
||||||
|
".mp3"
|
||||||
|
],
|
||||||
|
"subMetas": {},
|
||||||
|
"userData": {
|
||||||
|
"downloadMode": 0
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
assets/resources/audios/Failed.mp3
Normal file
BIN
assets/resources/audios/Failed.mp3
Normal file
Binary file not shown.
14
assets/resources/audios/Failed.mp3.meta
Normal file
14
assets/resources/audios/Failed.mp3.meta
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
{
|
||||||
|
"ver": "1.0.0",
|
||||||
|
"importer": "audio-clip",
|
||||||
|
"imported": true,
|
||||||
|
"uuid": "be83ca42-3579-46e8-821f-7a0f0b9d8464",
|
||||||
|
"files": [
|
||||||
|
".json",
|
||||||
|
".mp3"
|
||||||
|
],
|
||||||
|
"subMetas": {},
|
||||||
|
"userData": {
|
||||||
|
"downloadMode": 0
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
assets/resources/audios/Success.mp3
Normal file
BIN
assets/resources/audios/Success.mp3
Normal file
Binary file not shown.
14
assets/resources/audios/Success.mp3.meta
Normal file
14
assets/resources/audios/Success.mp3.meta
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
{
|
||||||
|
"ver": "1.0.0",
|
||||||
|
"importer": "audio-clip",
|
||||||
|
"imported": true,
|
||||||
|
"uuid": "45d1f0b7-d9d7-41d8-84b2-7abad9304148",
|
||||||
|
"files": [
|
||||||
|
".json",
|
||||||
|
".mp3"
|
||||||
|
],
|
||||||
|
"subMetas": {},
|
||||||
|
"userData": {
|
||||||
|
"downloadMode": 0
|
||||||
|
}
|
||||||
|
}
|
||||||
9
assets/resources/images/level.meta
Normal file
9
assets/resources/images/level.meta
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"ver": "1.2.0",
|
||||||
|
"importer": "directory",
|
||||||
|
"imported": true,
|
||||||
|
"uuid": "570ec71b-b925-481e-b600-23c7e32d7f6a",
|
||||||
|
"files": [],
|
||||||
|
"subMetas": {},
|
||||||
|
"userData": {}
|
||||||
|
}
|
||||||
BIN
assets/resources/images/level/level1.png
Normal file
BIN
assets/resources/images/level/level1.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 103 KiB |
134
assets/resources/images/level/level1.png.meta
Normal file
134
assets/resources/images/level/level1.png.meta
Normal file
@@ -0,0 +1,134 @@
|
|||||||
|
{
|
||||||
|
"ver": "1.0.27",
|
||||||
|
"importer": "image",
|
||||||
|
"imported": true,
|
||||||
|
"uuid": "388a4fd2-4c46-46ae-b796-10ab85c39e04",
|
||||||
|
"files": [
|
||||||
|
".json",
|
||||||
|
".png"
|
||||||
|
],
|
||||||
|
"subMetas": {
|
||||||
|
"6c48a": {
|
||||||
|
"importer": "texture",
|
||||||
|
"uuid": "388a4fd2-4c46-46ae-b796-10ab85c39e04@6c48a",
|
||||||
|
"displayName": "level1",
|
||||||
|
"id": "6c48a",
|
||||||
|
"name": "texture",
|
||||||
|
"userData": {
|
||||||
|
"wrapModeS": "clamp-to-edge",
|
||||||
|
"wrapModeT": "clamp-to-edge",
|
||||||
|
"imageUuidOrDatabaseUri": "388a4fd2-4c46-46ae-b796-10ab85c39e04",
|
||||||
|
"isUuid": true,
|
||||||
|
"visible": false,
|
||||||
|
"minfilter": "linear",
|
||||||
|
"magfilter": "linear",
|
||||||
|
"mipfilter": "none",
|
||||||
|
"anisotropy": 0
|
||||||
|
},
|
||||||
|
"ver": "1.0.22",
|
||||||
|
"imported": true,
|
||||||
|
"files": [
|
||||||
|
".json"
|
||||||
|
],
|
||||||
|
"subMetas": {}
|
||||||
|
},
|
||||||
|
"f9941": {
|
||||||
|
"importer": "sprite-frame",
|
||||||
|
"uuid": "388a4fd2-4c46-46ae-b796-10ab85c39e04@f9941",
|
||||||
|
"displayName": "level1",
|
||||||
|
"id": "f9941",
|
||||||
|
"name": "spriteFrame",
|
||||||
|
"userData": {
|
||||||
|
"trimThreshold": 1,
|
||||||
|
"rotated": false,
|
||||||
|
"offsetX": 57.5,
|
||||||
|
"offsetY": -0.5,
|
||||||
|
"trimX": 180,
|
||||||
|
"trimY": 73,
|
||||||
|
"width": 513,
|
||||||
|
"height": 999,
|
||||||
|
"rawWidth": 758,
|
||||||
|
"rawHeight": 1144,
|
||||||
|
"borderTop": 0,
|
||||||
|
"borderBottom": 0,
|
||||||
|
"borderLeft": 0,
|
||||||
|
"borderRight": 0,
|
||||||
|
"packable": true,
|
||||||
|
"pixelsToUnit": 100,
|
||||||
|
"pivotX": 0.5,
|
||||||
|
"pivotY": 0.5,
|
||||||
|
"meshType": 0,
|
||||||
|
"vertices": {
|
||||||
|
"rawPosition": [
|
||||||
|
-256.5,
|
||||||
|
-499.5,
|
||||||
|
0,
|
||||||
|
256.5,
|
||||||
|
-499.5,
|
||||||
|
0,
|
||||||
|
-256.5,
|
||||||
|
499.5,
|
||||||
|
0,
|
||||||
|
256.5,
|
||||||
|
499.5,
|
||||||
|
0
|
||||||
|
],
|
||||||
|
"indexes": [
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
2,
|
||||||
|
2,
|
||||||
|
1,
|
||||||
|
3
|
||||||
|
],
|
||||||
|
"uv": [
|
||||||
|
180,
|
||||||
|
1071,
|
||||||
|
693,
|
||||||
|
1071,
|
||||||
|
180,
|
||||||
|
72,
|
||||||
|
693,
|
||||||
|
72
|
||||||
|
],
|
||||||
|
"nuv": [
|
||||||
|
0.23746701846965698,
|
||||||
|
0.06293706293706294,
|
||||||
|
0.9142480211081794,
|
||||||
|
0.06293706293706294,
|
||||||
|
0.23746701846965698,
|
||||||
|
0.9361888111888111,
|
||||||
|
0.9142480211081794,
|
||||||
|
0.9361888111888111
|
||||||
|
],
|
||||||
|
"minPos": [
|
||||||
|
-256.5,
|
||||||
|
-499.5,
|
||||||
|
0
|
||||||
|
],
|
||||||
|
"maxPos": [
|
||||||
|
256.5,
|
||||||
|
499.5,
|
||||||
|
0
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"isUuid": true,
|
||||||
|
"imageUuidOrDatabaseUri": "388a4fd2-4c46-46ae-b796-10ab85c39e04@6c48a",
|
||||||
|
"atlasUuid": "",
|
||||||
|
"trimType": "auto"
|
||||||
|
},
|
||||||
|
"ver": "1.0.12",
|
||||||
|
"imported": true,
|
||||||
|
"files": [
|
||||||
|
".json"
|
||||||
|
],
|
||||||
|
"subMetas": {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"userData": {
|
||||||
|
"type": "sprite-frame",
|
||||||
|
"fixAlphaTransparencyArtifacts": false,
|
||||||
|
"hasAlpha": true,
|
||||||
|
"redirect": "388a4fd2-4c46-46ae-b796-10ab85c39e04@6c48a"
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
assets/resources/images/level/level2.png
Normal file
BIN
assets/resources/images/level/level2.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 130 KiB |
134
assets/resources/images/level/level2.png.meta
Normal file
134
assets/resources/images/level/level2.png.meta
Normal file
@@ -0,0 +1,134 @@
|
|||||||
|
{
|
||||||
|
"ver": "1.0.27",
|
||||||
|
"importer": "image",
|
||||||
|
"imported": true,
|
||||||
|
"uuid": "ea160d5d-8094-4867-afdc-1e1ae1279835",
|
||||||
|
"files": [
|
||||||
|
".json",
|
||||||
|
".png"
|
||||||
|
],
|
||||||
|
"subMetas": {
|
||||||
|
"6c48a": {
|
||||||
|
"importer": "texture",
|
||||||
|
"uuid": "ea160d5d-8094-4867-afdc-1e1ae1279835@6c48a",
|
||||||
|
"displayName": "level2",
|
||||||
|
"id": "6c48a",
|
||||||
|
"name": "texture",
|
||||||
|
"userData": {
|
||||||
|
"wrapModeS": "clamp-to-edge",
|
||||||
|
"wrapModeT": "clamp-to-edge",
|
||||||
|
"imageUuidOrDatabaseUri": "ea160d5d-8094-4867-afdc-1e1ae1279835",
|
||||||
|
"isUuid": true,
|
||||||
|
"visible": false,
|
||||||
|
"minfilter": "linear",
|
||||||
|
"magfilter": "linear",
|
||||||
|
"mipfilter": "none",
|
||||||
|
"anisotropy": 0
|
||||||
|
},
|
||||||
|
"ver": "1.0.22",
|
||||||
|
"imported": true,
|
||||||
|
"files": [
|
||||||
|
".json"
|
||||||
|
],
|
||||||
|
"subMetas": {}
|
||||||
|
},
|
||||||
|
"f9941": {
|
||||||
|
"importer": "sprite-frame",
|
||||||
|
"uuid": "ea160d5d-8094-4867-afdc-1e1ae1279835@f9941",
|
||||||
|
"displayName": "level2",
|
||||||
|
"id": "f9941",
|
||||||
|
"name": "spriteFrame",
|
||||||
|
"userData": {
|
||||||
|
"trimThreshold": 1,
|
||||||
|
"rotated": false,
|
||||||
|
"offsetX": -59,
|
||||||
|
"offsetY": 6.5,
|
||||||
|
"trimX": 137,
|
||||||
|
"trimY": 30,
|
||||||
|
"width": 578,
|
||||||
|
"height": 1409,
|
||||||
|
"rawWidth": 970,
|
||||||
|
"rawHeight": 1482,
|
||||||
|
"borderTop": 0,
|
||||||
|
"borderBottom": 0,
|
||||||
|
"borderLeft": 0,
|
||||||
|
"borderRight": 0,
|
||||||
|
"packable": true,
|
||||||
|
"pixelsToUnit": 100,
|
||||||
|
"pivotX": 0.5,
|
||||||
|
"pivotY": 0.5,
|
||||||
|
"meshType": 0,
|
||||||
|
"vertices": {
|
||||||
|
"rawPosition": [
|
||||||
|
-289,
|
||||||
|
-704.5,
|
||||||
|
0,
|
||||||
|
289,
|
||||||
|
-704.5,
|
||||||
|
0,
|
||||||
|
-289,
|
||||||
|
704.5,
|
||||||
|
0,
|
||||||
|
289,
|
||||||
|
704.5,
|
||||||
|
0
|
||||||
|
],
|
||||||
|
"indexes": [
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
2,
|
||||||
|
2,
|
||||||
|
1,
|
||||||
|
3
|
||||||
|
],
|
||||||
|
"uv": [
|
||||||
|
137,
|
||||||
|
1452,
|
||||||
|
715,
|
||||||
|
1452,
|
||||||
|
137,
|
||||||
|
43,
|
||||||
|
715,
|
||||||
|
43
|
||||||
|
],
|
||||||
|
"nuv": [
|
||||||
|
0.14123711340206185,
|
||||||
|
0.029014844804318488,
|
||||||
|
0.7371134020618557,
|
||||||
|
0.029014844804318488,
|
||||||
|
0.14123711340206185,
|
||||||
|
0.979757085020243,
|
||||||
|
0.7371134020618557,
|
||||||
|
0.979757085020243
|
||||||
|
],
|
||||||
|
"minPos": [
|
||||||
|
-289,
|
||||||
|
-704.5,
|
||||||
|
0
|
||||||
|
],
|
||||||
|
"maxPos": [
|
||||||
|
289,
|
||||||
|
704.5,
|
||||||
|
0
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"isUuid": true,
|
||||||
|
"imageUuidOrDatabaseUri": "ea160d5d-8094-4867-afdc-1e1ae1279835@6c48a",
|
||||||
|
"atlasUuid": "",
|
||||||
|
"trimType": "auto"
|
||||||
|
},
|
||||||
|
"ver": "1.0.12",
|
||||||
|
"imported": true,
|
||||||
|
"files": [
|
||||||
|
".json"
|
||||||
|
],
|
||||||
|
"subMetas": {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"userData": {
|
||||||
|
"type": "sprite-frame",
|
||||||
|
"fixAlphaTransparencyArtifacts": false,
|
||||||
|
"hasAlpha": true,
|
||||||
|
"redirect": "ea160d5d-8094-4867-afdc-1e1ae1279835@6c48a"
|
||||||
|
}
|
||||||
|
}
|
||||||
Binary file not shown.
|
Before Width: | Height: | Size: 197 KiB |
BIN
assets/resources/images/pageLevel/IconClock.png
Normal file
BIN
assets/resources/images/pageLevel/IconClock.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 3.0 KiB |
@@ -2,7 +2,7 @@
|
|||||||
"ver": "1.0.27",
|
"ver": "1.0.27",
|
||||||
"importer": "image",
|
"importer": "image",
|
||||||
"imported": true,
|
"imported": true,
|
||||||
"uuid": "fa1861ef-84d3-4347-9bf0-7627f54b05de",
|
"uuid": "4c8c7576-d69c-4524-8add-07ad36a958c6",
|
||||||
"files": [
|
"files": [
|
||||||
".json",
|
".json",
|
||||||
".png"
|
".png"
|
||||||
@@ -10,14 +10,14 @@
|
|||||||
"subMetas": {
|
"subMetas": {
|
||||||
"6c48a": {
|
"6c48a": {
|
||||||
"importer": "texture",
|
"importer": "texture",
|
||||||
"uuid": "fa1861ef-84d3-4347-9bf0-7627f54b05de@6c48a",
|
"uuid": "4c8c7576-d69c-4524-8add-07ad36a958c6@6c48a",
|
||||||
"displayName": "test",
|
"displayName": "IconClock",
|
||||||
"id": "6c48a",
|
"id": "6c48a",
|
||||||
"name": "texture",
|
"name": "texture",
|
||||||
"userData": {
|
"userData": {
|
||||||
"wrapModeS": "clamp-to-edge",
|
"wrapModeS": "clamp-to-edge",
|
||||||
"wrapModeT": "clamp-to-edge",
|
"wrapModeT": "clamp-to-edge",
|
||||||
"imageUuidOrDatabaseUri": "fa1861ef-84d3-4347-9bf0-7627f54b05de",
|
"imageUuidOrDatabaseUri": "4c8c7576-d69c-4524-8add-07ad36a958c6",
|
||||||
"isUuid": true,
|
"isUuid": true,
|
||||||
"visible": false,
|
"visible": false,
|
||||||
"minfilter": "linear",
|
"minfilter": "linear",
|
||||||
@@ -34,8 +34,8 @@
|
|||||||
},
|
},
|
||||||
"f9941": {
|
"f9941": {
|
||||||
"importer": "sprite-frame",
|
"importer": "sprite-frame",
|
||||||
"uuid": "fa1861ef-84d3-4347-9bf0-7627f54b05de@f9941",
|
"uuid": "4c8c7576-d69c-4524-8add-07ad36a958c6@f9941",
|
||||||
"displayName": "test",
|
"displayName": "IconClock",
|
||||||
"id": "f9941",
|
"id": "f9941",
|
||||||
"name": "spriteFrame",
|
"name": "spriteFrame",
|
||||||
"userData": {
|
"userData": {
|
||||||
@@ -45,10 +45,10 @@
|
|||||||
"offsetY": 0,
|
"offsetY": 0,
|
||||||
"trimX": 0,
|
"trimX": 0,
|
||||||
"trimY": 0,
|
"trimY": 0,
|
||||||
"width": 352,
|
"width": 200,
|
||||||
"height": 776,
|
"height": 200,
|
||||||
"rawWidth": 352,
|
"rawWidth": 200,
|
||||||
"rawHeight": 776,
|
"rawHeight": 200,
|
||||||
"borderTop": 0,
|
"borderTop": 0,
|
||||||
"borderBottom": 0,
|
"borderBottom": 0,
|
||||||
"borderLeft": 0,
|
"borderLeft": 0,
|
||||||
@@ -60,17 +60,17 @@
|
|||||||
"meshType": 0,
|
"meshType": 0,
|
||||||
"vertices": {
|
"vertices": {
|
||||||
"rawPosition": [
|
"rawPosition": [
|
||||||
-176,
|
-100,
|
||||||
-388,
|
-100,
|
||||||
0,
|
0,
|
||||||
176,
|
100,
|
||||||
-388,
|
-100,
|
||||||
0,
|
0,
|
||||||
-176,
|
-100,
|
||||||
388,
|
100,
|
||||||
0,
|
0,
|
||||||
176,
|
100,
|
||||||
388,
|
100,
|
||||||
0
|
0
|
||||||
],
|
],
|
||||||
"indexes": [
|
"indexes": [
|
||||||
@@ -83,12 +83,12 @@
|
|||||||
],
|
],
|
||||||
"uv": [
|
"uv": [
|
||||||
0,
|
0,
|
||||||
776,
|
200,
|
||||||
352,
|
200,
|
||||||
776,
|
200,
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
352,
|
200,
|
||||||
0
|
0
|
||||||
],
|
],
|
||||||
"nuv": [
|
"nuv": [
|
||||||
@@ -102,18 +102,18 @@
|
|||||||
1
|
1
|
||||||
],
|
],
|
||||||
"minPos": [
|
"minPos": [
|
||||||
-176,
|
-100,
|
||||||
-388,
|
-100,
|
||||||
0
|
0
|
||||||
],
|
],
|
||||||
"maxPos": [
|
"maxPos": [
|
||||||
176,
|
100,
|
||||||
388,
|
100,
|
||||||
0
|
0
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"isUuid": true,
|
"isUuid": true,
|
||||||
"imageUuidOrDatabaseUri": "fa1861ef-84d3-4347-9bf0-7627f54b05de@6c48a",
|
"imageUuidOrDatabaseUri": "4c8c7576-d69c-4524-8add-07ad36a958c6@6c48a",
|
||||||
"atlasUuid": "",
|
"atlasUuid": "",
|
||||||
"trimType": "auto"
|
"trimType": "auto"
|
||||||
},
|
},
|
||||||
@@ -129,6 +129,6 @@
|
|||||||
"type": "sprite-frame",
|
"type": "sprite-frame",
|
||||||
"fixAlphaTransparencyArtifacts": false,
|
"fixAlphaTransparencyArtifacts": false,
|
||||||
"hasAlpha": true,
|
"hasAlpha": true,
|
||||||
"redirect": "fa1861ef-84d3-4347-9bf0-7627f54b05de@6c48a"
|
"redirect": "4c8c7576-d69c-4524-8add-07ad36a958c6@6c48a"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
BIN
assets/resources/images/pageLevel/IconLive.png
Normal file
BIN
assets/resources/images/pageLevel/IconLive.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 4.8 KiB |
134
assets/resources/images/pageLevel/IconLive.png.meta
Normal file
134
assets/resources/images/pageLevel/IconLive.png.meta
Normal file
@@ -0,0 +1,134 @@
|
|||||||
|
{
|
||||||
|
"ver": "1.0.27",
|
||||||
|
"importer": "image",
|
||||||
|
"imported": true,
|
||||||
|
"uuid": "5ab5c212-a4cc-4c9b-a372-0cd2f30f4aff",
|
||||||
|
"files": [
|
||||||
|
".json",
|
||||||
|
".png"
|
||||||
|
],
|
||||||
|
"subMetas": {
|
||||||
|
"6c48a": {
|
||||||
|
"importer": "texture",
|
||||||
|
"uuid": "5ab5c212-a4cc-4c9b-a372-0cd2f30f4aff@6c48a",
|
||||||
|
"displayName": "IconLive",
|
||||||
|
"id": "6c48a",
|
||||||
|
"name": "texture",
|
||||||
|
"userData": {
|
||||||
|
"wrapModeS": "clamp-to-edge",
|
||||||
|
"wrapModeT": "clamp-to-edge",
|
||||||
|
"imageUuidOrDatabaseUri": "5ab5c212-a4cc-4c9b-a372-0cd2f30f4aff",
|
||||||
|
"isUuid": true,
|
||||||
|
"visible": false,
|
||||||
|
"minfilter": "linear",
|
||||||
|
"magfilter": "linear",
|
||||||
|
"mipfilter": "none",
|
||||||
|
"anisotropy": 0
|
||||||
|
},
|
||||||
|
"ver": "1.0.22",
|
||||||
|
"imported": true,
|
||||||
|
"files": [
|
||||||
|
".json"
|
||||||
|
],
|
||||||
|
"subMetas": {}
|
||||||
|
},
|
||||||
|
"f9941": {
|
||||||
|
"importer": "sprite-frame",
|
||||||
|
"uuid": "5ab5c212-a4cc-4c9b-a372-0cd2f30f4aff@f9941",
|
||||||
|
"displayName": "IconLive",
|
||||||
|
"id": "f9941",
|
||||||
|
"name": "spriteFrame",
|
||||||
|
"userData": {
|
||||||
|
"trimThreshold": 1,
|
||||||
|
"rotated": false,
|
||||||
|
"offsetX": 0.5,
|
||||||
|
"offsetY": -2.5,
|
||||||
|
"trimX": 16,
|
||||||
|
"trimY": 25,
|
||||||
|
"width": 169,
|
||||||
|
"height": 155,
|
||||||
|
"rawWidth": 200,
|
||||||
|
"rawHeight": 200,
|
||||||
|
"borderTop": 0,
|
||||||
|
"borderBottom": 0,
|
||||||
|
"borderLeft": 0,
|
||||||
|
"borderRight": 0,
|
||||||
|
"packable": true,
|
||||||
|
"pixelsToUnit": 100,
|
||||||
|
"pivotX": 0.5,
|
||||||
|
"pivotY": 0.5,
|
||||||
|
"meshType": 0,
|
||||||
|
"vertices": {
|
||||||
|
"rawPosition": [
|
||||||
|
-84.5,
|
||||||
|
-77.5,
|
||||||
|
0,
|
||||||
|
84.5,
|
||||||
|
-77.5,
|
||||||
|
0,
|
||||||
|
-84.5,
|
||||||
|
77.5,
|
||||||
|
0,
|
||||||
|
84.5,
|
||||||
|
77.5,
|
||||||
|
0
|
||||||
|
],
|
||||||
|
"indexes": [
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
2,
|
||||||
|
2,
|
||||||
|
1,
|
||||||
|
3
|
||||||
|
],
|
||||||
|
"uv": [
|
||||||
|
16,
|
||||||
|
175,
|
||||||
|
185,
|
||||||
|
175,
|
||||||
|
16,
|
||||||
|
20,
|
||||||
|
185,
|
||||||
|
20
|
||||||
|
],
|
||||||
|
"nuv": [
|
||||||
|
0.08,
|
||||||
|
0.1,
|
||||||
|
0.925,
|
||||||
|
0.1,
|
||||||
|
0.08,
|
||||||
|
0.875,
|
||||||
|
0.925,
|
||||||
|
0.875
|
||||||
|
],
|
||||||
|
"minPos": [
|
||||||
|
-84.5,
|
||||||
|
-77.5,
|
||||||
|
0
|
||||||
|
],
|
||||||
|
"maxPos": [
|
||||||
|
84.5,
|
||||||
|
77.5,
|
||||||
|
0
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"isUuid": true,
|
||||||
|
"imageUuidOrDatabaseUri": "5ab5c212-a4cc-4c9b-a372-0cd2f30f4aff@6c48a",
|
||||||
|
"atlasUuid": "",
|
||||||
|
"trimType": "auto"
|
||||||
|
},
|
||||||
|
"ver": "1.0.12",
|
||||||
|
"imported": true,
|
||||||
|
"files": [
|
||||||
|
".json"
|
||||||
|
],
|
||||||
|
"subMetas": {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"userData": {
|
||||||
|
"type": "sprite-frame",
|
||||||
|
"fixAlphaTransparencyArtifacts": false,
|
||||||
|
"hasAlpha": true,
|
||||||
|
"redirect": "5ab5c212-a4cc-4c9b-a372-0cd2f30f4aff@6c48a"
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
assets/resources/images/pageLevel/IconTips.png
Normal file
BIN
assets/resources/images/pageLevel/IconTips.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 5.0 KiB |
134
assets/resources/images/pageLevel/IconTips.png.meta
Normal file
134
assets/resources/images/pageLevel/IconTips.png.meta
Normal file
@@ -0,0 +1,134 @@
|
|||||||
|
{
|
||||||
|
"ver": "1.0.27",
|
||||||
|
"importer": "image",
|
||||||
|
"imported": true,
|
||||||
|
"uuid": "729b014d-f0e9-4b67-b99d-177756102d0e",
|
||||||
|
"files": [
|
||||||
|
".json",
|
||||||
|
".png"
|
||||||
|
],
|
||||||
|
"subMetas": {
|
||||||
|
"6c48a": {
|
||||||
|
"importer": "texture",
|
||||||
|
"uuid": "729b014d-f0e9-4b67-b99d-177756102d0e@6c48a",
|
||||||
|
"displayName": "IconTips",
|
||||||
|
"id": "6c48a",
|
||||||
|
"name": "texture",
|
||||||
|
"userData": {
|
||||||
|
"wrapModeS": "clamp-to-edge",
|
||||||
|
"wrapModeT": "clamp-to-edge",
|
||||||
|
"imageUuidOrDatabaseUri": "729b014d-f0e9-4b67-b99d-177756102d0e",
|
||||||
|
"isUuid": true,
|
||||||
|
"visible": false,
|
||||||
|
"minfilter": "linear",
|
||||||
|
"magfilter": "linear",
|
||||||
|
"mipfilter": "none",
|
||||||
|
"anisotropy": 0
|
||||||
|
},
|
||||||
|
"ver": "1.0.22",
|
||||||
|
"imported": true,
|
||||||
|
"files": [
|
||||||
|
".json"
|
||||||
|
],
|
||||||
|
"subMetas": {}
|
||||||
|
},
|
||||||
|
"f9941": {
|
||||||
|
"importer": "sprite-frame",
|
||||||
|
"uuid": "729b014d-f0e9-4b67-b99d-177756102d0e@f9941",
|
||||||
|
"displayName": "IconTips",
|
||||||
|
"id": "f9941",
|
||||||
|
"name": "spriteFrame",
|
||||||
|
"userData": {
|
||||||
|
"trimThreshold": 1,
|
||||||
|
"rotated": false,
|
||||||
|
"offsetX": 0.5,
|
||||||
|
"offsetY": 0,
|
||||||
|
"trimX": 31,
|
||||||
|
"trimY": 12,
|
||||||
|
"width": 139,
|
||||||
|
"height": 176,
|
||||||
|
"rawWidth": 200,
|
||||||
|
"rawHeight": 200,
|
||||||
|
"borderTop": 0,
|
||||||
|
"borderBottom": 0,
|
||||||
|
"borderLeft": 0,
|
||||||
|
"borderRight": 0,
|
||||||
|
"packable": true,
|
||||||
|
"pixelsToUnit": 100,
|
||||||
|
"pivotX": 0.5,
|
||||||
|
"pivotY": 0.5,
|
||||||
|
"meshType": 0,
|
||||||
|
"vertices": {
|
||||||
|
"rawPosition": [
|
||||||
|
-69.5,
|
||||||
|
-88,
|
||||||
|
0,
|
||||||
|
69.5,
|
||||||
|
-88,
|
||||||
|
0,
|
||||||
|
-69.5,
|
||||||
|
88,
|
||||||
|
0,
|
||||||
|
69.5,
|
||||||
|
88,
|
||||||
|
0
|
||||||
|
],
|
||||||
|
"indexes": [
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
2,
|
||||||
|
2,
|
||||||
|
1,
|
||||||
|
3
|
||||||
|
],
|
||||||
|
"uv": [
|
||||||
|
31,
|
||||||
|
188,
|
||||||
|
170,
|
||||||
|
188,
|
||||||
|
31,
|
||||||
|
12,
|
||||||
|
170,
|
||||||
|
12
|
||||||
|
],
|
||||||
|
"nuv": [
|
||||||
|
0.155,
|
||||||
|
0.06,
|
||||||
|
0.85,
|
||||||
|
0.06,
|
||||||
|
0.155,
|
||||||
|
0.94,
|
||||||
|
0.85,
|
||||||
|
0.94
|
||||||
|
],
|
||||||
|
"minPos": [
|
||||||
|
-69.5,
|
||||||
|
-88,
|
||||||
|
0
|
||||||
|
],
|
||||||
|
"maxPos": [
|
||||||
|
69.5,
|
||||||
|
88,
|
||||||
|
0
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"isUuid": true,
|
||||||
|
"imageUuidOrDatabaseUri": "729b014d-f0e9-4b67-b99d-177756102d0e@6c48a",
|
||||||
|
"atlasUuid": "",
|
||||||
|
"trimType": "auto"
|
||||||
|
},
|
||||||
|
"ver": "1.0.12",
|
||||||
|
"imported": true,
|
||||||
|
"files": [
|
||||||
|
".json"
|
||||||
|
],
|
||||||
|
"subMetas": {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"userData": {
|
||||||
|
"type": "sprite-frame",
|
||||||
|
"fixAlphaTransparencyArtifacts": false,
|
||||||
|
"hasAlpha": true,
|
||||||
|
"redirect": "729b014d-f0e9-4b67-b99d-177756102d0e@6c48a"
|
||||||
|
}
|
||||||
|
}
|
||||||
111
assets/scripts/utils/RoundedRectMask.ts
Normal file
111
assets/scripts/utils/RoundedRectMask.ts
Normal file
@@ -0,0 +1,111 @@
|
|||||||
|
import { _decorator, Component, UITransform, Graphics, Color, Mask } from 'cc';
|
||||||
|
const { ccclass, property } = _decorator;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 圆角矩形遮罩组件
|
||||||
|
* 使用 Graphics + Mask 绘制圆角矩形作为遮罩
|
||||||
|
*
|
||||||
|
* 使用方法:
|
||||||
|
* 1. 将此组件添加到需要圆角的节点上
|
||||||
|
* 2. 设置圆角半径
|
||||||
|
* 3. 该节点及其子节点会被裁剪为圆角矩形
|
||||||
|
*/
|
||||||
|
@ccclass('RoundedRectMask')
|
||||||
|
export class RoundedRectMask extends Component {
|
||||||
|
|
||||||
|
@property({
|
||||||
|
tooltip: '圆角半径(像素)'
|
||||||
|
})
|
||||||
|
radius: number = 20;
|
||||||
|
|
||||||
|
private _graphics: Graphics | null = null;
|
||||||
|
private _mask: Mask | null = null;
|
||||||
|
private _uiTransform: UITransform | null = null;
|
||||||
|
|
||||||
|
onLoad() {
|
||||||
|
this._uiTransform = this.getComponent(UITransform);
|
||||||
|
this.setupComponents();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置组件
|
||||||
|
*/
|
||||||
|
private setupComponents() {
|
||||||
|
// 获取或添加 Graphics 组件
|
||||||
|
this._graphics = this.getComponent(Graphics);
|
||||||
|
if (!this._graphics) {
|
||||||
|
this._graphics = this.addComponent(Graphics);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取或添加 Mask 组件
|
||||||
|
this._mask = this.getComponent(Mask);
|
||||||
|
if (!this._mask) {
|
||||||
|
this._mask = this.addComponent(Mask);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 设置 Mask 使用 Graphics 类型
|
||||||
|
this._mask.type = Mask.Type.GRAPHICS_STENCIL;
|
||||||
|
|
||||||
|
this.drawRoundedRect();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 绘制圆角矩形
|
||||||
|
*/
|
||||||
|
private drawRoundedRect() {
|
||||||
|
if (!this._graphics || !this._uiTransform) return;
|
||||||
|
|
||||||
|
const width = this._uiTransform.width;
|
||||||
|
const height = this._uiTransform.height;
|
||||||
|
const r = Math.min(this.radius, Math.min(width, height) / 2);
|
||||||
|
|
||||||
|
// 清除之前的绘制
|
||||||
|
this._graphics.clear();
|
||||||
|
|
||||||
|
// 设置填充颜色
|
||||||
|
this._graphics.fillColor = new Color(255, 255, 255, 255);
|
||||||
|
|
||||||
|
// 绘制圆角矩形路径
|
||||||
|
const halfW = width / 2;
|
||||||
|
const halfH = height / 2;
|
||||||
|
|
||||||
|
// 使用 lineTo 和 arc 绘制圆角矩形
|
||||||
|
// 从左下角开始,逆时针绘制
|
||||||
|
this._graphics.moveTo(-halfW + r, -halfH);
|
||||||
|
|
||||||
|
// 下边
|
||||||
|
this._graphics.lineTo(halfW - r, -halfH);
|
||||||
|
|
||||||
|
// 右下角圆角 (90度弧,从 -90度 到 0度)
|
||||||
|
this._graphics.arc(halfW - r, -halfH + r, r, -Math.PI / 2, 0, false);
|
||||||
|
|
||||||
|
// 右边
|
||||||
|
this._graphics.lineTo(halfW, halfH - r);
|
||||||
|
|
||||||
|
// 右上角圆角 (90度弧,从 0度 到 90度)
|
||||||
|
this._graphics.arc(halfW - r, halfH - r, r, 0, Math.PI / 2, false);
|
||||||
|
|
||||||
|
// 上边
|
||||||
|
this._graphics.lineTo(-halfW + r, halfH);
|
||||||
|
|
||||||
|
// 左上角圆角 (90度弧,从 90度 到 180度)
|
||||||
|
this._graphics.arc(-halfW + r, halfH - r, r, Math.PI / 2, Math.PI, false);
|
||||||
|
|
||||||
|
// 左边
|
||||||
|
this._graphics.lineTo(-halfW, -halfH + r);
|
||||||
|
|
||||||
|
// 左下角圆角 (90度弧,从 180度 到 270度)
|
||||||
|
this._graphics.arc(-halfW + r, -halfH + r, r, Math.PI, Math.PI * 1.5, false);
|
||||||
|
|
||||||
|
// 填充
|
||||||
|
this._graphics.fill();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置圆角半径
|
||||||
|
*/
|
||||||
|
setRadius(radius: number) {
|
||||||
|
this.radius = radius;
|
||||||
|
this.drawRoundedRect();
|
||||||
|
}
|
||||||
|
}
|
||||||
9
assets/scripts/utils/RoundedRectMask.ts.meta
Normal file
9
assets/scripts/utils/RoundedRectMask.ts.meta
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"ver": "4.0.24",
|
||||||
|
"importer": "typescript",
|
||||||
|
"imported": true,
|
||||||
|
"uuid": "e5f6a7b8-c901-2345-def6-789012345678",
|
||||||
|
"files": [],
|
||||||
|
"subMetas": {},
|
||||||
|
"userData": {}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user