纯血Harmony NETX 5小游戏实践:电子木鱼(附源文件)

一、技术与禅意的奇妙碰撞

(一)观察者模式下的状态管理:数据驱动的交互灵魂

less 复制代码
@ObservedV2 // 观察者模式装饰器,自动追踪状态变化
class Cell {
  value: string = '功德+1';
  @Trace opacity: number = 0; // 透明度追踪
  @Trace y: number = 0; // 位移追踪
}

通过@ObservedV2装饰器,Cell类实现数据响应式:当opacityy属性变化时,界面自动触发重绘。这种设计模式将「功德文字飘升」的视觉效果转化为数据驱动的状态迁移,使代码逻辑与UI表现解耦,提升可维护性。

(二)功德累加的双模式实现:手动点击与自动挂机的交互平衡

scss 复制代码
@State autoClick: boolean = false; // 自动点击开关
@State time: number = 0; // 定时器句柄

// 手动点击事件
Image($r('app.media.Snipaste'))
  .onClick(() => {
    this.totalMerit += 1; // 功德+1
    this.triggerAnimation(); // 触发文字飘升动画
  })

// 自动点击逻辑
Toggle({ type: ToggleType.Switch, isOn: this.autoClick })
  .onChange((isOn) => {
    isOn ? this.startAutoClick() : this.stopAutoClick();
  })

通过Toggle开关组件实现手动/自动模式切换:

  • 手动模式 :用户点击木鱼图片时,触发triggerAnimation生成飘升文字,模拟真实敲木鱼的交互反馈。

  • 自动模式 :通过setInterval定时器每秒自动执行点击逻辑,解放双手的同时保留视觉反馈,满足不同用户的「积功德」需求。

二、动画美学:用代码绘制数字禅意

功德文字的飘升动画是交互体验的核心,其实现基于ArkUI的animateTo动画接口:

ini 复制代码
private triggerAnimation(index: number) {
  // 初始状态(底部显示)
  animateTo({ duration: 0 }, () => {
    this.list[index].y = 0;
    this.list[index].opacity = 1;
  })
  // 结束状态(飘升消失)
  .then(() => {
    animateTo({ duration: 1000, curve: Curve.EaseOut }, () => {
      this.list[index].y = -200;
      this.list[index].opacity = 0;
    });
  });
}
  • 双阶段动画 :先瞬间重置文字位置与透明度(duration: 0),再通过1秒缓出动画(Curve.EaseOut)模拟自然飘落轨迹。

  • 循环复用 :通过indexCount % count取模运算,实现有限数量的Cell实例循环利用,避免内存泄漏的同时保证动画流畅性。

三、界面设计:暗黑美学与赛博符号的视觉叙事

(一)沉浸式暗黑背景

scss 复制代码
.backgroundColor(Color.Black) // 全局黑色背景

纯黑背景凸显白色文字与木鱼图标,减少视觉干扰的同时营造「禅修」氛围。功德统计与开关组件通过白色字体形成高对比度视觉焦点。

(二)木鱼图标的交互强化

php 复制代码
Image($r('app.media.Snipaste'))
  .clickEffect({ scale: 0.5, level: ClickEffectLevel.LIGHT }) // 点击缩放效果
  .width('300lpx')
  .height('300lpx')

通过clickEffect为木鱼图标添加轻量级点击缩放动效,模拟物理按压反馈。ImageFit.Contain属性确保图片不失真,保持视觉完整性。

(三)文字队列的堆叠布局

scss 复制代码
Stack() { // 堆叠容器实现多层文字重叠
  ForEach(this.list, (item, index) => {
    Text(item.value)
      .translate({ y: `${item.y}lpx` }) // 垂直位移
      .opacity(item.opacity) // 透明度渐变
  })
}

使用Stack容器使多个功德文字层叠显示,结合translateopacity属性实现文字从底部飘升至消失的动态效果,营造「功德源源不断」的视觉暗示。

四、附源文件

scss 复制代码
// 观察者模式装饰器
@ObservedV2
class Cell {
  value: string = '功德+1';
  @Trace opacity: number = 0;
  @Trace y: number = 0;
}

// 主入口组件
@Component
export struct play_muyu {
  @State list: Cell[] = [];
  indexCount: number = 0;
  count: number = 10;
  @State totalMerit: number = 0; // 总功德数
  @State autoClick: boolean = false; // 是否开启自动点击
  @State time:number = 0;

  // 组件显示时初始化音频
  aboutToAppear(): void {
    for (let i = 0; i < this.count; i++) {
      this.list.push(new Cell());
    }
  }

  build() {
    Column() {
      // 功德统计和自动点击开关
      Row() {
        Text(`总功德: ${this.totalMerit}`)
          .fontColor(Color.White)
          .fontSize('30lpx')
          .padding(10)

        Toggle({ type: ToggleType.Switch, isOn: this.autoClick })
          .width(50)
          .height(30)
          .onChange((isOn: boolean) => {
            this.autoClick = isOn;
            if (isOn) {
              // 开启自动点击时启动定时器
              this.time = setInterval(() => {
                if (this.autoClick) {
                  this.totalMerit += 1;
                  const index = this.indexCount % this.count;
                  this.indexCount++;

                  animateTo({
                    duration: 0,
                    onFinish: () => {
                      animateTo({
                        duration: 1000,
                      }, () => {
                        this.list[index].y = -200;
                        this.list[index].opacity = 0;
                      });
                    }
                  }, () => {
                    this.list[index].y = 0;
                    this.list[index].opacity = 1;
                  });
                }
              }, 1000); // 每秒自动点击一次
            } else {
              // 关闭自动点击时清除定时器
              clearInterval(this.time);
            }
          })
        Text(this.autoClick ? '自动点击: 开' : '自动点击: 关')
          .fontColor(Color.White)
          .fontSize('30lpx')
          .padding(10)
      }
      .width('100%')
      .justifyContent(FlexAlign.SpaceBetween)
      .alignItems(VerticalAlign.Center)
      .margin({ top: 20 })
      Stack() {
        ForEach(this.list, (item: Cell, index: number) => {
          Text(item.value)
            .fontColor(Color.White)
            .fontSize('50lpx')
            .translate({ x: 0, y: `${item.y}lpx` })
            .opacity(item.opacity)
        })
      }
      .width('300lpx')
      .height('300lpx')
      .align(Alignment.BottomEnd)

      Image($r('app.media.Snipaste'))
        .width('300lpx')
        .height('300lpx')
        .objectFit(ImageFit.Contain)
        .clickEffect({ scale: 0.5, level: ClickEffectLevel.LIGHT })
        .onClick(() => {
          // 增加功德
          this.totalMerit += 1;
          // 动画逻辑
          const index = this.indexCount % this.count;
          this.indexCount++;

          animateTo({
            duration: 0,
            onFinish: () => {
              animateTo({
                duration: 1000,
              }, () => {
                this.list[index].y = -200
                this.list[index].opacity = 0
              })
            }
          }, () => {
            this.list[index].y = 0
            this.list[index].opacity = 1
          })
        })
    }
    .height('100%')
    .width('100%')
    .backgroundColor(Color.Black)
  }

}
相关推荐
Aisanyi2 小时前
【鸿蒙开发】PC实现开局沉浸式全屏
前端·华为·harmonyos
我睡醒再说5 小时前
以下是对华为 HarmonyOS NETX 5属性动画(ArkTS)文档的结构化整理,通过层级标题、表格和代码块提升可读性:
harmonyos
我睡醒再说5 小时前
ArkUI-X跨平台开发能力解析:优势与限制场景
harmonyos
我睡醒再说5 小时前
纯血Harmony NETX 5小游戏实践:趣味三消游戏(附源文件)
harmonyos
我睡醒再说5 小时前
HarmonyOS NETX 5ArkUI-X打造数字猜谜游戏:(附源文件)
harmonyos
shenshizhong6 小时前
鸿蒙列表新的实现方式
harmonyos
程序员小刘6 小时前
鸿蒙跨平台开发:打通安卓、iOS生态
android·ios·harmonyos
王二蛋与他的张大花6 小时前
鸿蒙运动项目开发:封装超级好用的 RCP 网络库(中)—— 错误处理,会话管理与网络状态检测篇
harmonyos
王二蛋与他的张大花7 小时前
鸿蒙运动项目开发:封装超级好用的 RCP 网络库(上)—— 请求参数封装,类型转化器与日志记录篇
harmonyos