Two Eleven App aka 2048 (#16)
This commit is contained in:
@@ -0,0 +1,202 @@
|
||||
#include "TwoEleven.h"
|
||||
|
||||
#include <tt_lvgl_toolbar.h>
|
||||
#include <tt_app_alertdialog.h>
|
||||
#include <TactilityCpp/LvglLock.h>
|
||||
|
||||
constexpr auto* TAG = "TwoEleven";
|
||||
|
||||
static lv_obj_t* scoreLabel = nullptr;
|
||||
static lv_obj_t* scoreWrapper = nullptr;
|
||||
static lv_obj_t* toolbar = nullptr;
|
||||
static lv_obj_t* mainWrapper = nullptr;
|
||||
static lv_obj_t* newGameWrapper = nullptr;
|
||||
static lv_obj_t* gameObject = nullptr;
|
||||
|
||||
static uint16_t selectedSize = 4;
|
||||
|
||||
void TwoEleven::twoElevenEventCb(lv_event_t* e) {
|
||||
lv_event_code_t code = lv_event_get_code(e);
|
||||
lv_obj_t* obj_2048 = lv_event_get_target_obj(e);
|
||||
lv_obj_t* scoreLabel = (lv_obj_t *)lv_event_get_user_data(e);
|
||||
|
||||
const char* alertDialogLabels[] = { "OK" };
|
||||
|
||||
if (code == LV_EVENT_VALUE_CHANGED) {
|
||||
if (twoeleven_get_best_tile(obj_2048) >= 2048) {
|
||||
char message[64];
|
||||
sprintf(message, "YOU WIN!\n\nSCORE: %d", twoeleven_get_score(obj_2048));
|
||||
tt_app_alertdialog_start("YOU WIN!", message, alertDialogLabels, 1);
|
||||
} else if (twoeleven_get_status(obj_2048)) {
|
||||
char message[64];
|
||||
sprintf(message, "GAME OVER!\n\nSCORE: %d", twoeleven_get_score(obj_2048));
|
||||
tt_app_alertdialog_start("GAME OVER!", message, alertDialogLabels, 1);
|
||||
} else {
|
||||
lv_label_set_text_fmt(scoreLabel, "SCORE: %d", twoeleven_get_score(obj_2048));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TwoEleven::newGameBtnEvent(lv_event_t* e) {
|
||||
lv_obj_t* obj_2048 = (lv_obj_t *)lv_event_get_user_data(e);
|
||||
twoeleven_set_new_game(obj_2048);
|
||||
}
|
||||
|
||||
void TwoEleven::create_game(lv_obj_t* parent, uint16_t size, lv_obj_t* toolbar) {
|
||||
lv_obj_remove_flag(parent, LV_OBJ_FLAG_SCROLLABLE);
|
||||
lv_obj_set_flex_flow(parent, LV_FLEX_FLOW_COLUMN);
|
||||
|
||||
//game...
|
||||
gameObject = twoeleven_create(parent, size);
|
||||
lv_obj_set_style_text_font(gameObject, lv_font_get_default(), 0);
|
||||
lv_obj_set_size(gameObject, LV_PCT(100), LV_PCT(100));
|
||||
lv_obj_set_flex_grow(gameObject, 1);
|
||||
|
||||
scoreWrapper = lv_obj_create(toolbar);
|
||||
lv_obj_set_size(scoreWrapper, LV_SIZE_CONTENT, LV_PCT(100));
|
||||
lv_obj_set_style_pad_top(scoreWrapper, 4, LV_STATE_DEFAULT);
|
||||
lv_obj_set_style_pad_bottom(scoreWrapper, 0, LV_STATE_DEFAULT);
|
||||
lv_obj_set_style_pad_left(scoreWrapper, 0, LV_STATE_DEFAULT);
|
||||
lv_obj_set_style_pad_right(scoreWrapper, 10, LV_STATE_DEFAULT);
|
||||
lv_obj_set_style_pad_row(scoreWrapper, 0, LV_STATE_DEFAULT);
|
||||
lv_obj_set_style_pad_column(scoreWrapper, 0, LV_STATE_DEFAULT);
|
||||
lv_obj_set_style_border_width(scoreWrapper, 0, LV_STATE_DEFAULT);
|
||||
lv_obj_set_style_bg_opa(scoreWrapper, 0, LV_STATE_DEFAULT);
|
||||
lv_obj_remove_flag(scoreWrapper, LV_OBJ_FLAG_SCROLLABLE);
|
||||
|
||||
//toolbar new score
|
||||
scoreLabel = lv_label_create(scoreWrapper);
|
||||
lv_label_set_text_fmt(scoreLabel, "SCORE: %d", twoeleven_get_score(gameObject));
|
||||
lv_obj_set_style_text_align(scoreLabel, LV_TEXT_ALIGN_LEFT, LV_STATE_DEFAULT);
|
||||
lv_obj_align(scoreLabel, LV_ALIGN_CENTER, 0, 0);
|
||||
lv_obj_set_size(scoreLabel, LV_SIZE_CONTENT, LV_SIZE_CONTENT);
|
||||
lv_obj_set_style_text_font(scoreLabel, lv_font_get_default(), 0);
|
||||
lv_obj_set_style_text_color(scoreLabel, lv_palette_main(LV_PALETTE_AMBER), LV_PART_MAIN);
|
||||
lv_obj_add_event_cb(gameObject, twoElevenEventCb, LV_EVENT_ALL, scoreLabel);
|
||||
|
||||
newGameWrapper = lv_obj_create(toolbar);
|
||||
lv_obj_set_width(newGameWrapper, LV_SIZE_CONTENT);
|
||||
lv_obj_set_flex_flow(newGameWrapper, LV_FLEX_FLOW_ROW);
|
||||
lv_obj_set_style_pad_all(newGameWrapper, 2, LV_STATE_DEFAULT);
|
||||
lv_obj_set_style_border_width(newGameWrapper, 0, LV_STATE_DEFAULT);
|
||||
lv_obj_set_style_bg_opa(newGameWrapper, 0, LV_STATE_DEFAULT);
|
||||
|
||||
//toolbar reset
|
||||
lv_obj_t* newGameBtn = lv_btn_create(newGameWrapper);
|
||||
lv_obj_set_size(newGameBtn, 34, 34);
|
||||
lv_obj_set_style_pad_all(newGameBtn, 0, LV_STATE_DEFAULT);
|
||||
lv_obj_align(newGameBtn, LV_ALIGN_CENTER, 0, 0);
|
||||
lv_obj_add_event_cb(newGameBtn, newGameBtnEvent, LV_EVENT_CLICKED, gameObject);
|
||||
|
||||
lv_obj_t* btnLabel = lv_image_create(newGameBtn);
|
||||
lv_image_set_src(btnLabel, LV_SYMBOL_REFRESH);
|
||||
lv_obj_align(btnLabel, LV_ALIGN_CENTER, 0, 0);
|
||||
}
|
||||
|
||||
void TwoEleven::create_selection(lv_obj_t* parent, lv_obj_t* toolbar) {
|
||||
lv_obj_t* selection = lv_obj_create(parent);
|
||||
lv_obj_set_size(selection, LV_PCT(100), LV_PCT(100));
|
||||
lv_obj_set_flex_flow(selection, LV_FLEX_FLOW_COLUMN);
|
||||
lv_obj_set_flex_grow(selection, 1);
|
||||
lv_obj_remove_flag(selection, LV_OBJ_FLAG_SCROLLABLE);
|
||||
lv_obj_set_style_pad_all(selection, 0, LV_PART_MAIN);
|
||||
lv_obj_set_style_border_width(selection, 0, LV_STATE_DEFAULT);
|
||||
|
||||
lv_obj_t* titleWrapper = lv_obj_create(selection);
|
||||
lv_obj_set_size(titleWrapper, LV_PCT(100), LV_SIZE_CONTENT);
|
||||
lv_obj_set_style_pad_all(titleWrapper, 0, LV_STATE_DEFAULT);
|
||||
lv_obj_set_style_border_width(titleWrapper, 0, LV_STATE_DEFAULT);
|
||||
lv_obj_set_style_bg_opa(titleWrapper, 0, LV_STATE_DEFAULT);
|
||||
lv_obj_set_flex_flow(titleWrapper, LV_FLEX_FLOW_COLUMN);
|
||||
lv_obj_set_flex_align(titleWrapper, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER);
|
||||
lv_obj_remove_flag(titleWrapper, LV_OBJ_FLAG_SCROLLABLE);
|
||||
|
||||
lv_obj_t* titleLabel = lv_label_create(titleWrapper);
|
||||
lv_label_set_text(titleLabel, "Select Matrix Size");
|
||||
lv_obj_align(titleLabel, LV_ALIGN_CENTER, 0, 0);
|
||||
lv_obj_set_size(titleLabel, LV_SIZE_CONTENT, LV_SIZE_CONTENT);
|
||||
|
||||
lv_obj_t* controlsWrapper = lv_obj_create(titleWrapper);
|
||||
lv_obj_set_size(controlsWrapper, LV_PCT(100), LV_SIZE_CONTENT);
|
||||
lv_obj_set_style_pad_all(controlsWrapper, 0, LV_STATE_DEFAULT);
|
||||
lv_obj_set_style_border_width(controlsWrapper, 0, LV_STATE_DEFAULT);
|
||||
lv_obj_set_style_bg_opa(controlsWrapper, 0, LV_STATE_DEFAULT);
|
||||
lv_obj_set_flex_flow(controlsWrapper, LV_FLEX_FLOW_COLUMN);
|
||||
lv_obj_set_flex_align(controlsWrapper, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER);
|
||||
lv_obj_remove_flag(controlsWrapper, LV_OBJ_FLAG_SCROLLABLE);
|
||||
|
||||
lv_obj_t* touchControlsLabel = lv_label_create(controlsWrapper);
|
||||
lv_label_set_text(touchControlsLabel, "Touchscreen:\nSwipe up, down, left, right to move tiles.");
|
||||
lv_obj_set_style_text_font(touchControlsLabel, lv_font_get_default(), 0);
|
||||
lv_obj_set_style_text_align(touchControlsLabel, LV_TEXT_ALIGN_CENTER, 0);
|
||||
|
||||
lv_obj_t* keyControlsLabel = lv_label_create(controlsWrapper);
|
||||
lv_label_set_text_fmt(keyControlsLabel, "Keyboard:\nUse arrow keys (%s, %s, %s, %s) to move tiles.", LV_SYMBOL_UP, LV_SYMBOL_DOWN, LV_SYMBOL_LEFT, LV_SYMBOL_RIGHT);
|
||||
lv_obj_set_style_text_font(keyControlsLabel, lv_font_get_default(), 0);
|
||||
lv_obj_set_style_text_align(keyControlsLabel, LV_TEXT_ALIGN_CENTER, 0);
|
||||
|
||||
lv_obj_t* buttonContainer = lv_obj_create(selection);
|
||||
lv_obj_set_flex_flow(buttonContainer, LV_FLEX_FLOW_ROW);
|
||||
lv_obj_set_flex_align(buttonContainer, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER);
|
||||
lv_obj_remove_flag(buttonContainer, LV_OBJ_FLAG_SCROLLABLE);
|
||||
lv_obj_set_size(buttonContainer, LV_PCT(100), LV_SIZE_CONTENT);
|
||||
lv_obj_set_style_bg_opa(buttonContainer, 0, LV_STATE_DEFAULT);
|
||||
lv_obj_set_style_border_width(buttonContainer, 0, LV_STATE_DEFAULT);
|
||||
|
||||
for(int s = 3; s <= 6; s++) {
|
||||
lv_obj_t* btn = lv_btn_create(buttonContainer);
|
||||
lv_obj_set_size(btn, 60, 40);
|
||||
lv_obj_t* lbl = lv_label_create(btn);
|
||||
char txt[10];
|
||||
sprintf(txt, "%dx%d", s, s);
|
||||
lv_label_set_text(lbl, txt);
|
||||
lv_obj_center(lbl);
|
||||
lv_obj_add_event_cb(btn, size_select_cb, LV_EVENT_CLICKED, (void*)s);
|
||||
}
|
||||
}
|
||||
|
||||
void TwoEleven::size_select_cb(lv_event_t* e) {
|
||||
selectedSize = (uint16_t)(uintptr_t)lv_event_get_user_data(e);
|
||||
lv_obj_t* selection = lv_obj_get_parent(lv_event_get_target_obj(e));
|
||||
lv_obj_t* selectionWrapper = lv_obj_get_parent(selection);
|
||||
lv_obj_clean(selectionWrapper);
|
||||
scoreLabel = nullptr;
|
||||
scoreWrapper = nullptr;
|
||||
newGameWrapper = nullptr;
|
||||
gameObject = nullptr;
|
||||
create_game(selectionWrapper, selectedSize, toolbar);
|
||||
}
|
||||
|
||||
void TwoEleven::onShow(AppHandle appHandle, lv_obj_t* parent) {
|
||||
lv_obj_remove_flag(parent, LV_OBJ_FLAG_SCROLLABLE);
|
||||
lv_obj_set_flex_flow(parent, LV_FLEX_FLOW_COLUMN);
|
||||
|
||||
toolbar = tt_lvgl_toolbar_create_for_app(parent, appHandle);
|
||||
lv_obj_align(toolbar, LV_ALIGN_TOP_MID, 0, 0);
|
||||
|
||||
mainWrapper = lv_obj_create(parent);
|
||||
lv_obj_set_width(mainWrapper, LV_PCT(100));
|
||||
lv_obj_set_height(mainWrapper, LV_PCT(100));
|
||||
lv_obj_set_flex_grow(mainWrapper, 1);
|
||||
lv_obj_set_style_pad_all(mainWrapper, 2, LV_PART_MAIN);
|
||||
lv_obj_set_style_pad_row(mainWrapper, 2, LV_PART_MAIN);
|
||||
lv_obj_set_style_pad_column(mainWrapper, 2, LV_PART_MAIN);
|
||||
lv_obj_set_style_border_width(mainWrapper, 0, LV_PART_MAIN);
|
||||
lv_obj_remove_flag(mainWrapper, LV_OBJ_FLAG_SCROLLABLE);
|
||||
|
||||
create_selection(mainWrapper, toolbar);
|
||||
}
|
||||
|
||||
void TwoEleven::onResult(AppHandle appHandle, void* _Nullable data, AppLaunchId launchId, AppResult result, BundleHandle resultData) {
|
||||
if (result == APP_RESULT_OK && resultData != nullptr) {
|
||||
// Dialog closed with OK, go back to selection
|
||||
tt_lvgl_lock(TT_LVGL_DEFAULT_LOCK_TIME);
|
||||
lv_obj_clean(mainWrapper);
|
||||
scoreLabel = nullptr;
|
||||
scoreWrapper = nullptr;
|
||||
newGameWrapper = nullptr;
|
||||
gameObject = nullptr;
|
||||
create_selection(mainWrapper, toolbar);
|
||||
tt_lvgl_unlock();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
#pragma once
|
||||
|
||||
#include <tt_app.h>
|
||||
|
||||
#include <lvgl.h>
|
||||
#include <TactilityCpp/App.h>
|
||||
|
||||
#include "TwoElevenUi.h"
|
||||
#include "TwoElevenLogic.h"
|
||||
#include "TwoElevenHelpers.h"
|
||||
|
||||
class TwoEleven final : public App {
|
||||
|
||||
static void twoElevenEventCb(lv_event_t* e);
|
||||
static void newGameBtnEvent(lv_event_t* e);
|
||||
static void create_game(lv_obj_t* parent, uint16_t size, lv_obj_t* toolbar);
|
||||
static void create_selection(lv_obj_t* parent, lv_obj_t* toolbar);
|
||||
static void size_select_cb(lv_event_t* e);
|
||||
|
||||
public:
|
||||
|
||||
void onShow(AppHandle context, lv_obj_t* parent) override;
|
||||
void onResult(AppHandle appHandle, void* _Nullable data, AppLaunchId launchId, AppResult result, BundleHandle resultData) override;
|
||||
};
|
||||
@@ -0,0 +1,130 @@
|
||||
#include "TwoElevenHelpers.h"
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
/**
|
||||
* @brief Get the color for a given tile value
|
||||
*/
|
||||
lv_color_t get_num_color(uint16_t num)
|
||||
{
|
||||
switch (num) {
|
||||
case 0:
|
||||
return ELEVENTWO_NUMBER_EMPTY_COLOR;
|
||||
case 1:
|
||||
return ELEVENTWO_NUMBER_EMPTY_COLOR;
|
||||
case 2:
|
||||
return ELEVENTWO_NUMBER_2_COLOR;
|
||||
case 4:
|
||||
return ELEVENTWO_NUMBER_4_COLOR;
|
||||
case 8:
|
||||
return ELEVENTWO_NUMBER_8_COLOR;
|
||||
case 16:
|
||||
return ELEVENTWO_NUMBER_16_COLOR;
|
||||
case 32:
|
||||
return ELEVENTWO_NUMBER_32_COLOR;
|
||||
case 64:
|
||||
return ELEVENTWO_NUMBER_64_COLOR;
|
||||
case 128:
|
||||
return ELEVENTWO_NUMBER_128_COLOR;
|
||||
case 256:
|
||||
return ELEVENTWO_NUMBER_256_COLOR;
|
||||
case 512:
|
||||
return ELEVENTWO_NUMBER_512_COLOR;
|
||||
case 1024:
|
||||
return ELEVENTWO_NUMBER_1024_COLOR;
|
||||
case 2048:
|
||||
return ELEVENTWO_NUMBER_2048_COLOR;
|
||||
default:
|
||||
return ELEVENTWO_NUMBER_2048_COLOR;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Count empty cells in the matrix
|
||||
*/
|
||||
uint8_t count_empty(uint16_t matrix_size, const uint16_t **matrix) {
|
||||
uint8_t count = 0;
|
||||
for (uint8_t x = 0; x < matrix_size; x++) {
|
||||
for (uint8_t y = 0; y < matrix_size; y++) {
|
||||
if (matrix[x][y] == 0) count++;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Find if any adjacent pairs exist (for move possibility)
|
||||
*/
|
||||
bool find_pair_down(uint16_t matrix_size, const uint16_t **matrix) {
|
||||
for (uint8_t x = 0; x < matrix_size; x++) {
|
||||
for (uint8_t y = 0; y < matrix_size - 1; y++) {
|
||||
if (matrix[x][y] == matrix[x][y+1]) return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Rotate the matrix 90 degrees clockwise (in-place)
|
||||
* Used for move logic
|
||||
*/
|
||||
void rotate_matrix(uint16_t matrix_size, uint16_t **matrix) {
|
||||
uint8_t n = matrix_size;
|
||||
for (uint8_t i = 0; i < n / 2; i++) {
|
||||
for (uint8_t j = i; j < n - i - 1; j++) {
|
||||
uint16_t tmp = matrix[i][j];
|
||||
matrix[i][j] = matrix[n - j - 1][i];
|
||||
matrix[n - j - 1][i] = matrix[n - i - 1][n - j - 1];
|
||||
matrix[n - i - 1][n - j - 1] = matrix[j][n - i - 1];
|
||||
matrix[j][n - i - 1] = tmp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Slide and merge a single row/column
|
||||
*/
|
||||
bool slide_array(uint16_t * score, uint16_t matrix_size, uint16_t *array) {
|
||||
bool success = false;
|
||||
uint8_t stop = 0;
|
||||
for (uint8_t x = 0; x < matrix_size; x++) {
|
||||
if (array[x] != 0) {
|
||||
uint8_t t = x;
|
||||
while (t > stop && array[t-1] == 0) {
|
||||
array[t-1] = array[t];
|
||||
array[t] = 0;
|
||||
t--;
|
||||
success = true;
|
||||
}
|
||||
if (t > stop && array[t-1] == array[t]) {
|
||||
array[t-1]++;
|
||||
*score += (1U << array[t-1]);
|
||||
array[t] = 0;
|
||||
stop = t;
|
||||
success = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Update the button map with current matrix values
|
||||
*/
|
||||
void update_btnm_map(uint16_t matrix_size, char ** btnm_map, const uint16_t **matrix)
|
||||
{
|
||||
uint8_t index = 0;
|
||||
for (uint8_t x = 0; x < matrix_size; x++) {
|
||||
for (uint8_t y = 0; y < matrix_size; y++) {
|
||||
if (((index + 1) % (matrix_size + 1)) == 0) {
|
||||
index++;
|
||||
}
|
||||
if (matrix[x][y] != 0) {
|
||||
snprintf(btnm_map[index], 16, "%d", (1 << matrix[x][y]));
|
||||
} else {
|
||||
strcpy(btnm_map[index], " ");
|
||||
}
|
||||
index++;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
#ifndef TWOELEVEN_HELPERS_H
|
||||
#define TWOELEVEN_HELPERS_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "lvgl.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
#define ELEVENTWO_BG_COLOR lv_color_hex(0xb3a397)
|
||||
#define ELEVENTWO_TEXT_BLACK_COLOR lv_color_hex(0x6c635b)
|
||||
#define ELEVENTWO_TEXT_WHITE_COLOR lv_color_hex(0xf8f5f0)
|
||||
#define ELEVENTWO_NUMBER_EMPTY_COLOR lv_color_hex(0xc7b9ac)
|
||||
#define ELEVENTWO_NUMBER_2_COLOR lv_color_hex(0xeee4da)
|
||||
#define ELEVENTWO_NUMBER_4_COLOR lv_color_hex(0xede0c8)
|
||||
#define ELEVENTWO_NUMBER_8_COLOR lv_color_hex(0xf2b179)
|
||||
#define ELEVENTWO_NUMBER_16_COLOR lv_color_hex(0xf59563)
|
||||
#define ELEVENTWO_NUMBER_32_COLOR lv_color_hex(0xf67c5f)
|
||||
#define ELEVENTWO_NUMBER_64_COLOR lv_color_hex(0xf75f3b)
|
||||
#define ELEVENTWO_NUMBER_128_COLOR lv_color_hex(0xedcf72)
|
||||
#define ELEVENTWO_NUMBER_256_COLOR lv_color_hex(0xedcc61)
|
||||
#define ELEVENTWO_NUMBER_512_COLOR lv_color_hex(0xedc850)
|
||||
#define ELEVENTWO_NUMBER_1024_COLOR lv_color_hex(0xedc53f)
|
||||
#define ELEVENTWO_NUMBER_2048_COLOR lv_color_hex(0xedc22e)
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
/**
|
||||
* @brief Struct for 2048 game state
|
||||
*/
|
||||
struct twoeleven_t {
|
||||
lv_obj_t * btnm;
|
||||
uint16_t score;
|
||||
uint16_t map_count;
|
||||
uint16_t matrix_size;
|
||||
uint16_t **matrix;
|
||||
char ** btnm_map;
|
||||
bool game_over;
|
||||
};
|
||||
|
||||
typedef struct twoeleven_t twoeleven_t;
|
||||
|
||||
/***********************
|
||||
* FUNCTION PROTOTYPES
|
||||
**********************/
|
||||
/**
|
||||
* @brief Get the color for a given tile value
|
||||
*/
|
||||
lv_color_t get_num_color(uint16_t num);
|
||||
|
||||
/**
|
||||
* @brief Count empty cells in the matrix
|
||||
*/
|
||||
uint8_t count_empty(uint16_t matrix_size, const uint16_t **matrix);
|
||||
|
||||
/**
|
||||
* @brief Find if any adjacent pairs exist (for move possibility)
|
||||
*/
|
||||
bool find_pair_down(uint16_t matrix_size, const uint16_t **matrix);
|
||||
|
||||
/**
|
||||
* @brief Rotate the matrix 90 degrees clockwise (in-place)
|
||||
* Used for move logic
|
||||
*/
|
||||
void rotate_matrix(uint16_t matrix_size, uint16_t **matrix);
|
||||
|
||||
/**
|
||||
* @brief Slide and merge a single row/column
|
||||
*/
|
||||
bool slide_array(uint16_t * score, uint16_t matrix_size, uint16_t *array);
|
||||
|
||||
/**
|
||||
* @brief Update the button map with current matrix values
|
||||
*/
|
||||
void update_btnm_map(uint16_t matrix_size, char ** btnm_map, const uint16_t **matrix);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /*TWOELEVEN_HELPERS_H*/
|
||||
@@ -0,0 +1,162 @@
|
||||
#include "TwoElevenLogic.h"
|
||||
#include "TwoElevenHelpers.h"
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
#include <string.h>
|
||||
|
||||
/**
|
||||
* @brief Initialize the matrix with two random tiles
|
||||
*/
|
||||
void init_matrix_num(uint16_t matrix_size, uint16_t **matrix)
|
||||
{
|
||||
for (uint8_t x = 0; x < matrix_size; x++) {
|
||||
for (uint8_t y = 0; y < matrix_size; y++) {
|
||||
matrix[x][y] = 0;
|
||||
}
|
||||
}
|
||||
// Add two random tiles
|
||||
add_random(matrix_size, matrix);
|
||||
add_random(matrix_size, matrix);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Add a random tile (2 or 4) to the matrix
|
||||
*/
|
||||
void add_random(uint16_t matrix_size, uint16_t **matrix)
|
||||
{
|
||||
static bool initialized = false;
|
||||
if (!initialized) {
|
||||
srand((unsigned int)time(NULL));
|
||||
initialized = true;
|
||||
}
|
||||
uint16_t empty[matrix_size * matrix_size][2];
|
||||
uint16_t len = 0;
|
||||
for (uint8_t x = 0; x < matrix_size; x++) {
|
||||
for (uint8_t y = 0; y < matrix_size; y++) {
|
||||
if (matrix[x][y] == 0) {
|
||||
empty[len][0] = x;
|
||||
empty[len][1] = y;
|
||||
len++;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (len > 0) {
|
||||
uint16_t r = rand() % len;
|
||||
uint8_t x = empty[r][0];
|
||||
uint8_t y = empty[r][1];
|
||||
uint16_t n = (rand() % 10 == 0) ? 2 : 1; // 10% chance for 4, else 2
|
||||
matrix[x][y] = n;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Move up (or left/right/down via rotation)
|
||||
*/
|
||||
bool move_up(uint16_t * score, uint16_t matrix_size, uint16_t **matrix) {
|
||||
bool success = false;
|
||||
for (uint8_t x = 0; x < matrix_size; x++) {
|
||||
success |= slide_array(score, matrix_size, matrix[x]);
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
bool move_down(uint16_t * score, uint16_t matrix_size, uint16_t **matrix) {
|
||||
rotate_matrix(matrix_size, matrix);
|
||||
rotate_matrix(matrix_size, matrix);
|
||||
bool success = move_up(score, matrix_size, matrix);
|
||||
rotate_matrix(matrix_size, matrix);
|
||||
rotate_matrix(matrix_size, matrix);
|
||||
return success;
|
||||
}
|
||||
|
||||
bool move_left(uint16_t * score, uint16_t matrix_size, uint16_t **matrix) {
|
||||
rotate_matrix(matrix_size, matrix);
|
||||
bool success = move_up(score, matrix_size, matrix);
|
||||
rotate_matrix(matrix_size, matrix);
|
||||
rotate_matrix(matrix_size, matrix);
|
||||
rotate_matrix(matrix_size, matrix);
|
||||
return success;
|
||||
}
|
||||
|
||||
bool move_right(uint16_t * score, uint16_t matrix_size, uint16_t **matrix) {
|
||||
rotate_matrix(matrix_size, matrix);
|
||||
rotate_matrix(matrix_size, matrix);
|
||||
rotate_matrix(matrix_size, matrix);
|
||||
bool success = move_up(score, matrix_size, matrix);
|
||||
rotate_matrix(matrix_size, matrix);
|
||||
return success;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Check if the game is over (no moves left)
|
||||
* Does not mutate the original matrix
|
||||
*/
|
||||
bool game_over(uint16_t matrix_size, const uint16_t **matrix) {
|
||||
if (count_empty(matrix_size, matrix) > 0) return false;
|
||||
if (find_pair_down(matrix_size, matrix)) return false;
|
||||
// Check for possible moves in rotated matrices
|
||||
uint16_t **temp = lv_malloc(matrix_size * sizeof(uint16_t*));
|
||||
for (uint16_t i = 0; i < matrix_size; i++) {
|
||||
temp[i] = lv_malloc(matrix_size * sizeof(uint16_t));
|
||||
memcpy(temp[i], matrix[i], matrix_size * sizeof(uint16_t));
|
||||
}
|
||||
rotate_matrix(matrix_size, temp);
|
||||
if (find_pair_down(matrix_size, (const uint16_t **)temp)) {
|
||||
for (uint16_t i = 0; i < matrix_size; i++) lv_free(temp[i]);
|
||||
lv_free(temp);
|
||||
return false;
|
||||
}
|
||||
rotate_matrix(matrix_size, temp);
|
||||
if (find_pair_down(matrix_size, (const uint16_t **)temp)) {
|
||||
for (uint16_t i = 0; i < matrix_size; i++) lv_free(temp[i]);
|
||||
lv_free(temp);
|
||||
return false;
|
||||
}
|
||||
rotate_matrix(matrix_size, temp);
|
||||
if (find_pair_down(matrix_size, (const uint16_t **)temp)) {
|
||||
for (uint16_t i = 0; i < matrix_size; i++) lv_free(temp[i]);
|
||||
lv_free(temp);
|
||||
return false;
|
||||
}
|
||||
for (uint16_t i = 0; i < matrix_size; i++) lv_free(temp[i]);
|
||||
lv_free(temp);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the current score
|
||||
*/
|
||||
uint16_t twoeleven_get_score(lv_obj_t * obj)
|
||||
{
|
||||
const twoeleven_t * game_2048 = (const twoeleven_t *)lv_obj_get_user_data(obj);
|
||||
if (!game_2048) return 0;
|
||||
return game_2048->score;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the game over status
|
||||
*/
|
||||
bool twoeleven_get_status(lv_obj_t * obj)
|
||||
{
|
||||
const twoeleven_t * game_2048 = (const twoeleven_t *)lv_obj_get_user_data(obj);
|
||||
if (!game_2048) return true;
|
||||
return game_2048->game_over;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the best tile value
|
||||
*/
|
||||
uint16_t twoeleven_get_best_tile(lv_obj_t * obj)
|
||||
{
|
||||
const twoeleven_t * game_2048 = (const twoeleven_t *)lv_obj_get_user_data(obj);
|
||||
if (!game_2048) return 0;
|
||||
uint16_t best_tile = 0;
|
||||
for (uint8_t x = 0; x < game_2048->matrix_size; x++) {
|
||||
for (uint8_t y = 0; y < game_2048->matrix_size; y++) {
|
||||
if (best_tile < game_2048->matrix[x][y]) {
|
||||
best_tile = game_2048->matrix[x][y];
|
||||
}
|
||||
}
|
||||
}
|
||||
return (uint16_t)(1 << best_tile);
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
#ifndef TWOELEVEN_LOGIC_H
|
||||
#define TWOELEVEN_LOGIC_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "TwoElevenHelpers.h"
|
||||
|
||||
/***********************
|
||||
* FUNCTION PROTOTYPES
|
||||
**********************/
|
||||
/**
|
||||
* @brief Initialize the matrix with two random tiles
|
||||
*/
|
||||
void init_matrix_num(uint16_t matrix_size, uint16_t **matrix);
|
||||
|
||||
/**
|
||||
* @brief Add a random tile (2 or 4) to the matrix
|
||||
*/
|
||||
void add_random(uint16_t matrix_size, uint16_t **matrix);
|
||||
|
||||
/**
|
||||
* @brief Move up
|
||||
*/
|
||||
bool move_up(uint16_t * score, uint16_t matrix_size, uint16_t **matrix);
|
||||
|
||||
/**
|
||||
* @brief Move down
|
||||
*/
|
||||
bool move_down(uint16_t * score, uint16_t matrix_size, uint16_t **matrix);
|
||||
|
||||
/**
|
||||
* @brief Move left
|
||||
*/
|
||||
bool move_left(uint16_t * score, uint16_t matrix_size, uint16_t **matrix);
|
||||
|
||||
/**
|
||||
* @brief Move right
|
||||
*/
|
||||
bool move_right(uint16_t * score, uint16_t matrix_size, uint16_t **matrix);
|
||||
|
||||
/**
|
||||
* @brief Check if the game is over (no moves left)
|
||||
* Does not mutate the original matrix
|
||||
*/
|
||||
bool game_over(uint16_t matrix_size, const uint16_t **matrix);
|
||||
|
||||
/**
|
||||
* @brief Get the current score
|
||||
*/
|
||||
uint16_t twoeleven_get_score(lv_obj_t * obj);
|
||||
|
||||
/**
|
||||
* @brief Get the game over status
|
||||
*/
|
||||
bool twoeleven_get_status(lv_obj_t * obj);
|
||||
|
||||
/**
|
||||
* @brief Get the best tile value
|
||||
*/
|
||||
uint16_t twoeleven_get_best_tile(lv_obj_t * obj);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /*TWOELEVEN_LOGIC_H*/
|
||||
@@ -0,0 +1,242 @@
|
||||
#include "TwoElevenUi.h"
|
||||
#include "TwoElevenLogic.h"
|
||||
#include "TwoElevenHelpers.h"
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
static void game_play_event(lv_event_t * e);
|
||||
static void btnm_event_cb(lv_event_t * e);
|
||||
|
||||
/**
|
||||
* @brief Free all resources for the 2048 game object
|
||||
*/
|
||||
static void delete_event(lv_event_t * e)
|
||||
{
|
||||
lv_obj_t * obj = lv_event_get_target_obj(e);
|
||||
twoeleven_t * game_2048 = (twoeleven_t *)lv_obj_get_user_data(obj);
|
||||
if (game_2048) {
|
||||
for (uint16_t index = 0; index < game_2048->map_count; index++) {
|
||||
if (game_2048->btnm_map[index]) {
|
||||
lv_free(game_2048->btnm_map[index]);
|
||||
game_2048->btnm_map[index] = NULL;
|
||||
}
|
||||
}
|
||||
lv_free(game_2048->btnm_map);
|
||||
// Free matrix
|
||||
for (uint16_t i = 0; i < game_2048->matrix_size; i++) {
|
||||
lv_free(game_2048->matrix[i]);
|
||||
}
|
||||
lv_free(game_2048->matrix);
|
||||
lv_free(game_2048);
|
||||
lv_obj_set_user_data(obj, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Create a new 2048 game object
|
||||
*/
|
||||
lv_obj_t * twoeleven_create(lv_obj_t * parent, uint16_t matrix_size)
|
||||
{
|
||||
lv_obj_t * obj = lv_obj_create(parent);
|
||||
if (!obj) return NULL;
|
||||
twoeleven_t * game_2048 = (twoeleven_t *)lv_malloc(sizeof(twoeleven_t));
|
||||
if (!game_2048) {
|
||||
lv_obj_delete(obj);
|
||||
return NULL;
|
||||
}
|
||||
lv_obj_set_user_data(obj, game_2048);
|
||||
|
||||
game_2048->score = 0;
|
||||
game_2048->game_over = false;
|
||||
// Limit matrix size to 3x3 to 6x6, default to 4x4 if out of range
|
||||
if (matrix_size < 3 || matrix_size > 6) {
|
||||
matrix_size = 4;
|
||||
}
|
||||
game_2048->matrix_size = matrix_size;
|
||||
game_2048->map_count = game_2048->matrix_size * game_2048->matrix_size + game_2048->matrix_size;
|
||||
|
||||
// Allocate matrix
|
||||
game_2048->matrix = lv_malloc(game_2048->matrix_size * sizeof(uint16_t*));
|
||||
if (!game_2048->matrix) {
|
||||
lv_free(game_2048);
|
||||
lv_obj_delete(obj);
|
||||
return NULL;
|
||||
}
|
||||
for (uint16_t i = 0; i < game_2048->matrix_size; i++) {
|
||||
game_2048->matrix[i] = lv_malloc(game_2048->matrix_size * sizeof(uint16_t));
|
||||
if (!game_2048->matrix[i]) {
|
||||
for (uint16_t j = 0; j < i; j++) lv_free(game_2048->matrix[j]);
|
||||
lv_free(game_2048->matrix);
|
||||
lv_free(game_2048);
|
||||
lv_obj_delete(obj);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
// Allocate button map
|
||||
game_2048->btnm_map = lv_malloc(game_2048->map_count * sizeof(char*));
|
||||
for (uint16_t index = 0; index < game_2048->map_count; index++) {
|
||||
if (((index + 1) % (game_2048->matrix_size + 1)) == 0) {
|
||||
game_2048->btnm_map[index] = (char *)lv_malloc(2);
|
||||
if (!game_2048->btnm_map[index]) continue;
|
||||
if ((index + 1) == game_2048->map_count)
|
||||
strcpy(game_2048->btnm_map[index], "");
|
||||
else
|
||||
strcpy(game_2048->btnm_map[index], "\n");
|
||||
} else {
|
||||
game_2048->btnm_map[index] = (char *)lv_malloc(16);
|
||||
if (!game_2048->btnm_map[index]) continue;
|
||||
strcpy(game_2048->btnm_map[index], " ");
|
||||
}
|
||||
}
|
||||
|
||||
init_matrix_num(game_2048->matrix_size, game_2048->matrix);
|
||||
update_btnm_map(game_2048->matrix_size, game_2048->btnm_map, (const uint16_t **)game_2048->matrix);
|
||||
|
||||
// Style initialization (unchanged)
|
||||
lv_obj_set_style_outline_color(obj, lv_theme_get_color_primary(obj), LV_STATE_FOCUS_KEY);
|
||||
lv_obj_set_style_outline_width(obj, lv_display_dpx(lv_obj_get_disp(obj), 2), LV_STATE_FOCUS_KEY);
|
||||
lv_obj_set_style_outline_pad(obj, lv_display_dpx(lv_obj_get_disp(obj), 2), LV_STATE_FOCUS_KEY);
|
||||
lv_obj_set_style_outline_opa(obj, LV_OPA_50, LV_STATE_FOCUS_KEY);
|
||||
|
||||
// Create button matrix
|
||||
game_2048->btnm = lv_btnmatrix_create(obj);
|
||||
lv_obj_set_size(game_2048->btnm, LV_PCT(100), LV_PCT(100));
|
||||
lv_obj_center(game_2048->btnm);
|
||||
lv_obj_set_style_pad_all(game_2048->btnm, 10, LV_PART_MAIN | LV_STATE_DEFAULT);
|
||||
lv_obj_set_style_border_width(game_2048->btnm, 0, LV_PART_MAIN | LV_STATE_DEFAULT);
|
||||
lv_obj_set_style_bg_color(game_2048->btnm, ELEVENTWO_BG_COLOR, LV_PART_MAIN);
|
||||
lv_group_remove_obj(game_2048->btnm);
|
||||
lv_obj_add_flag(game_2048->btnm, LV_OBJ_FLAG_SEND_DRAW_TASK_EVENTS);
|
||||
lv_obj_remove_flag(game_2048->btnm, LV_OBJ_FLAG_GESTURE_BUBBLE);
|
||||
|
||||
lv_btnmatrix_set_map(game_2048->btnm, (const char **)game_2048->btnm_map);
|
||||
lv_btnmatrix_set_btn_ctrl_all(game_2048->btnm, LV_BTNMATRIX_CTRL_DISABLED);
|
||||
|
||||
lv_obj_add_event_cb(game_2048->btnm, game_play_event, LV_EVENT_ALL, obj);
|
||||
lv_obj_add_event_cb(game_2048->btnm, btnm_event_cb, LV_EVENT_DRAW_TASK_ADDED, NULL);
|
||||
lv_obj_add_event_cb(obj, delete_event, LV_EVENT_DELETE, NULL);
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Start a new game (reset state)
|
||||
*/
|
||||
void twoeleven_set_new_game(lv_obj_t * obj)
|
||||
{
|
||||
twoeleven_t * game_2048 = (twoeleven_t *)lv_obj_get_user_data(obj);
|
||||
if (!game_2048) return;
|
||||
game_2048->score = 0;
|
||||
game_2048->game_over = false;
|
||||
game_2048->map_count = game_2048->matrix_size * game_2048->matrix_size + game_2048->matrix_size;
|
||||
init_matrix_num(game_2048->matrix_size, game_2048->matrix);
|
||||
update_btnm_map(game_2048->matrix_size, game_2048->btnm_map, (const uint16_t **)game_2048->matrix);
|
||||
lv_btnmatrix_set_map(game_2048->btnm, (const char **)game_2048->btnm_map);
|
||||
lv_obj_invalidate(game_2048->btnm);
|
||||
lv_obj_send_event(obj, LV_EVENT_VALUE_CHANGED, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Event callback for game play (gesture/key)
|
||||
*/
|
||||
static void game_play_event(lv_event_t * e)
|
||||
{
|
||||
lv_event_code_t code = lv_event_get_code(e);
|
||||
lv_obj_t * obj = lv_event_get_user_data(e);
|
||||
twoeleven_t * game_2048 = (twoeleven_t *)lv_obj_get_user_data(obj);
|
||||
bool success = false;
|
||||
if (!game_2048) return;
|
||||
|
||||
if (code == LV_EVENT_GESTURE) {
|
||||
game_2048->game_over = game_over(game_2048->matrix_size, (const uint16_t **)game_2048->matrix);
|
||||
if (!game_2048->game_over) {
|
||||
lv_dir_t dir = lv_indev_get_gesture_dir(lv_indev_active());
|
||||
switch (dir) {
|
||||
case LV_DIR_TOP:
|
||||
success = move_left(&(game_2048->score), game_2048->matrix_size, game_2048->matrix);
|
||||
break;
|
||||
case LV_DIR_BOTTOM:
|
||||
success = move_right(&(game_2048->score), game_2048->matrix_size, game_2048->matrix);
|
||||
break;
|
||||
case LV_DIR_LEFT:
|
||||
success = move_up(&(game_2048->score), game_2048->matrix_size, game_2048->matrix);
|
||||
break;
|
||||
case LV_DIR_RIGHT:
|
||||
success = move_down(&(game_2048->score), game_2048->matrix_size, game_2048->matrix);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
lv_obj_send_event(obj, LV_EVENT_VALUE_CHANGED, NULL);
|
||||
return;
|
||||
}
|
||||
} else if (code == LV_EVENT_KEY) {
|
||||
game_2048->game_over = game_over(game_2048->matrix_size, (const uint16_t **)game_2048->matrix);
|
||||
if (!game_2048->game_over) {
|
||||
switch (*((const uint8_t *) lv_event_get_param(e))) {
|
||||
case LV_KEY_UP:
|
||||
success = move_left(&(game_2048->score), game_2048->matrix_size, game_2048->matrix);
|
||||
break;
|
||||
case LV_KEY_DOWN:
|
||||
success = move_right(&(game_2048->score), game_2048->matrix_size, game_2048->matrix);
|
||||
break;
|
||||
case LV_KEY_LEFT:
|
||||
success = move_up(&(game_2048->score), game_2048->matrix_size, game_2048->matrix);
|
||||
break;
|
||||
case LV_KEY_RIGHT:
|
||||
success = move_down(&(game_2048->score), game_2048->matrix_size, game_2048->matrix);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
lv_obj_send_event(obj, LV_EVENT_VALUE_CHANGED, NULL);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (success) {
|
||||
add_random(game_2048->matrix_size, game_2048->matrix);
|
||||
update_btnm_map(game_2048->matrix_size, game_2048->btnm_map, (const uint16_t **)game_2048->matrix);
|
||||
lv_btnmatrix_set_map(game_2048->btnm, (const char **)game_2048->btnm_map);
|
||||
lv_obj_invalidate(game_2048->btnm);
|
||||
lv_obj_send_event(obj, LV_EVENT_VALUE_CHANGED, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Event callback for button matrix drawing (coloring tiles)
|
||||
*/
|
||||
static void btnm_event_cb(lv_event_t * e)
|
||||
{
|
||||
lv_obj_t * btnm = lv_event_get_target_obj(e);
|
||||
lv_obj_t * parent = lv_obj_get_parent(btnm);
|
||||
twoeleven_t * game_2048 = (twoeleven_t *)lv_obj_get_user_data(parent);
|
||||
if (!game_2048) return;
|
||||
|
||||
lv_draw_task_t * draw_task = lv_event_get_draw_task(e);
|
||||
lv_draw_dsc_base_t * base_dsc = lv_draw_task_get_draw_dsc(draw_task);
|
||||
|
||||
if (base_dsc->part == LV_PART_ITEMS) {
|
||||
lv_draw_label_dsc_t * label_draw_dsc = lv_draw_task_get_label_dsc(draw_task);
|
||||
lv_draw_fill_dsc_t * fill_draw_dsc = lv_draw_task_get_fill_dsc(draw_task);
|
||||
|
||||
if ((int32_t)base_dsc->id1 >= 0) {
|
||||
uint16_t x = (uint16_t)((base_dsc->id1) / game_2048->matrix_size);
|
||||
uint16_t y = (uint16_t)((base_dsc->id1) % game_2048->matrix_size);
|
||||
uint16_t num = (uint16_t)(1 << (game_2048->matrix[x][y]));
|
||||
|
||||
if (fill_draw_dsc) {
|
||||
fill_draw_dsc->radius = 3;
|
||||
fill_draw_dsc->color = get_num_color(num);
|
||||
}
|
||||
if (label_draw_dsc) {
|
||||
label_draw_dsc->color = (num < 8) ? ELEVENTWO_TEXT_BLACK_COLOR : ELEVENTWO_TEXT_WHITE_COLOR;
|
||||
}
|
||||
} else {
|
||||
if (fill_draw_dsc) fill_draw_dsc->radius = 5;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
#ifndef TWOELEVEN_UI_H
|
||||
#define TWOELEVEN_UI_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "TwoElevenHelpers.h"
|
||||
#include "lvgl.h"
|
||||
|
||||
/***********************
|
||||
* FUNCTION PROTOTYPES
|
||||
**********************/
|
||||
/**
|
||||
* @brief Create a new 2048 game object
|
||||
* @param parent Parent LVGL object
|
||||
* @param matrix_size Size of the game matrix (3 to 6, defaults to 4 if out of range)
|
||||
* @return Pointer to the created LVGL object
|
||||
*/
|
||||
lv_obj_t * twoeleven_create(lv_obj_t * parent, uint16_t matrix_size);
|
||||
|
||||
/**
|
||||
* @brief Start a new game (reset state)
|
||||
* @param obj 2048 game LVGL object
|
||||
*/
|
||||
void twoeleven_set_new_game(lv_obj_t * obj);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /*TWOELEVEN_UI_H*/
|
||||
@@ -0,0 +1,11 @@
|
||||
#include "TwoEleven.h"
|
||||
#include <TactilityCpp/App.h>
|
||||
|
||||
extern "C" {
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
registerApp<TwoEleven>();
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user