鸿蒙NEXT小游戏开发:猜小球

1. 引言

“猜小球”是一个经典的益智游戏,通常由一名表演者和多名参与者共同完成。表演者会将一个小球放在一个杯子下面,然后将三个杯子快速地交换位置,参与者则需要猜出最终哪个杯子下面有小球。本文将介绍如何使用HarmonyOS NEXT技术,如装饰器、状态管理和动画,来实现一个“猜小球”游戏。

2. 环境准备

电脑系统:windows 10
开发工具:DevEco Studio NEXT Beta1 Build Version: 5.0.3.806
工程版本:API 12
真机:Mate 60 Pro
语言:ArkTS、ArkUI

3. 实现目标

创建一个交互式的游戏,让玩家能够:

  1. 开始游戏:通过点击“开始游戏”按钮启动游戏,触发杯子间的随机交换。
  2. 调整动画速度:允许用户通过界面上的控制器来调整游戏过程中杯子交换的速度。
  3. 调整混合次数:让用户可以设置每局游戏中杯子的混合次数。
  4. 显示杯子内容:当动画停止后,玩家可以通过点击任意一个杯子来查看其下面是否有小球。
  5. 自动重置:如果所有预定的交换次数完成,游戏会自动重置,等待下一轮开始。
    【开发逻辑】
  6. 定义杯子类:创建 Cup 类,定义杯子的属性和构造函数。
  7. 实现游戏逻辑:
    • 初始化游戏状态。
    • 实现 startGame() 方法,用于开始游戏。
    • 实现 moveCups() 方法,用于移动杯子。
    • 实现 swapBalls() 方法,用于交换杯子内的球。
    • 实现 resetCupPosition() 方法,用于重置杯子的位置。
  8. 动画效果:使用动画库(animateToImmediately)实现杯子的动画效果。

4. 完整代码

// 使用装饰器来追踪对象的变化
@ObservedV2
class Cup { // 定义杯子类// 使用装饰器来追踪属性的变化@Trace positionX: number; // 杯子的X轴位置@Trace positionY: number; // 杯子的Y轴位置@Trace containsBall: boolean; // 杯子内是否有球@Trace isRevealed: boolean; // 杯子是否打开,即是否显示内部情况// 构造函数初始化杯子的状态constructor(hasBall: boolean) { // 初始化杯子,参数hasBall表示杯子是否包含小球this.positionX = 0; // 初始X轴位置设为0this.positionY = 0; // 初始Y轴位置设为0this.containsBall = hasBall; // 设置杯子是否含有小球this.isRevealed = true; // 初始状态为打开,即可以看到里面是否有球}
}// 游戏入口组件
@Entry
@Component
struct ThreeCupGame { // 定义游戏主结构体// 游戏状态变量@State gameCups: Cup[] = [// 初始化三个杯子数组,其中只有一个杯子含有小球new Cup(true), // 第一个杯子含有小球new Cup(false), // 第二个杯子不含有小球new Cup(false)// 第三个杯子也不含有小球];@State cupWidth: number = 200; // 设置杯子宽度@State cupSpacing: number = 10; // 设置杯子之间的间距@State animationDurationMs: number = 140; // 设置动画持续时间(毫秒)@State isGameAnimating: boolean = false; // 表示游戏是否正在进行动画@State mixingCount: number = 5; // 设置每局游戏混合次数@State currentMixingCount: number = 0; // 当前正在进行的混合次数计数// 开始游戏的方法startGame() { // 开始游戏的函数this.currentMixingCount--; // 每次调用此函数时减少一次混合次数const cupPairs = [[0, 1], [0, 2], [1, 2]]; // 定义可能的杯子对组合const selectedPair = cupPairs[Math.floor(Math.random() * cupPairs.length)]; // 随机选择一对杯子this.moveCups(selectedPair[0], selectedPair[1]); // 开始移动选定的两个杯子}// 移动指定的两个杯子moveCups(cupIndex1: number, cupIndex2: number) {const direction: number = Math.random() < 0.5 ? -1 : 1; // 随机方向const distanceFactor: number = Math.abs(cupIndex1 - cupIndex2); // 距离因子const adjustedDistanceFactor: number = distanceFactor === 1 ? 2 : 1; // 根据距离调整因子animateToImmediately({delay: 0,duration: this.animationDurationMs}, () => {this.gameCups[cupIndex1].positionY = -direction * (this.cupWidth + this.cupSpacing * 2) / adjustedDistanceFactor})animateToImmediately({delay: this.animationDurationMs,duration: this.animationDurationMs}, () => {this.gameCups[cupIndex1].positionX = (this.cupWidth + this.cupSpacing * 2) * distanceFactorthis.gameCups[cupIndex1].positionY = -direction * (this.cupWidth + this.cupSpacing * 2) / adjustedDistanceFactor})animateToImmediately({delay: this.animationDurationMs * 2,duration: this.animationDurationMs}, () => {this.gameCups[cupIndex1].positionX = (this.cupWidth + this.cupSpacing * 2) * distanceFactorthis.gameCups[cupIndex1].positionY = 0})animateToImmediately({delay: 0,duration: this.animationDurationMs}, () => {this.gameCups[cupIndex2].positionY = direction * (this.cupWidth + this.cupSpacing * 2) / adjustedDistanceFactor})animateToImmediately({delay: this.animationDurationMs,duration: this.animationDurationMs}, () => {this.gameCups[cupIndex2].positionX = -(this.cupWidth + this.cupSpacing * 2) * distanceFactorthis.gameCups[cupIndex2].positionY = direction * (this.cupWidth + this.cupSpacing * 2) / adjustedDistanceFactor})animateToImmediately({delay: this.animationDurationMs * 2,duration: this.animationDurationMs,onFinish: () => {this.swapBalls(cupIndex1, cupIndex2)}}, () => {this.gameCups[cupIndex2].positionX = -(this.cupWidth + this.cupSpacing * 2) * distanceFactorthis.gameCups[cupIndex2].positionY = 0})}// 重置杯子的位置resetCupPosition(cupIndex: number) { // 重置指定杯子位置的函数this.gameCups[cupIndex].positionX = 0; // 重置X轴位置this.gameCups[cupIndex].positionY = 0; // 重置Y轴位置}// 交换两个杯子内的球swapBalls(cupIndex1: number, cupIndex2: number) { // 交换两个杯子中球的函数this.resetCupPosition(cupIndex1); // 重置第一个杯子的位置this.resetCupPosition(cupIndex2); // 重置第二个杯子的位置let temporaryBallStatus = this.gameCups[cupIndex1].containsBall; // 临时保存第一个杯子的球状态this.gameCups[cupIndex1].containsBall = this.gameCups[cupIndex2].containsBall; // 将第二个杯子的球状态赋给第一个杯子this.gameCups[cupIndex2].containsBall = temporaryBallStatus; // 将临时保存的球状态赋给第二个杯子if (this.currentMixingCount <= 0) { // 如果当前混合次数已经用完this.isGameAnimating = false; // 结束动画} else {setTimeout(() => { // 否则,延时调用startGame继续下一轮混合this.startGame();}, 10);}}// 构建游戏界面build() { // 构建游戏界面的函数Column({ space: 20 }) { // 创建一个垂直布局容器// 游戏标题Text('猜小球游戏')// 显示游戏标题.fontSize(24)// 设置字体大小.margin({ top: 20 }); // 设置顶部边距// 动画速度控制器Counter() { // 创建一个计数器组件Text(`当前速度${this.animationDurationMs}毫秒`)// 显示当前动画速度.fontColor(Color.Black)// 设置字体颜色.fontSize('26lpx'); // 设置字体大小}.width('400lpx') // 设置计数器宽度.onInc(() => { // 当计数器增加时this.animationDurationMs += 10; // 增加动画速度}).onDec(() => { // 当计数器减少时this.animationDurationMs -= 10; // 减少动画速度this.animationDurationMs = this.animationDurationMs < 10 ? 10 : this.animationDurationMs; // 确保动画速度不低于10毫秒});// 混合次数控制器Counter() { // 创建另一个计数器组件Text(`每局混合${this.mixingCount}次`)// 显示当前混合次数.fontColor(Color.Black).fontSize('26lpx');}.width('400lpx').onInc(() => { // 当计数器增加时this.mixingCount += 1; // 增加混合次数}).onDec(() => { // 当计数器减少时this.mixingCount -= 1; // 减少混合次数this.mixingCount = this.mixingCount < 1 ? 1 : this.mixingCount; // 确保混合次数不低于1});// 杯子布局Row() { // 创建一个水平布局容器ForEach(this.gameCups, (cup: Cup) => { // 循环遍历每个杯子Text(cup.isRevealed ? (cup.containsBall ? '小球' : '空') : '')// 根据杯子的状态显示文字.width(`${this.cupWidth}lpx`)// 设置宽度.height(`${this.cupWidth}lpx`)// 设置高度.margin(`${this.cupSpacing}lpx`)// 设置外边距.backgroundColor(Color.Orange)// 设置背景色.fontSize(`${this.cupWidth / 4}lpx`)// 设置字体大小.textAlign(TextAlign.Center)// 设置文本对齐方式.fontColor(Color.White)// 设置字体颜色.borderRadius(5)// 设置圆角半径.translate({ x: `${cup.positionX}lpx`, y: `${cup.positionY}lpx` })// 设置位置偏移.onClick(() => { // 当点击杯子时if (!this.isGameAnimating) { // 如果游戏没有在动画中cup.isRevealed = true; // 打开杯子查看内部}});});}.justifyContent(FlexAlign.Center).width('100%').height('720lpx').backgroundColor(Color.Gray); // 设置布局属性// 开始游戏按钮Button('开始游戏').onClick(() => { // 创建一个按钮,点击时触发事件if (!this.isGameAnimating) { // 如果游戏没有在动画中this.currentMixingCount = this.mixingCount; // 重置当前混合次数this.isGameAnimating = true; // 设置游戏为动画中this.gameCups.forEach(cup => cup.isRevealed = false); // 关闭所有杯子this.startGame(); // 开始游戏}});}.width('100%').height('100%'); // 设置布局容器的尺寸}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/74357.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

网络购物谨慎使用手机免密支付功能

在数字经济蓬勃发展的当下&#xff0c;“免密支付”成为许多人消费时的首选支付方式。 “免密支付”的存在有其合理性。在快节奏的现代生活中&#xff0c;时间愈发珍贵&#xff0c;每节省一秒都可能带来更高的效率。以日常通勤为例&#xff0c;上班族乘坐交通工具时&#xff0c…

记录 | Android getWindow().getDecorView().setSystemUiVisibility(...)设置状态栏属性

纯纯的一边开发一边学习&#xff0c;是小白是菜鸟&#xff0c;单纯的记录和学习&#xff0c;大神勿喷&#xff0c;理解有错望指正&#xff5e; getWindow().getDecorView().setSystemUiVisibility(…) 该方法用于控制系统 UI&#xff08;如状态栏、导航栏&#xff09;的可见性…

java虚拟机---JVM

JVM JVM&#xff0c;也就是 Java 虚拟机&#xff0c;它最主要的作用就是对编译后的 Java 字节码文件逐行解释&#xff0c;翻译成机器码指令&#xff0c;并交给对应的操作系统去执行。 JVM 的其他特性有&#xff1a; JVM 可以自动管理内存&#xff0c;通过垃圾回收器回收不再…

VectorBT:使用PyTorch+LSTM训练和回测股票模型 进阶四

VectorBT&#xff1a;使用PyTorchLSTM训练和回测股票模型 进阶四 本方案融合 LSTM 时序预测与动态风险控制。系统采用混合架构&#xff0c;离线训练构建多尺度特征工程和双均线策略&#xff0c;结合在线增量更新持续优化模型。技术要点包括三层特征筛选、波动率动态仓位管理、混…

前端中rem,vh,vw

1. rem&#xff08;Root EM&#xff09; 参照对象 基准&#xff1a;相对于 根元素&#xff08;<html>&#xff09;的 font-size 计算。 默认情况下&#xff0c;浏览器的根 font-size 为 16px&#xff08;即 1rem 16px&#xff09;&#xff0c;但可通过 CSS 修改&#…

详解 MySQL 常见的存储引擎及它们之间的区别

MySQL 支持多种存储引擎&#xff0c;每种引擎针对不同的应用场景提供了特定的特性和优化。下面是几种常见的存储引擎以及它们之间的主要区别&#xff1a; 常见存储引擎 1. InnoDB&#xff08;重点&#xff09; 事务支持&#xff1a; 完全支持 ACID 事务&#xff0c;确保数据一…

html+css+js 实现一个贪吃蛇小游戏

目录 游戏简介 游戏功能与特点 如何玩转贪吃蛇 游戏设计与实现 HTML结构 JavaScript核心实现 代码结构&#xff1a; 效果 关于“其他游戏” 游戏简介 贪吃蛇是一款经典的单人小游戏&#xff0c;玩家通过控制蛇的移动&#xff0c;吃掉食物来增加长度&#xff0c;避免撞…

GLSL(OpenGL 着色器语言)基础语法

GLSL&#xff08;OpenGL 着色器语言&#xff09;基础语法 GLSL&#xff08;OpenGL Shading Language&#xff09;是 OpenGL 计算着色器的语言&#xff0c;语法类似于 C 语言&#xff0c;但提供了针对 GPU 的特殊功能&#xff0c;如向量运算和矩阵运算。 着色器的开头总是要声明…

ngx_http_core_merge_srv_conf

定义在 src\http\ngx_http_core_module.c static char * ngx_http_core_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child) {ngx_http_core_srv_conf_t *prev parent;ngx_http_core_srv_conf_t *conf child;ngx_str_t name;ngx_http_server_name_t…

uni-app:firstUI框架的选择器Select改造,添加一个搜索的插槽

<fui-select :show"showSiteType" :options"siteTypeList" textKey"dict_label" title"请选择站点类型" confirm"chooseSiteType" close"onCloseSiteType"><template v-slot:search><view><…

Debian/Ubuntu的networking的`/etc/network/interfaces`配置文件,如何配置route路由

Debian/Ubuntu的networking的/etc/network/interfaces配置文件,如何配置route路由 在 Debian/Ubuntu 系统中&#xff0c;通过 /etc/network/interfaces 配置文件配置路由&#xff08;静态路由或默认路由&#xff09;可以通过以下方式实现。以下是详细配置方法及示例&#xff1…

天梯赛 L2-024 部落

一个并查集题目&#xff0c;难点就在于统计总人数&#xff0c;使用map即可&#xff0c;还有需要注意的是编号不一定是小于N的&#xff0c;小于10000的&#xff0c;需要注意。 #include<bits/stdc.h> using namespace std; const int N 10010; int fa[N]; int find(int …

uniapp 微信小程序 使用ucharts

文章目录 前言一、组件功能概述二、代码结构分析2.1 模板结构 总结 前言 本文介绍一个基于 Vue 框架的小程序图表组件开发方案。该组件通过 uCharts 库实现折线图的绘制&#xff0c;并支持滚动、缩放、触摸提示等交互功能。文章将从代码结构、核心方法、交互实现和样式设计等方…

Axure项目实战:智慧运输平台后台管理端-承运商管理(中继器筛选)

亲爱的小伙伴,在您浏览之前,烦请关注一下,在此深表感谢! 课程主题:智慧运输平台后台管理端 主要内容:承运商管理 应用场景:条件筛选、增删改查操作、台账制作 案例展示: 正文内容: 承运商管理模块主要解决平台对承运商的管理,包括新增承运商作,审核承运商申请,修…

[论文笔记] Deepseek技术报告解读: MLAMTP

1. RMSNorm 归一化层 class RMSNorm(nn.Module):def __init__(self, dim: int, eps: float = 1e-8):super().__init__()self.eps = epsself.weight = nn.Parameter(torch.ones(dim)) # 可学习的缩放参数def _norm(self, x: torch.Tensor):return x * torch.rsqrt(x.pow(2).me…

八款内网电脑监控软件:探寻适配企业需求的数字化监管方案组合

数字化办公的时代背景下&#xff0c;企业管理面临着前所未有的挑战。如何实现对员工办公行为的高效管理&#xff0c;确保网络资源的合理利用&#xff0c;成为众多企业决策者和高级管理人员亟待解决的重要问题。内网电脑监控软件作为一种有效的管理工具&#xff0c;应运而生。本…

Flutter求助贴

报错信息&#xff1a;The Dart VM Service was not discovered after 30 seconds. This is taking much longer than expected... 基本情况&#xff1a; 硬件&#xff1a;mac(15.3.1)&#xff0c;iPad(iOS 16.6),iPhone 16 pro(iOS 18.4) 项目环境 flutter&#xff1a;3.16…

React(九)React Hooks

初识Hook 我们到底为什么需要hook那? 函数组件类组件存在问题 函数组件存在的问题&#xff1a; import React, { PureComponent } from reactfunction HelloWorld2(props) {let message"Hello world"// 函数式组件存在的缺陷&#xff1a;// 1.修改message之后&a…

数据清洗的具体内容

&#xff08;一&#xff09;ETL介绍 “ETL&#xff0c;是英文Extract-Transform-Load的缩写&#xff0c;用来描述将数据从来源端经过抽取&#xff08;Extract&#xff09;、转换&#xff08;Transform&#xff09;、加载&#xff08;Load&#xff09;至目的端的过程。ETL一词较…

【动手学深度学习】#7 现代卷积神经网络

主要参考学习资料&#xff1a; 《动手学深度学习》阿斯顿张 等 著 【动手学深度学习 PyTorch版】哔哩哔哩跟李牧学AI 概述 硬件性能和大数据的发展为深度卷积神经网络&#xff08;AlexNet&#xff09;的实现提供了条件。VGG首次将块的思想用于搭建网络。NiN将多层感知机应用在…