「Mac畅玩鸿蒙与硬件50」UI互动应用篇27 - 水果掉落小游戏

本篇教程将带你实现一个水果掉落小游戏,掌握基本的动态交互逻辑和鸿蒙组件的使用,进一步了解事件处理与状态管理。

在这里插入图片描述


关键词
  • UI互动应用
  • 水果掉落
  • 状态管理
  • 动态交互
  • 游戏开发

一、功能说明

水果掉落小游戏包含以下交互功能:

  1. 随机生成水果:屏幕顶部随机生成水果,并动态下落。
  2. 接收水果:通过左右移动篮子接住水果。
  3. 实时分数统计:成功接住水果增加得分,未接住则无分。
  4. 游戏重置:支持一键重置游戏状态。

二、所需组件
  • @Entry@Component 装饰器
  • Canvas 组件用于绘制水果和篮子
  • Button 组件用于移动篮子和重置游戏
  • @State 修饰符用于状态管理
  • setIntervalclearInterval 实现定时功能

三、项目结构
  • 项目名称FruitDropGame
  • 自定义组件名称FruitDropPage
  • 代码文件FruitDropPage.etsIndex.ets

四、代码实现
1. 水果掉落页面
// 文件名:FruitDropPage.ets

// 定义水果接口
interface Fruit {
  x: number;
  y: number;
}

@Component
export struct FruitDropPage {
  @State basketPosition: number = 400; // 篮子初始位置
  @State fruits: Fruit[] = []; // 水果列表
  @State score: number = 0; // 游戏得分
  private intervalId: number | null = null; // 定时器ID
  private context: CanvasRenderingContext2D = new CanvasRenderingContext2D();

  // 初始化游戏
  initGame(): void {
    this.score = 0;
    this.fruits = [];
    this.startDroppingFruits();
  }

  // 启动水果掉落
  startDroppingFruits(): void {
    if (this.intervalId !== null) {
      return; // 如果定时器已存在,则不重复启动
    }
    this.intervalId = setInterval(() => {
      this.fruits.push({ x: Math.random() * 700, y: 0 }); // 随机生成水果
      this.updateFruits();
    }, 1000); // 每秒生成一个水果
  }

  // 更新水果位置
  updateFruits(): void {
    const updatedFruits: Fruit[] = [];
    this.fruits.forEach(fruit => {
      const updatedY = fruit.y + 10; // 调整水果下落速度
      if (updatedY >= 580 && Math.abs(fruit.x - this.basketPosition) < 100) {
        this.score += 1; // 接住水果,得分
      } else if (updatedY < 600) {
        updatedFruits.push({ x: fruit.x, y: updatedY }); // 更新位置
      }
    });
    this.fruits = updatedFruits; // 更新水果数组
    this.redrawCanvas();
  }

  // 绘制游戏画布
  redrawCanvas(): void {
    this.context.clearRect(0, 0, 700, 600); // 清空画布
    this.fruits.forEach(fruit => {
      this.context.fillStyle = '#FFA500'; // 水果颜色
      this.context.beginPath();
      this.context.arc(fruit.x, fruit.y, 15, 0, 2 * Math.PI); // 绘制水果
      this.context.fill();
    });

    // 绘制篮子
    this.context.fillStyle = '#0000FF';
    this.context.fillRect(this.basketPosition - 100, 570, 200, 20); // 调整篮子位置和大小
  }

  // 移动篮子
  moveBasket(direction: string): void {
    if (direction === 'left' && this.basketPosition > 100) {
      this.basketPosition -= 40; // 调整移动距离
    } else if (direction === 'right' && this.basketPosition < 600) {
      this.basketPosition += 40; // 调整移动距离
    }
    this.redrawCanvas();
  }

  // 停止游戏
  stopGame(): void {
    if (this.intervalId !== null) {
      clearInterval(this.intervalId); // 清除定时器
      this.intervalId = null;
    }
    this.fruits = [];
    this.redrawCanvas();
  }

  build() {
    Column({ space: 20 }) {
      // 游戏标题和分数
      Row({ space: 20 }) {
        Text('水果掉落小游戏')
          .fontSize(30)
          .fontWeight(FontWeight.Bold)
          .alignSelf(ItemAlign.Start)
          .margin({ left: 20 });

        Text(`得分:${this.score}`)
          .fontSize(24)
          .alignSelf(ItemAlign.End)
          .margin({ right: 20 });
      }
      .width('100%');

      Row() {
        // 左侧画布
        Canvas(this.context)
          .width(700) // 调整画布宽度
          .height(600) // 调整画布高度
          .border({ width: 2, color: '#CCCCCC' }) // 添加边框,方便观察
          .onReady(() => {
            this.initGame();
          });

        // 右侧操作区
        Column({ space: 40 }) {
          Button('左移')
            .onClick(() => this.moveBasket('left'))
            .width(150)
            .height(70)
            .backgroundColor('#00AAFF')
            .fontSize(24)
            .fontColor(Color.White);

          Button('右移')
            .onClick(() => this.moveBasket('right'))
            .width(150)
            .height(70)
            .backgroundColor('#00AAFF')
            .fontSize(24)
            .fontColor(Color.White);

          Button('重置游戏')
            .onClick(() => {
              this.stopGame();
              this.initGame();
            })
            .width(150)
            .height(70)
            .backgroundColor('#FF5555')
            .fontSize(24)
            .fontColor(Color.White);
        }
        .width(200)
        .alignSelf(ItemAlign.Center);
      }
      .padding(20)
      .width('100%')
      .height('80%')
      .alignSelf(ItemAlign.Center);
    }
    .padding(20)
    .width('100%')
    .height('100%')
    .alignSelf(ItemAlign.Center);
  }
}

2. 主入口文件
// 文件名:Index.ets

import { FruitDropPage } from './FruitDropPage';

@Entry
@Component
struct Index {
  build() {
    Column() {
      FruitDropPage() // 调用水果掉落页面
    }
    .padding(20);
  }
}

效果示例:水果随机从顶部掉落,玩家通过移动篮子接住水果,实时更新分数。

效果展示
在这里插入图片描述


五、代码解读
  1. 水果随机生成与移动

    • 使用 setInterval 定时生成水果,并动态更新位置。
  2. 状态管理与分数更新

    • 使用 @State 管理水果位置、篮子位置和分数状态,实现实时更新。
  3. 画布绘制逻辑

    • Canvas 组件结合 CanvasRenderingContext2D 绘制水果和篮子。
  4. 用户交互逻辑

    • 通过按钮控制篮子左右移动,实时更新画布内容。

六、优化建议
  1. 随分数增加逐步加快水果掉落速度,增加游戏挑战性。
  2. 提供多种水果类型,并设定不同的分值。
  3. 增加暂停和继续功能,提升用户体验。

七、效果展示
  • 随机水果生成与掉落:水果从顶部随机生成,并不断下落。
  • 实时分数统计:成功接住水果实时更新分数。
  • 灵活操作:通过按钮灵活控制篮子左右移动,接住水果。

八、相关知识点
  • 「Mac畅玩鸿蒙与硬件20」鸿蒙UI组件篇10 - Canvas组件自定义绘图
  • 「Mac畅玩鸿蒙与硬件11」鸿蒙UI组件篇1 - Text和Button组件详解

小结

本篇教程通过动态生成水果、实时分数统计以及用户交互逻辑,实现了一个水果掉落小游戏。用户可以掌握鸿蒙组件和状态管理的实际应用,为开发更复杂的游戏提供基础。


下一篇预告

在下一篇「UI互动应用篇28 - 模拟记账应用」中,我们将实现一个实用的记账功能,学习数据输入和动态展示的开发技巧。


上一篇: 「Mac畅玩鸿蒙与硬件49」UI互动应用篇26 - 数字填色游戏
下一篇: 「Mac畅玩鸿蒙与硬件51」UI互动应用篇28 - 模拟记账应用

作者:SoraLuna
链接:https://www.nutpi.net/thread?topicId=657
來源:坚果派
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。


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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

C# OpenCV机器视觉:凸包检测

在一个看似平常却又暗藏玄机的午后&#xff0c;阿强正悠闲地坐在实验室里&#xff0c;翘着二郎腿&#xff0c;哼着小曲儿&#xff0c;美滋滋地品尝着手中那杯热气腾腾的咖啡&#xff0c;仿佛整个世界都与他无关。突然&#xff0c;实验室的门 “砰” 的一声被撞开&#xff0c;小…

UGUI 优化DrawCall操作记录(基于Unity2021.3.18)

UGUI中相同材质相同Shader相同贴图的UI元素可以合并DrawCall。 1.使用图集 Unity性能优化---使用SpriteAtlas创建图集进行批次优化_unity2021.3.33 spriteatlas优化-CSDN博客 2.Canvas的子物体在场景树中的索引位置和不同图集不影响UI合批且UI网格没有重叠&#xff0c;如下图…

3---杭州工作三年半

2021-07-06来杭——2025-01-01元旦 1滨江2021-07-06——2022-11-25&#xff08;一年零四个月&#xff09; 2下沙2023-01-01——2023-04-27&#xff08;五个月&#xff09; 3苏州2023-06-07——2023-06-27&#xff08;一个月&#xff09;厦门2023-06-29——2023-07-06&#xff…

【项目开发】C#环境配置及VScode运行C#教程(学生管理系统)

原创文章,禁止转载。 文章目录 下载.NETVScode配置运行程序下载.NET 官网链接: https://dotnet.microsoft.com/en-us/download选择任意版本下载: 下载完成后,双击运行exe文件,等待安装完成。 在控制台输入: dotnet --version若出现版本信息,说明安装成功: VScode配…

Excel文件恢复教程:快速找回丢失数据!

Excel文件恢复位置在哪里&#xff1f; Excel是微软开发的电子表格软件&#xff0c;它为处理数据和组织工作提供了便捷。虽然数据丢失的问题在数字时代已经司空见惯&#xff0c;但对于某些用户来说&#xff0c;恢复未保存/删除/丢失的Excel文件可能会很困难&#xff0c;更不用说…

亚矩阵云手机技术形态与应用方向

亚矩阵云手机技术架构 亚矩阵云手机技术架构深度融合了云计算、虚拟化、边缘计算和大数据等先进技术&#xff0c;构建了一个全面且高效的移动终端服务体系。其中&#xff0c;云端服务器作为整个云手机的基石&#xff0c;采用高性能、高可用性的云计算资源&#xff0c;负责提供海…

3D线上艺术展:艺术与技术的完美融合

随着数字技术的飞速发展&#xff0c;未来的艺术展览正逐步迈向线上线下融合的新阶段。其中&#xff0c;3D线上展览以其独特的魅力&#xff0c;成为线下展览的延伸与拓展&#xff0c;为艺术爱好者们开辟了全新的观赏途径。 对于艺术家和策展人而言&#xff0c;3D线上展览不仅打…

ES elasticsearch-8.17.0-windows-x86_64使用

1、下载ES(elasticsearch 简称 ES 下载链接&#xff1a;https://www.elastic.co/downloads/elasticsearch) ES 下载链接&#xff1a;https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-8.17.0-windows-x86_64.zip))&#xff0c;需要在修改ES配置&#xff0…

sqlserver设置定时任务计划(SSMS)

软件&#xff1a;SQL Server Management Studio&#xff08;SSMS&#xff09; 1.连接数据库服务器&#xff0c;找到 SQL Sever Agent&#xff08;代理&#xff09; 启动 2.启动后&#xff0c;点开 Jobs&#xff08;作业&#xff09; 新建&#xff0c;填写常规信息 3.步骤 > …

如何规范的提交Git?

多人协作开发提交代码通常是遵循约定式提交规范&#xff0c;如果严格安照约定式提交规范&#xff0c; 手动进行代码提交的话&#xff0c;那么是一件非常痛苦的事情&#xff0c;但是 Git 提交规范的处理又势在必行&#xff0c;那么怎么办呢&#xff1f; 经过了很多人的冥思苦想…

WPF编程excel表格操作

WPF编程excel表格操作 摘要NPOI安装封装代码测试代码 摘要 Excel操作几种方式 使用开源库NPOI(常用&#xff0c;操作丰富)使用Microsoft.Office.Interop.Excel COM组件(兼容性问题)使用OpenXml(效率高)使用OleDb(过时) NPOI安装 封装代码 using System; using System.IO; u…

初识 Conda:一站式包管理和环境管理工具

文章目录 1. 什么是 Conda&#xff1f;2. 为什么选择 Conda&#xff1f;3. Conda 的安装3.1 安装步骤&#xff08;以 Miniconda 为例&#xff09; 4. Conda 的核心功能4.1 包管理4.2 环境管理4.3 Conda Forge4.4 设置国内镜像 5. 常见使用场景5.1 数据科学项目5.2 离线安装5.3 …

docker 搭建集群

准备3台机器&#xff1a; #dockermaster 192.168.31.150 sudo hostnamectl set-hostname dockermaster #初始化主节点 docker swarm init --advertise-addr 192.168.31.150 #查看集群是否搭建成功 docker node ls #dockernode1 192.168.31.151 sudo hostnamectl set-hostname …

Kafka消息不丢失与重复消费问题解决方案总结

1. 生产者层面 异步发送与回调处理 异步发送方式&#xff1a;生产者一般使用异步方式发送消息&#xff0c;异步发送有消息和回调接口两个参数。在回调接口的重写方法中&#xff0c;可通过异常参数判断消息发送状态。若消息发送成功&#xff0c;异常参数为null&#xff1b;若发…

StarRocks 存算分离在得物的降本增效实践

编者荐语&#xff1a; 得物优化数据引擎布局&#xff0c;近期将 4000 核 ClickHouse 迁移至自建 StarRocks&#xff0c;成本降低 40%&#xff0c;查询耗时减半&#xff0c;集群稳定性显著提升。本文详解迁移实践与成果&#xff0c;文末附丁凯剑老师 StarRocks Summit Asia 2024…

微服务-1 认识微服务

目录​​​​​​​ 1 认识微服务 1.1 单体架构 1.2 微服务 1.3 SpringCloud 2 服务拆分原则 2.1 什么时候拆 2.2 怎么拆 2.3 服务调用 3. 服务注册与发现 3.1 注册中心原理 3.2 Nacos注册中心 3.3 服务注册 3.3.1 添加依赖 3.3.2 配置Nacos 3.3.3 启动服务实例 …

IDEA工具使用介绍、IDEA常用设置以及如何集成Git版本控制工具

文章目录 一、IDEA二、建立第一个 Java 程序三、IDEA 常用设置四、IDEA 集成版本控制工具&#xff08;Git、GitHub&#xff09;4.1 IDEA 拉 GitHub/Git 项目4.2 IDEA 上传 项目到 Git4.3 更新提交命令 一、IDEA 1、什么是IDEA&#xff1f; IDEA&#xff0c;全称为 IntelliJ ID…

kafka开机自启失败问题处理

前言&#xff1a;在当今大数据处理领域&#xff0c;Kafka 作为一款高性能、分布式的消息队列系统&#xff0c;发挥着举足轻重的作用。无论是海量数据的实时传输&#xff0c;还是复杂系统间的解耦通信&#xff0c;Kafka 都能轻松应对。然而&#xff0c;在实际部署和运维 Kafka 的…

二维数组综合

第1题 稀疏矩阵 查看测评数据信息 nm矩阵大部分元素是0的矩阵称为稀疏矩阵&#xff0c;假设有k个非0元素&#xff0c;则可把稀疏矩阵用K3的矩阵简记之&#xff0c;其中第一列是行号&#xff0c;第二列是列号&#xff0c;第三列是该行、该列下的非0元素的值。如&#xff1a;…

STM32-笔记20-测量按键按下时间

1、按键按下的时间-思路 我们先检测下降沿信号&#xff0c;检测到以后&#xff0c;在回调函数里切换成检测上升沿信号&#xff0c;当两个信号都检测到的时候&#xff0c;这段时间就是按键按下的时间&#xff0c;如图所示&#xff1a;>N*(ARR1)CCRx的值 N是在这段时间内&…