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

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

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

HarmonyOS NEXT Development Case: 2048 Game Implementation

Lomanu4 Оффлайн

Lomanu4

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

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



This article demonstrates a 2048 game implementation using HarmonyOS NEXT, featuring reactive state management and gesture controls.

Core Implementation

1. Game Cell Class


// Decorator indicating observable state tracking
@ObservedV2
class Cell {
// Track value changes with decorator
@Trace value: number;

// Initialize cell value to 0
constructor() {
this.value = 0;
}
}
2. Main Game Component


@Entry
@Component
struct Game2048 {
// Game state variables
@State board: Cell[][] = []; // Game board cells
@State score: number = 0; // Current score
@State cellSize: number = 200; // Cell dimension
@State cellMargin: number = 5; // Cell spacing
@State screenStartX: number = 0; // Touch start X
@State screenStartY: number = 0; // Touch start Y
@State lastScreenX: number = 0; // Touch end X
@State lastScreenY: number = 0; // Touch end Y

// Color scheme for different values
colors: string[] = [
'#CCCCCC', // 0 - Gray
'#FFC107', // 2 - Yellow
'#FF9800', // 4 - Orange
'#FF5722', // 8 - Dark Orange
'#F44336', // 16 - Red
'#9C27B0', // 32 - Purple
'#3F51B5', // 64 - Indigo
'#00BCD4', // 128 - Cyan
'#009688', // 256 - Teal
'#4CAF50', // 512 - Green
'#8BC34A', // 1024 - Light Green
'#CDDC39', // 2048 - Lime
'#FFEB3B', // 4096 - Light Yellow
'#795548', // 8192 - Brown
'#607D8B', // 16384 - Dark Gray
'#9E9E9E', // 32768 - Gray
'#000000' // Above - Black
];

// Lifecycle method
aboutToAppear() {
this.resetGame();
}

// Initialize game board
initBoard() {
if (this.board.length === 0) {
for (let i = 0; i < 4; i++) {
let row: Cell[] = [];
for (let j = 0; j < 4; j++) {
row.push(new Cell());
}
this.board.push(row);
}
} else {
this.board.forEach(row => row.forEach(cell => cell.value = 0));
}
}

// Add new tiles to board
addRandomTiles(count: number) {
let emptyCells: {row: number, col: number}[] = [];
this.board.forEach((row, i) => {
row.forEach((cell, j) => {
if (cell.value === 0) emptyCells.push({row: i, col: j});
});
});

for (let i = 0; i < count; i++) {
if (emptyCells.length === 0) break;
const index = Math.floor(Math.random() * emptyCells.length);
const {row, col} = emptyCells[index];
this.board[row][col].value = Math.random() < 0.9 ? 2 : 4;
emptyCells.splice(index, 1);
}
}

// Slide movement logic (left example)
slideLeft() {
this.board.forEach((row, i) => {
let temp = row.filter(cell => cell.value !== 0).map(cell => cell.value);
let merged = new Array(4).fill(false);

for (let j = 0; j < temp.length - 1; j++) {
if (temp[j] === temp[j + 1] && !merged[j]) {
temp[j] *= 2;
this.score += temp[j];
merged[j] = true;
temp.splice(j + 1, 1);
}
}

while (temp.length < 4) temp.push(0);
row.forEach((cell, j) => cell.value = temp[j]);
});
}

// Similar implementations for slideRight(), slideUp(), slideDown()

// UI Construction
build() {
Column({ space: 10 }) {
Text(`Score: ${this.score}`)
.fontSize(24)
.margin({ top: 20 });

Flex({ wrap: FlexWrap.Wrap }) {
ForEach(this.board.flat(), (cell: Cell, index: number) => {
Text(`${cell.value || ''}`)
.size(`${this.cellSize}px`)
.margin(`${this.cellMargin}px`)
.fontSize(this.calculateFontSize(cell.value))
.backgroundColor(this.getCellColor(cell.value))
.fontColor(cell.value ? '#fff' : '#000');
});
}
.width(`${(this.cellSize + this.cellMargin * 2) * 4}px`);

Button('Restart').onClick(() => this.resetGame());
}
.gesture(
SwipeGesture({ direction: SwipeDirection.All })
.onAction(this.handleSwipe.bind(this))
);
}

// Helper methods
private resetGame() {
this.score = 0;
this.initBoard();
this.addRandomTiles(2);
}

private handleSwipe() {
const dx = this.lastScreenX - this.screenStartX;
const dy = this.lastScreenY - this.screenStartY;

if (Math.abs(dx) > Math.abs(dy)) {
dx > 0 ? this.slideRight() : this.slideLeft();
} else {
dy > 0 ? this.slideDown() : this.slideUp();
}

this.addRandomTiles(1);
}

private calculateFontSize(value: number): string {
return `${value >= 100 ? this.cellSize / 3 : this.cellSize / 2}px`;
}

private getCellColor(value: number): string {
return this.colors[value ? Math.floor(Math.log2(value)) : 0];
}
}
Key Features

  1. Reactive State Management:
  2. @ObservedV2 enables automatic UI updates
  3. @Trace tracks individual cell value changes

  4. State-driven UI rendering


  5. Gesture Control System:


  6. Comprehensive swipe detection


  7. Directional movement handling


  8. Touch coordinate tracking


  9. Game Logic:


  10. Tile merging algorithms


  11. Score calculation


  12. Random tile generation


  13. Game reset functionality


  14. Visual Design:


  15. Dynamic color scheme


  16. Adaptive font sizing


  17. Responsive grid layout


  18. Smooth animations


  19. Architecture:


  20. Separation of game logic and UI


  21. Helper methods for code organization


  22. Clean state management


  23. Lifecycle methods for game control
Technical Highlights

  1. Swipe Detection:

.gesture(
SwipeGesture({ direction: SwipeDirection.All })
.onAction((event) => {
const dx = event.offsetX;
const dy = event.offsetY;
// Handle direction based on dominant axis
})
)
  1. Dynamic Styling:

.backgroundColor(this.colors[value ? Math.floor(Math.log2(value)) : 0])
.fontSize(`${value >= 100 ? cellSize/3 : cellSize/2}px`)
  1. Efficient Board Updates:

// Example for left slide
let temp = row.filter(cell => cell.value !== 0).map(cell => cell.value);
while (temp.length < 4) temp.push(0);
row.forEach((cell, j) => cell.value = temp[j]);
  1. State Preservation:

aboutToAppear() {
this.resetGame();
}
Usage Guide

  1. Swipe in any direction to move tiles
  2. Matching numbers merge and increase score
  3. Game ends when board fills with no possible merges
  4. Click Restart to begin new game
  5. Observe color changes for different values

This implementation demonstrates HarmonyOS NEXT's capabilities in handling complex game logic, responsive touch controls, and efficient state management. The decorator-based approach ensures optimal performance while maintaining clean code structure.


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

 
Вверх Снизу