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

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

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

HarmonyOS NEXT Development Case: Guess the Ball Game

Lomanu4 Оффлайн

Lomanu4

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

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



This article demonstrates a simple "Guess the Ball" game implementation using HarmonyOS NEXT, featuring state management with decorators and animation control.

Core Implementation

1. Cup Class with State Tracking


// Use decorator for object change tracking
@ObservedV2
class Cup {
// Track property changes with decorators
@Trace positionX: number; // X-axis position
@Trace positionY: number; // Y-axis position
@Trace containsBall: boolean; // Whether contains the ball
@Trace isRevealed: boolean; // Whether cup is opened

// Constructor to initialize cup states
constructor(hasBall: boolean) {
this.positionX = 0;
this.positionY = 0;
this.containsBall = hasBall;
this.isRevealed = true;
}
}
2. Game Component Structure


@Entry
@Component
struct ThreeCupGame {
// Game state variables
@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;

// Game initialization
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]);
}

// Cup movement logic
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;

// Animation sequence for first cup
animateToImmediately({
delay: 0,
duration: this.animationDurationMs
}, () => {
this.gameCups[cupIndex1].positionY = -direction * (this.cupWidth + this.cupSpacing * 2) / adjustedDistanceFactor
});

// Animation sequence for second cup
animateToImmediately({
delay: 0,
duration: this.animationDurationMs
}, () => {
this.gameCups[cupIndex2].positionY = direction * (this.cupWidth + this.cupSpacing * 2) / adjustedDistanceFactor
});

// Animation completion handler
animateToImmediately({
delay: this.animationDurationMs * 2,
duration: this.animationDurationMs,
onFinish: () => {
this.swapBalls(cupIndex1, cupIndex2)
}
}, () => {
this.gameCups[cupIndex2].positionX = -(this.cupWidth + this.cupSpacing * 2) * distanceFactor
this.gameCups[cupIndex2].positionY = 0
});
}

// Ball swapping logic
swapBalls(cupIndex1: number, cupIndex2: number) {
[this.gameCups[cupIndex1].containsBall, this.gameCups[cupIndex2].containsBall] =
[this.gameCups[cupIndex2].containsBall, this.gameCups[cupIndex1].containsBall];

if (this.currentMixingCount <= 0) {
this.isGameAnimating = false;
} else {
setTimeout(() => this.startGame(), 10);
}
}

// UI Construction
build() {
Column({ space: 20 }) {
Text('Guess the Ball Game')
.fontSize(24)
.margin({ top: 20 });

// Animation speed control
Counter() {
Text(`Current Speed: ${this.animationDurationMs}ms`)
.fontColor(Color.Black)
.fontSize('26lpx');
}.onInc(() => this.animationDurationMs += 10)
.onDec(() => this.animationDurationMs = Math.max(10, this.animationDurationMs - 10));

// Mixing count control
Counter() {
Text(`Mixes per Round: ${this.mixingCount}`)
.fontColor(Color.Black)
.fontSize('26lpx');
}.onInc(() => this.mixingCount += 1)
.onDec(() => this.mixingCount = Math.max(1, this.mixingCount - 1));

// Cups layout
Row() {
ForEach(this.gameCups, (cup: Cup) => {
Text(cup.isRevealed ? (cup.containsBall ? 'Ball' : 'Empty') : '')
.size(`${this.cupWidth}lpx`)
.margin(`${this.cupSpacing}lpx`)
.backgroundColor(Color.Orange)
.translate({ x: `${cup.positionX}lpx`, y: `${cup.positionY}lpx` })
.onClick(() => {
if (!this.isGameAnimating) cup.isRevealed = true;
});
});
}.height('720lpx').backgroundColor(Color.Gray);

// Start button
Button('Start Game').onClick(() => {
if (!this.isGameAnimating) {
this.currentMixingCount = this.mixingCount;
this.isGameAnimating = true;
this.gameCups.forEach(cup => cup.isRevealed = false);
this.startGame();
}
});
}.size('100%');
}
}
Key Features

  1. State Management:
  2. @ObservedV2 and @Trace decorators enable efficient state tracking

  3. Automatic UI updates when cup properties change


  4. Animation System:


  5. Sequential animations using animateToImmediately


  6. Configurable duration and delay parameters


  7. Smooth transition effects for cup movements


  8. Game Logic:


  9. Random cup pair selection


  10. Configurable mixing count


  11. Ball position swapping mechanism


  12. UI Controls:


  13. Interactive speed adjustment


  14. Visual feedback for cup states


  15. Responsive layout adaptation
Usage

  1. Adjust animation speed using the speed control
  2. Set desired mixing count
  3. Click "Start Game" to begin
  4. Click cups after mixing to reveal contents
  5. Adjust parameters between rounds

This implementation demonstrates HarmonyOS NEXT's capabilities in handling complex state management, smooth animations, and responsive UI interactions. The decorator-based approach provides efficient state tracking while maintaining clean code structure.


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

 
Вверх Снизу