【HarmonyOS NEXT星河版开发学习】娱乐小游戏-生肖抽卡

个人主页→VON

收录专栏→鸿蒙开发小型案例总结​​​​​

基础语法部分会发布于github 和 gitee上面(暂未发布)

难度系数:

 

 

前言

该小游戏使用到的知识点都是一些新的东西,当时写的时候就是一边写一边学习知识点,所以时间上花费的比较多。有些东西是为了简化代码提高可读性,希望大家认真观看认真学习。

构建思路

初始界面

没有抽到任何卡片时的一个界面,这个页面的构建相对简单一些。方法也有很多,初始时的图片是自定义的一张图片,立即抽卡是一个Button组件。 

抽取到卡片时的页面 

 

点击开始抽卡的时候会弹出这一界面,原理就是层叠关系的转变以及透明度的更改。点击开心收下时所属卡片的数量会加一,还可以接着抽卡。 

 获奖页面

 当所有卡片都集齐后会有中级大奖,当然这个大奖也是我们自行设计的,这里是以手机为例。这一界面的实现和抽到卡片时的页面原理相同。

界面讲解

1.定义接口并且准备生肖卡片

2.定义初始化页面

 

 3.设定抽卡页面和奖品页面的初始值

4.构建抽卡页面

因为篇幅的原因,将部分代码折叠了起来。 

5.中奖页面

 

6.再来一次 

点击再来一次后,所有数据恢复默认值,重新开始游戏

 

知识点概述

鸿蒙开发中的Grid布局是一种新型的布局方式,通过网格来划分页面,使用行列来定义网格,从而使得页面布局更加灵活、简洁且易于维护

鸿蒙HarmonyOS中的ArkUI框架提供了Grid和GridItem组件来构建网格布局。Grid作为容器组件,用于设置网格布局的相关参数,而GridItem则定义了子组件的特征。这种布局方式支持自适应布局,能够轻松实现响应式设计,适用于多终端设备显示。

在鸿蒙开发中,网格布局由“行”和“列”分割的单元格组成,每个单元格可以包含不同的元素,如文本、图片和媒体等。Grid组件支持自定义行列数以及每行每列的尺寸占比,并允许设置子组件横跨多行或多列。这种布局不仅具备强大的页面均分能力,还允许开发者精确控制子组件的占比。

网格布局的创建主要通过设置Grid组件的rowsTemplate和columnsTemplate属性来完成。这两个属性的值是由空格和'数字+fr'间隔拼接的字符串,其中fr的数量表示网格的行数或列数。数字表示该行或列在网格布局宽度上的占比,从而决定该行或列的宽度。例如,一个三行三列的网格布局,垂直方向上分为三等份,每行占一份;水平方向上分为四等份,第一列占一份,第二列占两份,第三列占一份。这可以通过设置rowsTemplate为'1fr 1fr 1fr'和columnsTemplate为'1fr 2fr 1fr'来实现。

为了进一步细化子组件的布局,GridItem组件提供了rowStart、rowEnd、columnStart和columnEnd等属性。这些属性分别指定当前子组件的起始行号、终点行号、起始列号和终点列号。例如,如果一个子组件需要横跨第一列和第二列,可以将其columnStart和columnEnd分别设置为1和2。同理,如果一个子组件需要横跨第五行和第六行,可以将其rowStart和rowEnd分别设置为5和6。

此外,Grid组件还支持设置排列方式和主轴方向。通过layoutDirection属性,可以设定网格布局的主轴方向,并决定子组件的排列方式。当layoutDirection设为Row时,子组件会从左到右排列,排满一行再排下一行;设为Column时,子组件会从上到下排列,排满一列再排下一列。结合minCount和maxCount属性,可以约束主轴方向上的网格数量。

鸿蒙开发中的Grid布局提供了一种强大且灵活的方式来组织和管理页面元素。通过合理应用Grid和GridItem组件的属性及方法,开发者可以构建出多样化的网格布局,满足不同场景的应用需求。

Grid容器组件

  • 基本概念
    • Grid是一个容器,由行和列组成的单元格构成。
    • 通过指定每个子组件GridItem所在的单元格位置来实现灵活多变的布局效果。

属性

  • rowsTemplatecolumnsTemplate

    • 这两个属性用来定义网格的行和列模板。例如,你可以定义等宽的列或等高的行,或者混合使用固定尺寸和可伸缩的单元格。
  • rowsGapcolumnsGap

    • 这两个属性用来设置行与行之间以及列与列之间的间隙大小。
  • layoutDirection

    • 决定网格中元素的排列方向,默认为水平方向(Row),也可以设置为垂直方向(Column)。

子组件 GridItem

  • GridItemGrid容器的直接子组件,用来表示网格中的一个单元格。
  • 你可以在GridItem中放置任何其他组件,并且可以指定其跨越多少行或列。

代码展示

// 1.定义接口
interface Images{
  url:string
  count:number
}

// 需求1:遮罩层显隐 透明度opacity 0-1 层级zInsex 1-99
// 需求2:图片收缩 缩放scale 0-1
@Entry
@Component
struct Index {
  // 随机的生肖卡序号
  @State randomNum:number=-1// 初始值为-1表示还没有抽卡
  // 2.基于接口准备数据
  @State images:Images[]=[
    {url:'app.media.sxcard',count:0},
    {url:'app.media.sxcard',count:0},
    {url:'app.media.sxcard',count:0},
    {url:'app.media.sxcard',count:0},
    {url:'app.media.sxcard',count:0},
    {url:'app.media.sxcard',count:0}
  ]
  // 透明度
  @State transparent:number=0 // 初始为0
  //层级
  @State Level:number=0 // 初始为0
  // 缩放
  @State zoomx:number=0
  @State zoomy:number=0
  // 控制中奖
  @State isGet:boolean=false
  // 奖池
  @State arr:string[]=['pg','hw','xm']
  @State price:string=''//默认没有中奖

  build() {
    // 层叠布局
    Stack(){
      // 初始化页面
      Column(){
        // Grid布局的基础使用:规则的行列布局中非常常见
        Grid(){
          ForEach(this.images,(item:Images,index:number)=>{
            GridItem(){
              Badge({
                count:item.count,
                position:BadgePosition.RightTop,
                style:{
                  fontSize:14,
                  badgeSize:20,
                  badgeColor:Color.Red
                }
              }){
                Image($r(item.url))
                  .width(100)
                  .height(100)
              }
            }
          })
        }
        .columnsTemplate('1fr 1fr 1fr')
        .rowsTemplate('1fr 1fr')
        .width('100%')
        .height(300)
        .margin({top:100})

        Button('立即抽卡')
          .width(200)
          .backgroundColor('#de668d')
          .margin({top:50})
          .onClick(()=>{
            this.Level=99
            this.transparent=1
            this.zoomx=1
            this.zoomy=1
            //计算随机数
            this.randomNum = Math.floor(Math.random()*6)
          })
      }
      .zIndex(5) // 初始化层级为5
      .width('100%')
      .height('100%')

      // 抽卡时的页面
      Column({space:25}){
        Text('获得生肖卡片')
          .fontColor('#f5ebcf')
          .fontSize(25)
          .fontWeight(FontWeight.Bold)
        Image($r(`app.media.sxcard0${this.randomNum}`))
          .width(200)
        // 卡片的播放
          .scale({
            x:this.zoomx,
            y:this.zoomy
          })
          .animation({
            duration:500
          })
        Button('开心收下')
          .width(200)
          .height(50)
          .backgroundColor(Color.Transparent)// 透明色
          .border({width:2,color:'#fff9e0'})
          .onClick(()=>{
            this.transparent=0
            this.Level=0
            this.zoomx=0
            this.zoomy=0
            // 开心收下
            this.images[this.randomNum]={
              url:`app.media.sxcard0${this.randomNum}`,
              count:this.images[this.randomNum].count+1
            }
            // 判断卡片的数量
            // 如果卡片中有一个的数量为0,那就是没集齐
            let flag:boolean=true

            for(let item of this.images){
              if(item.count==0){
                flag=false
                break
              }
            }
            this.isGet=flag
            if(flag){
              let randomIndex:number=Math.floor(Math.random()*3)
              this.price=this.arr[randomIndex]
            }
          })
      }
      .justifyContent(FlexAlign.Center)// 居中对齐
      .width('100%')
      .height('100%')
      .backgroundColor('#cc000000')
      .zIndex(this.Level)
      .opacity(this.transparent)// 透明度
      // 动画
      .animation({
        duration:200
      })
      if(this.isGet){
        // 中奖页面
        Column(){
          Text('恭喜获得手机一部')
            .fontColor('#f5ebcf')
            .fontSize(25)
            .fontWeight(700)
          Image($r(`app.media.sxcard_${this.price}`))
            .width(300)
          Button('再来一次')
            .width(200)
            .height(50)
            .backgroundColor(Color.Transparent)
            .border({width:2,color:'#fff9e0'})
            .onClick(()=>{
              this.isGet=false
              this.price=''
              this.images=[
                {url:'app.media.sxcard',count:0},
                {url:'app.media.sxcard',count:0},
                {url:'app.media.sxcard',count:0},
                {url:'app.media.sxcard',count:0},
                {url:'app.media.sxcard',count:0},
                {url:'app.media.sxcard',count:0}
              ]
            })
        }
        .zIndex(10)
        .width('100%')
        .height('100%')
        .justifyContent(FlexAlign.Center)
        .backgroundColor('#cc000000')
      }
    }
  }
}

  • 17
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值