• Что бы вступить в ряды "Принятый кодер" Вам нужно:
    Написать 10 полезных сообщений или тем и Получить 10 симпатий.
    Для того кто не хочет терять время,может пожертвовать средства для поддержки сервеса, и вступить в ряды VIP на месяц, дополнительная информация в лс.

  • Пользаватели которые будут спамить, уходят в бан без предупреждения. Спам сообщения определяется администрацией и модератором.

  • Гость, Что бы Вы хотели увидеть на нашем Форуме? Изложить свои идеи и пожелания по улучшению форума Вы можете поделиться с нами здесь. ----> Перейдите сюда
  • Все пользователи не прошедшие проверку электронной почты будут заблокированы. Все вопросы с разблокировкой обращайтесь по адресу электронной почте : info@guardianelinks.com . Не пришло сообщение о проверке или о сбросе также сообщите нам.

HarmonyOS NEXT Development Case Study: Whac-A-Mole Game

Lomanu4 Оффлайн

Lomanu4

Команда форума
Администратор
Регистрация
1 Мар 2015
Сообщения
1,481
Баллы
155

Пожалуйста Авторизируйтесь или Зарегистрируйтесь для просмотра скрытого текста.



This article demonstrates how to implement a classic "Whac-A-Mole" game using HarmonyOS NEXT's ArkUI framework. The implementation showcases various UI components, animation handling, and state management capabilities.

Core Code Implementation

1. Hamster Component (Game Character)


import { curves, window } from '@kit.ArkUI'

@Component
struct Hamster {
@Prop cellWidth: number // Cell width for layout calculations

build() {
Stack() { // Stack layout container
// Body
Text()
.width(`${this.cellWidth / 2}lpx`)
.height(`${this.cellWidth / 3 * 2}lpx`)
.backgroundColor("#b49579")
.borderRadius({ topLeft: '50%', topRight: '50%' })
.borderColor("#2a272d")
.borderWidth(1)

// Mouth
Ellipse()
.width(`${this.cellWidth / 4}lpx`)
.height(`${this.cellWidth / 5}lpx`)
.fillOpacity(1)
.fill("#e7bad7")
.stroke("#563e3f")
.strokeWidth(1)
.margin({ top: `${this.cellWidth / 6}lpx`)

// Left eye
Ellipse()
.width(`${this.cellWidth / 9}lpx`)
.height(`${this.cellWidth / 6}lpx`)
.fillOpacity(1)
.fill("#313028")
.stroke("#2e2018")
.strokeWidth(1)
.margin({ bottom: `${this.cellWidth / 3}lpx`, right: `${this.cellWidth / 6}lpx`)

// Right eye
Ellipse()
.width(`${this.cellWidth / 9}lpx`)
.height(`${this.cellWidth / 6}lpx`)
.fillOpacity(1)
.fill("#313028")
.stroke("#2e2018")
.strokeWidth(1)
.margin({ bottom: `${this.cellWidth / 3}lpx`, left: `${this.cellWidth / 6}lpx`)

// Eye highlights
Ellipse()
.width(`${this.cellWidth / 20}lpx`)
.height(`${this.cellWidth / 15}lpx`)
.fillOpacity(1)
.fill("#fefbfa")
.margin({ bottom: `${this.cellWidth / 2.5}lpx`, right: `${this.cellWidth / 6}lpx`)

Ellipse()
.width(`${this.cellWidth / 20}lpx`)
.height(`${this.cellWidth / 15}lpx`)
.fillOpacity(1)
.fill("#fefbfa")
.margin({ bottom: `${this.cellWidth / 2.5}lpx`, left: `${this.cellWidth / 6}lpx`)
}.width(`${this.cellWidth}lpx`).height(`${this.cellWidth}lpx`)
}
}
2. Game Cell Management


@ObservedV2
class Cell {
@Trace scaleOptions: ScaleOptions = { x: 1, y: 1 };
@Trace isSelected: boolean = false
cellWidth: number
selectTime: number = 0

constructor(cellWidth: number) {
this.cellWidth = cellWidth
}

setSelectedTrueTime() {
this.selectTime = Date.now()
this.isSelected = true
}

checkTime(stayDuration: number) {
if (this.isSelected && Date.now() - this.selectTime >= stayDuration) {
this.selectTime = 0
this.isSelected = false
}
}
}
3. Game Timer Implementation


class MyTextTimerModifier implements ContentModifier<TextTimerConfiguration> {
applyContent(): WrappedBuilder<[TextTimerConfiguration]> {
return wrapBuilder(buildTextTimer)
}
}

@Builder
function buildTextTimer(config: TextTimerConfiguration) {
Column() {
Stack({ alignContent: Alignment.Center }) {
Circle({ width: 150, height: 150 })
.fill(config.started ? (config.isCountDown ? 0xFF232323 : 0xFF717171) : 0xFF929292)
Column() {
Text(config.isCountDown ? "Countdown" : "Elapsed Time").fontColor(Color.White)
Text(
(config.isCountDown ? "Remaining: " : "Elapsed: ") +
(config.isCountDown ?
Math.max(config.count/1000 - config.elapsedTime/100, 0).toFixed(0) :
(config.elapsedTime/100).toFixed(0)) + "s"
).fontColor(Color.White)
}
}
}
}
Key Implementation Points

1. Responsive Layout System

  • Uses lpx units for dynamic sizing
  • Flexible layout calculations based on cell dimensions
  • Adaptive component positioning using margin properties
2. Animation System

  • Spring animation curve implementation:

curves.springCurve(10, 1, 228, 30)
  • Scale transformations for hit effects
  • Timed visibility control for game elements
3. Game State Management


for (let i = 0; i < availableIndexList.length; i++) {
let index = Math.floor(Math.random() * (availableIndexList.length - i))
// Swap positions
}
4. Game Configuration

  • Customizable parameters:
    • gameDuration: Total game time
    • appearanceCount: Moles per wave
    • animationInterval: Spawn interval
    • hamsterStayDuration: Visible duration
Game Features

  1. Landscape orientation setup:

windowClass.setPreferredOrientation(window.Orientation.LANDSCAPE)
  1. Score tracking system
  2. Configurable game parameters
  3. Visual feedback mechanisms:
    • Scale animations
    • Color state indicators
  4. Game completion dialog:

showAlertDialog({ title: 'Game Over', message: `Score: ${currentScore}` })

This implementation demonstrates HarmonyOS NEXT's capabilities in building interactive games with complex state management and smooth animations. The component-based architecture allows for maintainable code structure while leveraging ArkUI's declarative syntax for efficient UI updates.

Developers can extend this foundation by:

  • Adding sound effects
  • Implementing difficulty levels
  • Creating progressive animation systems
  • Adding multiplayer support
  • Integrating with device sensors for alternative input methods

The complete code demonstrates best practices in HarmonyOS application development, including responsive design, state management, and user interaction handling.


Пожалуйста Авторизируйтесь или Зарегистрируйтесь для просмотра скрытого текста.

 
Вверх Снизу