Location>code7788 >text

Hongmeng NEXT Development Case: Finger Roulette

Popularity:219 ℃/2024-11-11 19:06:59

 

[1] Introduction

"Finger Roulette" is a simple and interesting interactive game (similar to drawing lots), this application through the way of touching the screen, allowing players to participate in an exciting game, and ultimately choose the lucky winner. In the future, we can further expand the functions, such as adding game modes, optimizing animation effects, adding sound effects, etc., to enhance the user experience.

[2] Environmental Preparation

Computer system: windows 10

Development Tools: DevEco Studio NEXT Beta1 Build Version: 5.0.3.806

Engineering version: API 12

The real one: mate60 pro

Languages: ArkTS, ArkUI

[Functional Overview]

1. Display the title and game description to guide the player in the game.

2. Support multiple players to participate, each player is represented by a different color circle.

3. Dynamically update the interface state according to the number of fingers touching the screen.

4. Implementation of a countdown function whereby a player is randomly selected as the winner at the end of the countdown.

[Technical realization points]

1. Build interfaces and handle user interactions using the components and state management functions provided by the HM system.

2. Use animation effects to add zoom animation to the player circle to enhance the visual effect.

3. Countdown and random player selection by timer.

4. Handle touch events and update the player position and interface state based on the number of fingers.

[Development Process

1. Create a PlayerPosition class to manage player properties and animation effects.

2. Design the entry component (WheelGamePage), which contains the list of players, countdown timer, touch event handling and other functions.

3. Construction of a UI interface to display titles, explanatory text and player rounds for dynamic updating and interactive effects.

4. Implement the logic of countdown and random player selection to enhance the game experience.

[complete code]

@ObservedV2
  // Observation class for observing property changes
class PlayerPosition {
  @Trace isVisible: boolean = false // Whether the player is visible or not
  @Trace startX: number = 0 // Starting X coordinate of the player
  @Trace startY: number = 0 // Starting Y coordinate of the player
  @Trace scaleOptions: ScaleOptions = { x: 0.5, y: 0.5 } // Player zoom options
  cellWidth: number = 100 // The width of the player's circle
  color: string // Player color

  constructor(color: string) { // Constructor to initialize the color
     = color
  }

  isRunningAnimation: boolean = false // Whether the animation is running or not

  setShowAnimation() { // Setting the display animation
    if (!) { // If the animation is not running
       = true // Mark as running
      animateToImmediately({
        // Start animation
        delay: 0,
        duration: 500,
        curve: ,
        iterations: 1,
        onFinish: () => { // Callback when the animation is complete
          (`onFinish 1`)
          animateToImmediately({
            // Start the second animation
            delay: 0,
            duration: 300,
            iterations: -1,
            curve: ,
            onFinish: () => { // Callback after the second animation is complete
              (`onFinish 2`)
            }
          }, () => {
             = { x: 1.1, y: 1.1 } // Setting the zoom
          })
        }
      }, () => {
         = { x: 1.0, y: 1.0 } // Reset zoom at end of animation
      })
    }
  }
}

@Entry
  // Entry components
@Component
struct WheelGamePage {
  @State playerList: PlayerPosition[] = [// Player List
    new PlayerPosition("#26c2ff"),
    new PlayerPosition("#978efe"),
    new PlayerPosition("#c389fe"),
    new PlayerPosition("#ff85bd"),
    new PlayerPosition("#ff7051"),
    new PlayerPosition("#fea800"),
    new PlayerPosition("#ffcf18"),
    new PlayerPosition("#a9c92a"),
  ]
  @State showTitle: boolean = true // Whether to display the title
  @State showInstructions: boolean = true // Whether to display the description
  @State showCountdown: boolean = false // Whether to display a countdown timer
  @State @Watch('countdownNumberChanged') countdownNumber: number = 3 // Countdown digits
  @State selectIndex: number = -1 // Final selected player subscript
  countdownTimerId: number = 0 // Countdown timer ID
  randomSelectionTimerId: number = 0 // Randomly select timer ID

  countdownNumberChanged() { // Handler function for countdown changes
    if ( <= 0) { // If the countdown ends
      (); // Start random selection
    } else {
       = -1; // End random display
    }
  }

  startRandomSelection() { // Begin random player selection
    const len =  + (() * ); // Random length
    const visiblePlayers = (player => ); // Visible Player List
    (`visiblePlayers:${(visiblePlayers)}`);

    let count = 0; // Current count
    let iteration = 0; // current iteration number

    clearInterval(); // Clear the previous timer
     = setInterval(() => { // Setting a new timer
      (`count:${count}`);
      (`iteration:${iteration}`);
      (`len:${len}`);

      if (iteration >= len) { // If the number of iterations is reached
        clearInterval(); // Clear the timer
        return;
      }

       = count++ % ; // Randomly selected players
      iteration++; // Increase the number of iterations
    }, 150); // Every 150 milliseconds
  }

  updatePlayerPositions(touchPoints: TouchObject[]) { // Update player location
    ((player, index) => { // Iterate through the player list
      if (index < ) { // If the number of touch points is greater than the player index
         = true // Set the player to be visible
        () // Setting up the animation
         = touchPoints[index].x // Update the X coordinate
         = touchPoints[index].y // Update the Y coordinate
      } else {
         = false // Set the player invisible
      }
    })
  }

  updateTextState(touchCount: number) { // Update text status
     = 3 // Reset countdown
    if (touchCount === 0) { // If there is no touch
       = true // Display title
       = true // Show description
       = false // Hide the countdown
    } else if (touchCount === 1) { // If there is a touch
       = false // Hide the title
       = true // Show description
       = false // Hide the countdown
    } else if (touchCount >= 2) { // If there are two or more touches
       = false // Hide the title
       = false // Hide the description
       = true // Display countdown
      clearInterval() // Clear the previous countdown
       = setInterval(() => { // Setting a new countdown
        if ( >= 0) { // If the countdown is not over
          -- // Countdown minus one
        } else {
          clearInterval() // countdown ends, clear timer
        }
      }, 1000) // Executed every second
    }
  }

  build() { // Build the UI
    Stack() { // Create a stack layout
      Text("Finger Roulette.")// Display title text
        .width('100%')// 100% width
        .height(80)// Height 80
        .textAlign()// Text centering
        .fontSize(20)// Font size 20
        .fontColor("#0c0c0c")// font color
        .visibility( ?  : )// Set visibility based on status
        .draggable(false) // Not draggable
      Stack() { // Create another stack layout
        Text(`1. Invite your friends to join this exciting game!!simply2until (a time)${}One player can start。\n
2. When you're ready.,Ask each participant to reach out with one finger and gently press the screen of the cell phone。count down3seconds later,Game autostart,Or you can manually click“commencement”buttons。\n
3. Holding your fingers tightly,直until (a time)动画结束。Luck will favor one of the players.,Be the winner of the game.!`)// Show description text
          .textAlign()// Text alignment
          .fontSize(20)// Font size 20
          .fontColor("#0c0c0c")// font color
          .padding(20)// Inside margin 20
          .visibility( ?  : )// Set visibility based on status
          .draggable(false) // Not draggable

        Text( > 0 ? `count down${}seconds latercommencement` : ``)// Display countdown text
          .textAlign()// Text centering
          .fontSize(20)// Font size 20
          .fontColor("#0c0c0c")// font color
          .padding(20)// Inside margin 20
          .visibility( ?  : )// Set visibility based on status
          .draggable(false)
      }.width('100%').height('100%') // Set the stack width and height
      .draggable(false)

      ForEach(, (player: PlayerPosition, index: number) => { // Iterate through the player list
        Stack() { // Create a stack layout
          Circle()// Create an outer circle
            .width( + 10)// Outer ring width is 10 times larger than player width
            .height( + 10)// The height of the outer ring is 10 times greater than the height of the player
            .fill()// Fill the outer ring color
            .fillOpacity(0.5)// Set the outer ring transparency to 0.5
            .visibility( ?  : )// Set outer circle visibility based on player visibility
            .draggable(false)// Outer ring cannot be dragged
            .scale() // Set outer ring zoom options

          Circle()// Create an inner circle
            .width()// Inner ring width
            .height()// Inner ring height
            .fill()// Fill the inner circle with color
            .fillOpacity(1)// Set the inner circle transparency to 1
            .visibility( ?  : )// Set inner circle visibility based on player visibility
            .draggable(false)// Inner ring is not draggable
            .scale() // Set inner circle zoom options

        }.draggable(false) // Stack layout is not draggable
        .scale( == index ? { x: 1.5, y: 1.5 } : { x: 1.0, y: 1.0 }) // Set zoom based on selected state
        .margin({ left:  -  / 2, top:  -  / 2 }) // Setting the player position
      })
    }
    .align() // Set the stack alignment
    .height('100%') // Set the stack height to 100%
    .width('100%') // Set the stack width to 100%
    .draggable(false) // Stacks are not draggable
    .onTouch((event: TouchEvent) => { // Handling touch events
      if ( == ) { // Press event
        () // Update player location
        () // Update text status
      } else if ( == ) { // Move events
        () // Update player location
      } else if ( == ) { // Lift event
        ( - 1) // Update text status
        if ( - 1 === 0) { // If there is no touch
          ([]) // Empty player positions
        }
      } else if ( == ) { // Cancel event
        () // Update player location
      }
    })
  }
}