2025-04-11 09:40:32 +08:00

596 lines
23 KiB
C

#include "racing.h"
#ifdef ENABLE_GAME_RACING
#define ROAD_HEIGHT 270
#define NPC_CAR_HEIGHT 400
#define NPC_CAR_OFFSET_Y -110
#define NPC_CAR_X_OFFSET -50
#define SPEED_DIVISOR 5000.0
#define SCORE_MULTIPLIER 10
#define MIN_SPEED 0.5
#define INITIAL_SPEED 3.5
#define SPEED_LIMIT_FACTOR 3.5
void ui_event_raceScreen(lv_event_t *e);
lv_obj_t *ui_raceScreen;
void ui_event_roadPanel(lv_event_t *e);
lv_obj_t *ui_roadPanel;
lv_obj_t *ui_roadImage;
lv_obj_t *ui_distanceLabel;
lv_obj_t *ui_speedLabel;
lv_obj_t *ui_carPlayer;
void ui_event_leftButton(lv_event_t *e);
lv_obj_t *ui_leftButton;
lv_obj_t *ui_leftButtonText;
void ui_event_rightButton(lv_event_t *e);
lv_obj_t *ui_rightButton;
lv_obj_t *ui_rightButtonText;
lv_obj_t *ui_carNPC1;
lv_obj_t *ui_carNPC2;
lv_obj_t *ui_carNPC3;
lv_obj_t *ui_racePanel;
lv_obj_t *ui_raceTitle;
lv_obj_t *ui_raceInfo;
lv_obj_t *ui_raceLabel;
lv_obj_t *ui_raceScore;
void ui_event_raceStart(lv_event_t *e);
lv_obj_t *ui_raceStart;
lv_obj_t *ui_raceButtonText;
void ui_event_exitRace(lv_event_t *e);
lv_obj_t *ui_exitRace;
lv_obj_t *ui_exitRaceText;
void ui_event_roadPanel(lv_event_t *e);
bool active;
int highScore, currentScore;
bool isRacing, gameOver;
float speed = 1;
float m = INITIAL_SPEED;
float speedFactor;
float roadProgress = 0.0f;
float npcProgress = 0.0f;
uint64_t counter;
float npcSpeed = INITIAL_SPEED / 1.5;
bool gen = false;
int rd;
typedef struct CarPosition
{
int x;
int y;
} CarP;
const lv_img_dsc_t *carIcons[] = {
&ui_img_car_green_png,
&ui_img_car_red_png,
&ui_img_car_yellow_png,
};
CarP player;
CarP npc1;
CarP npcBuf;
CarP plBuf;
// Function to check if two cars have crashed into each other
bool haveCrashed(CarP car1, CarP car2)
{
// Calculate the absolute differences in x and y coordinates
int dx = LV_ABS(car1.x - car2.x);
int dy = LV_ABS(car1.y - car2.y);
// Check if the differences are less than the minimum required distances
// x 28 y 58
if (dx < 28 && dy < 58)
{
return true; // The cars have crashed
}
else
{
return false; // The cars have not crashed
}
}
void ui_event_raceScreen(lv_event_t *e)
{
lv_event_code_t event_code = lv_event_get_code(e);
lv_obj_t *target = lv_event_get_target(e);
if (event_code == LV_EVENT_SCREEN_LOAD_START)
{
onGameOpened();
active = true;
isRacing = false;
lv_label_set_text(ui_distanceLabel, "0");
lv_label_set_text(ui_speedLabel, "0");
lv_label_set_text(ui_raceButtonText, "Start");
lv_label_set_text(ui_raceLabel, "High Score");
lv_label_set_text_fmt(ui_raceScore, "%dm", highScore);
lv_obj_clear_flag(ui_racePanel, LV_OBJ_FLAG_HIDDEN); /// Flags
lv_obj_add_flag(ui_raceInfo, LV_OBJ_FLAG_HIDDEN); /// Flags
currentScore = 0;
gameOver = false;
counter = 0;
npc1.x = 0;
npc1.y = 0;
player.x = 0;
player.y = 160;
roadProgress = 0.0f;
npcProgress = 0.0f;
npcSpeed = INITIAL_SPEED / 1.5;
gen = true;
}
if (event_code == LV_EVENT_SCREEN_UNLOAD_START)
{
active = false;
isRacing = false;
}
if (event_code == LV_EVENT_SCREEN_UNLOADED)
{
onGameClosed();
}
if (event_code == LV_EVENT_GESTURE && lv_indev_get_gesture_dir(lv_indev_get_act()) == LV_DIR_RIGHT)
{
if (isRacing)
{
ui_event_roadPanel(e);
}
else
{
ui_gameExit();
}
}
}
void ui_event_roadPanel(lv_event_t *e)
{
lv_event_code_t event_code = lv_event_get_code(e);
lv_obj_t *target = lv_event_get_target(e);
if (event_code == LV_EVENT_CLICKED)
{
if (isRacing)
{
isRacing = false;
if (!gameOver)
{
lv_label_set_text(ui_raceButtonText, "Continue");
lv_label_set_text(ui_raceLabel, "Paused");
lv_label_set_text_fmt(ui_raceScore, "%dm", currentScore);
lv_obj_add_flag(ui_raceInfo, LV_OBJ_FLAG_HIDDEN); /// Flags
}
else
{
lv_label_set_text(ui_raceButtonText, "Start");
lv_label_set_text(ui_raceLabel, "Your Score");
lv_label_set_text_fmt(ui_raceScore, "%dm", currentScore);
lv_obj_clear_flag(ui_raceInfo, LV_OBJ_FLAG_HIDDEN); /// Flags
}
lv_obj_clear_flag(ui_racePanel, LV_OBJ_FLAG_HIDDEN); /// Flags
}
}
}
void ui_event_leftButton(lv_event_t *e)
{
lv_event_code_t event_code = lv_event_get_code(e);
lv_obj_t *target = lv_event_get_target(e);
if (event_code == LV_EVENT_PRESSING)
{
player.x--;
if (player.x < -60)
{
player.x = -60;
}
}
}
void ui_event_rightButton(lv_event_t *e)
{
lv_event_code_t event_code = lv_event_get_code(e);
lv_obj_t *target = lv_event_get_target(e);
if (event_code == LV_EVENT_PRESSING)
{
player.x++;
if (player.x > 60)
{
player.x = 60;
}
}
}
void ui_event_raceStart(lv_event_t *e)
{
lv_event_code_t event_code = lv_event_get_code(e);
lv_obj_t *target = lv_event_get_target(e);
if (event_code == LV_EVENT_CLICKED)
{
if (gameOver)
{
counter = 0;
gameOver = false;
npc1.x = 0;
npc1.y = 0;
player.x = 0;
player.y = 160;
npcSpeed = INITIAL_SPEED / 1.5;
roadProgress = 0.0f;
npcProgress = 0.0f;
gen = true;
}
isRacing = true;
lv_obj_add_flag(ui_racePanel, LV_OBJ_FLAG_HIDDEN); /// Flags
}
}
#endif
void ui_event_exitRace(lv_event_t *e)
{
#ifdef ENABLE_GAME_RACING
lv_event_code_t event_code = lv_event_get_code(e);
lv_obj_t *target = lv_event_get_target(e);
if (event_code == LV_EVENT_CLICKED)
{
ui_gameExit();
}
#endif
}
void ui_raceScreen_screen_init(void (*callback)(const char *, const lv_img_dsc_t *, lv_obj_t **))
{
#ifdef ENABLE_GAME_RACING
ui_raceScreen = lv_obj_create(NULL);
lv_obj_clear_flag(ui_raceScreen, LV_OBJ_FLAG_SCROLLABLE); /// Flags
lv_obj_set_style_bg_color(ui_raceScreen, lv_color_hex(0x000000), LV_PART_MAIN | LV_STATE_DEFAULT);
lv_obj_set_style_bg_opa(ui_raceScreen, 255, LV_PART_MAIN | LV_STATE_DEFAULT);
ui_roadPanel = lv_obj_create(ui_raceScreen);
lv_obj_set_width(ui_roadPanel, 150);
lv_obj_set_height(ui_roadPanel, 240);
lv_obj_set_align(ui_roadPanel, LV_ALIGN_CENTER);
lv_obj_clear_flag(ui_roadPanel, LV_OBJ_FLAG_SCROLLABLE); /// Flags
lv_obj_set_style_border_width(ui_roadPanel, 0, LV_PART_MAIN | LV_STATE_DEFAULT);
lv_obj_set_style_pad_left(ui_roadPanel, 0, LV_PART_MAIN | LV_STATE_DEFAULT);
lv_obj_set_style_pad_right(ui_roadPanel, 0, LV_PART_MAIN | LV_STATE_DEFAULT);
lv_obj_set_style_pad_top(ui_roadPanel, 0, LV_PART_MAIN | LV_STATE_DEFAULT);
lv_obj_set_style_pad_bottom(ui_roadPanel, 0, LV_PART_MAIN | LV_STATE_DEFAULT);
ui_roadImage = lv_img_create(ui_roadPanel);
lv_img_set_src(ui_roadImage, &ui_img_road_png);
lv_obj_set_width(ui_roadImage, 150);
lv_obj_set_height(ui_roadImage, 540);
lv_obj_set_align(ui_roadImage, LV_ALIGN_BOTTOM_MID);
lv_obj_add_flag(ui_roadImage, LV_OBJ_FLAG_ADV_HITTEST); /// Flags
lv_obj_clear_flag(ui_roadImage, LV_OBJ_FLAG_SCROLLABLE); /// Flags
ui_distanceLabel = lv_label_create(ui_raceScreen);
lv_obj_set_width(ui_distanceLabel, LV_SIZE_CONTENT); /// 1
lv_obj_set_height(ui_distanceLabel, LV_SIZE_CONTENT); /// 1
lv_obj_set_x(ui_distanceLabel, 30);
lv_obj_set_y(ui_distanceLabel, 51);
lv_label_set_text(ui_distanceLabel, "0");
lv_obj_set_style_radius(ui_distanceLabel, 10, LV_PART_MAIN | LV_STATE_DEFAULT);
lv_obj_set_style_bg_color(ui_distanceLabel, lv_color_hex(0xAC8900), LV_PART_MAIN | LV_STATE_DEFAULT);
lv_obj_set_style_bg_opa(ui_distanceLabel, 100, LV_PART_MAIN | LV_STATE_DEFAULT);
lv_obj_set_style_outline_color(ui_distanceLabel, lv_color_hex(0xAC8900), LV_PART_MAIN | LV_STATE_DEFAULT);
lv_obj_set_style_outline_opa(ui_distanceLabel, 100, LV_PART_MAIN | LV_STATE_DEFAULT);
lv_obj_set_style_outline_width(ui_distanceLabel, 5, LV_PART_MAIN | LV_STATE_DEFAULT);
lv_obj_set_style_outline_pad(ui_distanceLabel, 1, LV_PART_MAIN | LV_STATE_DEFAULT);
ui_speedLabel = lv_label_create(ui_raceScreen);
lv_obj_set_width(ui_speedLabel, LV_SIZE_CONTENT); /// 1
lv_obj_set_height(ui_speedLabel, LV_SIZE_CONTENT); /// 1
lv_obj_set_x(ui_speedLabel, -30);
lv_obj_set_y(ui_speedLabel, 51);
lv_obj_set_align(ui_speedLabel, LV_ALIGN_TOP_RIGHT);
lv_label_set_text(ui_speedLabel, "0");
lv_obj_set_style_radius(ui_speedLabel, 10, LV_PART_MAIN | LV_STATE_DEFAULT);
lv_obj_set_style_bg_color(ui_speedLabel, lv_color_hex(0xAC8900), LV_PART_MAIN | LV_STATE_DEFAULT);
lv_obj_set_style_bg_opa(ui_speedLabel, 100, LV_PART_MAIN | LV_STATE_DEFAULT);
lv_obj_set_style_border_width(ui_speedLabel, 0, LV_PART_MAIN | LV_STATE_DEFAULT);
lv_obj_set_style_outline_color(ui_speedLabel, lv_color_hex(0xAC8900), LV_PART_MAIN | LV_STATE_DEFAULT);
lv_obj_set_style_outline_opa(ui_speedLabel, 100, LV_PART_MAIN | LV_STATE_DEFAULT);
lv_obj_set_style_outline_width(ui_speedLabel, 5, LV_PART_MAIN | LV_STATE_DEFAULT);
lv_obj_set_style_outline_pad(ui_speedLabel, 1, LV_PART_MAIN | LV_STATE_DEFAULT);
ui_carPlayer = lv_img_create(ui_raceScreen);
lv_img_set_src(ui_carPlayer, &ui_img_car_png);
lv_obj_set_width(ui_carPlayer, LV_SIZE_CONTENT); /// 1
lv_obj_set_height(ui_carPlayer, LV_SIZE_CONTENT); /// 1
lv_obj_set_x(ui_carPlayer, 0);
lv_obj_set_y(ui_carPlayer, 160);
lv_obj_set_align(ui_carPlayer, LV_ALIGN_TOP_MID);
lv_obj_add_flag(ui_carPlayer, LV_OBJ_FLAG_ADV_HITTEST); /// Flags
lv_obj_clear_flag(ui_carPlayer, LV_OBJ_FLAG_SCROLLABLE); /// Flags
ui_leftButton = lv_btn_create(ui_raceScreen);
lv_obj_set_width(ui_leftButton, 50);
lv_obj_set_height(ui_leftButton, 100);
lv_obj_set_x(ui_leftButton, -100);
lv_obj_set_y(ui_leftButton, 1);
lv_obj_set_align(ui_leftButton, LV_ALIGN_CENTER);
lv_obj_add_flag(ui_leftButton, LV_OBJ_FLAG_SCROLL_ON_FOCUS); /// Flags
lv_obj_clear_flag(ui_leftButton, LV_OBJ_FLAG_SCROLLABLE); /// Flags
lv_obj_set_style_radius(ui_leftButton, 30, LV_PART_MAIN | LV_STATE_DEFAULT);
lv_obj_set_style_bg_color(ui_leftButton, lv_color_hex(0x665104), LV_PART_MAIN | LV_STATE_DEFAULT);
lv_obj_set_style_bg_opa(ui_leftButton, 150, LV_PART_MAIN | LV_STATE_DEFAULT);
lv_obj_set_style_bg_color(ui_leftButton, lv_color_hex(0x4B9F31), LV_PART_MAIN | LV_STATE_CHECKED);
lv_obj_set_style_bg_opa(ui_leftButton, 150, LV_PART_MAIN | LV_STATE_CHECKED);
lv_obj_set_style_bg_color(ui_leftButton, lv_color_hex(0x4B9F31), LV_PART_MAIN | LV_STATE_PRESSED);
lv_obj_set_style_bg_opa(ui_leftButton, 150, LV_PART_MAIN | LV_STATE_PRESSED);
ui_leftButtonText = lv_label_create(ui_leftButton);
lv_obj_set_width(ui_leftButtonText, LV_SIZE_CONTENT); /// 1
lv_obj_set_height(ui_leftButtonText, LV_SIZE_CONTENT); /// 1
lv_obj_set_align(ui_leftButtonText, LV_ALIGN_CENTER);
lv_label_set_text(ui_leftButtonText, "<");
lv_obj_set_style_text_font(ui_leftButtonText, &lv_font_montserrat_30, LV_PART_MAIN | LV_STATE_DEFAULT);
ui_rightButton = lv_btn_create(ui_raceScreen);
lv_obj_set_width(ui_rightButton, 50);
lv_obj_set_height(ui_rightButton, 100);
lv_obj_set_x(ui_rightButton, 100);
lv_obj_set_y(ui_rightButton, 1);
lv_obj_set_align(ui_rightButton, LV_ALIGN_CENTER);
lv_obj_add_flag(ui_rightButton, LV_OBJ_FLAG_SCROLL_ON_FOCUS); /// Flags
lv_obj_clear_flag(ui_rightButton, LV_OBJ_FLAG_SCROLLABLE); /// Flags
lv_obj_set_style_radius(ui_rightButton, 30, LV_PART_MAIN | LV_STATE_DEFAULT);
lv_obj_set_style_bg_color(ui_rightButton, lv_color_hex(0x665104), LV_PART_MAIN | LV_STATE_DEFAULT);
lv_obj_set_style_bg_opa(ui_rightButton, 150, LV_PART_MAIN | LV_STATE_DEFAULT);
lv_obj_set_style_bg_color(ui_rightButton, lv_color_hex(0x4B9F31), LV_PART_MAIN | LV_STATE_PRESSED);
lv_obj_set_style_bg_opa(ui_rightButton, 150, LV_PART_MAIN | LV_STATE_PRESSED);
ui_rightButtonText = lv_label_create(ui_rightButton);
lv_obj_set_width(ui_rightButtonText, LV_SIZE_CONTENT); /// 1
lv_obj_set_height(ui_rightButtonText, LV_SIZE_CONTENT); /// 1
lv_obj_set_align(ui_rightButtonText, LV_ALIGN_CENTER);
lv_label_set_text(ui_rightButtonText, ">");
lv_obj_set_style_text_font(ui_rightButtonText, &lv_font_montserrat_30, LV_PART_MAIN | LV_STATE_DEFAULT);
ui_carNPC1 = lv_img_create(ui_raceScreen);
lv_img_set_src(ui_carNPC1, &ui_img_car_green_png);
lv_obj_set_width(ui_carNPC1, LV_SIZE_CONTENT); /// 1
lv_obj_set_height(ui_carNPC1, LV_SIZE_CONTENT); /// 1
lv_obj_set_x(ui_carNPC1, 20);
lv_obj_set_y(ui_carNPC1, -1);
lv_obj_set_align(ui_carNPC1, LV_ALIGN_TOP_MID);
lv_obj_add_flag(ui_carNPC1, LV_OBJ_FLAG_ADV_HITTEST); /// Flags
lv_obj_clear_flag(ui_carNPC1, LV_OBJ_FLAG_SCROLLABLE); /// Flags
ui_carNPC2 = lv_img_create(ui_raceScreen);
lv_img_set_src(ui_carNPC2, &ui_img_car_red_png);
lv_obj_set_width(ui_carNPC2, LV_SIZE_CONTENT); /// 1
lv_obj_set_height(ui_carNPC2, LV_SIZE_CONTENT); /// 1
lv_obj_set_x(ui_carNPC2, -21);
lv_obj_set_y(ui_carNPC2, -60);
lv_obj_set_align(ui_carNPC2, LV_ALIGN_TOP_MID);
lv_obj_add_flag(ui_carNPC2, LV_OBJ_FLAG_ADV_HITTEST); /// Flags
lv_obj_clear_flag(ui_carNPC2, LV_OBJ_FLAG_SCROLLABLE); /// Flags
ui_carNPC3 = lv_img_create(ui_raceScreen);
lv_img_set_src(ui_carNPC3, &ui_img_car_yellow_png);
lv_obj_set_width(ui_carNPC3, LV_SIZE_CONTENT); /// 1
lv_obj_set_height(ui_carNPC3, LV_SIZE_CONTENT); /// 1
lv_obj_set_x(ui_carNPC3, -21);
lv_obj_set_y(ui_carNPC3, -60);
lv_obj_set_align(ui_carNPC3, LV_ALIGN_TOP_MID);
lv_obj_add_flag(ui_carNPC3, LV_OBJ_FLAG_ADV_HITTEST); /// Flags
lv_obj_clear_flag(ui_carNPC3, LV_OBJ_FLAG_SCROLLABLE); /// Flags
ui_racePanel = lv_obj_create(ui_raceScreen);
lv_obj_set_width(ui_racePanel, 240);
lv_obj_set_height(ui_racePanel, 240);
lv_obj_set_align(ui_racePanel, LV_ALIGN_CENTER);
lv_obj_set_flex_flow(ui_racePanel, LV_FLEX_FLOW_COLUMN);
lv_obj_set_flex_align(ui_racePanel, LV_FLEX_ALIGN_SPACE_BETWEEN, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER);
lv_obj_add_flag(ui_racePanel, LV_OBJ_FLAG_HIDDEN); /// Flags
lv_obj_clear_flag(ui_racePanel, LV_OBJ_FLAG_SCROLLABLE); /// Flags
lv_obj_set_style_radius(ui_racePanel, 0, LV_PART_MAIN | LV_STATE_DEFAULT);
lv_obj_set_style_bg_color(ui_racePanel, lv_color_hex(0x000000), LV_PART_MAIN | LV_STATE_DEFAULT);
lv_obj_set_style_bg_opa(ui_racePanel, 230, LV_PART_MAIN | LV_STATE_DEFAULT);
lv_obj_set_style_border_color(ui_racePanel, lv_color_hex(0x968100), LV_PART_MAIN | LV_STATE_DEFAULT);
lv_obj_set_style_border_opa(ui_racePanel, 200, LV_PART_MAIN | LV_STATE_DEFAULT);
lv_obj_set_style_border_width(ui_racePanel, 0, LV_PART_MAIN | LV_STATE_DEFAULT);
lv_obj_set_style_pad_left(ui_racePanel, 0, LV_PART_MAIN | LV_STATE_DEFAULT);
lv_obj_set_style_pad_right(ui_racePanel, 0, LV_PART_MAIN | LV_STATE_DEFAULT);
lv_obj_set_style_pad_top(ui_racePanel, 10, LV_PART_MAIN | LV_STATE_DEFAULT);
lv_obj_set_style_pad_bottom(ui_racePanel, 20, LV_PART_MAIN | LV_STATE_DEFAULT);
ui_raceTitle = lv_label_create(ui_racePanel);
lv_obj_set_width(ui_raceTitle, 100);
lv_obj_set_height(ui_raceTitle, LV_SIZE_CONTENT); /// 1
lv_obj_set_align(ui_raceTitle, LV_ALIGN_CENTER);
lv_label_set_text(ui_raceTitle, "Race");
lv_obj_set_style_text_align(ui_raceTitle, LV_TEXT_ALIGN_CENTER, LV_PART_MAIN | LV_STATE_DEFAULT);
lv_obj_set_style_text_font(ui_raceTitle, &lv_font_montserrat_20, LV_PART_MAIN | LV_STATE_DEFAULT);
lv_obj_set_style_border_color(ui_raceTitle, lv_color_hex(0xFFFFFF), LV_PART_MAIN | LV_STATE_DEFAULT);
lv_obj_set_style_border_opa(ui_raceTitle, 255, LV_PART_MAIN | LV_STATE_DEFAULT);
lv_obj_set_style_border_width(ui_raceTitle, 1, LV_PART_MAIN | LV_STATE_DEFAULT);
lv_obj_set_style_border_side(ui_raceTitle, LV_BORDER_SIDE_BOTTOM, LV_PART_MAIN | LV_STATE_DEFAULT);
ui_raceInfo = lv_label_create(ui_racePanel);
lv_obj_set_width(ui_raceInfo, LV_SIZE_CONTENT); /// 1
lv_obj_set_height(ui_raceInfo, LV_SIZE_CONTENT); /// 1
lv_obj_set_align(ui_raceInfo, LV_ALIGN_CENTER);
lv_label_set_text(ui_raceInfo, "Crashed");
lv_obj_add_flag(ui_raceInfo, LV_OBJ_FLAG_HIDDEN); /// Flags
lv_obj_set_style_text_color(ui_raceInfo, lv_color_hex(0xF77272), LV_PART_MAIN | LV_STATE_DEFAULT);
lv_obj_set_style_text_opa(ui_raceInfo, 255, LV_PART_MAIN | LV_STATE_DEFAULT);
lv_obj_set_style_text_font(ui_raceInfo, &lv_font_montserrat_14, LV_PART_MAIN | LV_STATE_DEFAULT);
ui_raceLabel = lv_label_create(ui_racePanel);
lv_obj_set_width(ui_raceLabel, LV_SIZE_CONTENT); /// 1
lv_obj_set_height(ui_raceLabel, LV_SIZE_CONTENT); /// 1
lv_obj_set_align(ui_raceLabel, LV_ALIGN_CENTER);
lv_label_set_text(ui_raceLabel, "Your Score");
lv_obj_set_style_text_font(ui_raceLabel, &lv_font_montserrat_16, LV_PART_MAIN | LV_STATE_DEFAULT);
ui_raceScore = lv_label_create(ui_racePanel);
lv_obj_set_width(ui_raceScore, LV_SIZE_CONTENT); /// 1
lv_obj_set_height(ui_raceScore, LV_SIZE_CONTENT); /// 1
lv_obj_set_align(ui_raceScore, LV_ALIGN_CENTER);
lv_label_set_text(ui_raceScore, "27m");
lv_obj_set_style_text_color(ui_raceScore, lv_color_hex(0x18F80E), LV_PART_MAIN | LV_STATE_DEFAULT);
lv_obj_set_style_text_opa(ui_raceScore, 255, LV_PART_MAIN | LV_STATE_DEFAULT);
lv_obj_set_style_text_font(ui_raceScore, &lv_font_montserrat_20, LV_PART_MAIN | LV_STATE_DEFAULT);
ui_raceStart = lv_btn_create(ui_racePanel);
lv_obj_set_width(ui_raceStart, 100);
lv_obj_set_height(ui_raceStart, 40);
lv_obj_set_align(ui_raceStart, LV_ALIGN_CENTER);
lv_obj_add_flag(ui_raceStart, LV_OBJ_FLAG_SCROLL_ON_FOCUS); /// Flags
lv_obj_clear_flag(ui_raceStart, LV_OBJ_FLAG_SCROLLABLE); /// Flags
lv_obj_set_style_radius(ui_raceStart, 20, LV_PART_MAIN | LV_STATE_DEFAULT);
ui_raceButtonText = lv_label_create(ui_raceStart);
lv_obj_set_width(ui_raceButtonText, LV_SIZE_CONTENT); /// 1
lv_obj_set_height(ui_raceButtonText, LV_SIZE_CONTENT); /// 40
lv_obj_set_align(ui_raceButtonText, LV_ALIGN_CENTER);
lv_label_set_text(ui_raceButtonText, "Start");
ui_exitRace = lv_btn_create(ui_racePanel);
lv_obj_set_width(ui_exitRace, 100);
lv_obj_set_height(ui_exitRace, 40);
lv_obj_set_align(ui_exitRace, LV_ALIGN_CENTER);
lv_obj_add_flag(ui_exitRace, LV_OBJ_FLAG_SCROLL_ON_FOCUS); /// Flags
lv_obj_clear_flag(ui_exitRace, LV_OBJ_FLAG_SCROLLABLE); /// Flags
lv_obj_set_style_radius(ui_exitRace, 20, LV_PART_MAIN | LV_STATE_DEFAULT);
lv_obj_set_style_bg_color(ui_exitRace, lv_color_hex(0xF30000), LV_PART_MAIN | LV_STATE_DEFAULT);
lv_obj_set_style_bg_opa(ui_exitRace, 255, LV_PART_MAIN | LV_STATE_DEFAULT);
ui_exitRaceText = lv_label_create(ui_exitRace);
lv_obj_set_width(ui_exitRaceText, LV_SIZE_CONTENT); /// 1
lv_obj_set_height(ui_exitRaceText, LV_SIZE_CONTENT); /// 40
lv_obj_set_align(ui_exitRaceText, LV_ALIGN_CENTER);
lv_label_set_text(ui_exitRaceText, "Exit");
lv_obj_add_event_cb(ui_roadPanel, ui_event_roadPanel, LV_EVENT_ALL, NULL);
lv_obj_add_event_cb(ui_leftButton, ui_event_leftButton, LV_EVENT_ALL, NULL);
lv_obj_add_event_cb(ui_rightButton, ui_event_rightButton, LV_EVENT_ALL, NULL);
lv_obj_add_event_cb(ui_raceStart, ui_event_raceStart, LV_EVENT_ALL, NULL);
lv_obj_add_event_cb(ui_exitRace, ui_event_exitRace, LV_EVENT_ALL, NULL);
lv_obj_add_event_cb(ui_raceScreen, ui_event_raceScreen, LV_EVENT_ALL, NULL);
callback("Racing", &ui_img_car_png, &ui_raceScreen);
active = false;
#endif
}
void ui_raceScreen_screen_loop()
{
#ifdef ENABLE_GAME_RACING
if (!active)
{
return;
}
if (!ui_raceScreen)
{
return;
}
if (isRacing)
{
if (plBuf.x != player.x)
{
lv_obj_set_x(ui_carPlayer, player.x);
plBuf.x = player.x;
}
if (plBuf.y != player.y)
{
lv_obj_set_y(ui_carPlayer, player.y);
plBuf.y = player.y;
}
// Calculate speed modifier
m = INITIAL_SPEED - (counter / SPEED_DIVISOR);
if (m < MIN_SPEED)
{
m = MIN_SPEED;
}
// Calculate speed factor
speedFactor = INITIAL_SPEED / m;
if (speedFactor > SPEED_LIMIT_FACTOR)
{
speedFactor = SPEED_LIMIT_FACTOR;
}
// Update current score
currentScore = (counter / 100) + ((INITIAL_SPEED - m) * SCORE_MULTIPLIER);
lv_label_set_text_fmt(ui_distanceLabel, "%d", currentScore);
// Update road movement progress
roadProgress += speedFactor;
// Update speed label
lv_label_set_text_fmt(ui_speedLabel, "%d", (int)(speedFactor * 100));
// Move the road image vertically
lv_obj_set_y(ui_roadImage, ((int)roadProgress) % ROAD_HEIGHT);
// NPC car logic
if (((int)npcProgress % NPC_CAR_HEIGHT) > (NPC_CAR_HEIGHT - 10))
{
gen = true; // Flag to generate new NPC car position
}
if (((int)npcProgress % NPC_CAR_HEIGHT) == 0 && gen)
{
npc1.x = (lv_rand(0, 99) % 100) + NPC_CAR_X_OFFSET;
lv_obj_set_x(ui_carNPC1, npc1.x);
lv_img_set_src(ui_carNPC1, carIcons[lv_rand(0, 2) % 3]);
gen = false;
}
// Update NPC car speed
// npcSpeed -= 0.001; // Decrease NPC speed gradually
// if (npcSpeed < MIN_SPEED)
// {
// npcSpeed = MIN_SPEED;
// }
// Update NPC car y-position
npcProgress += MIN_SPEED;
npc1.y = ((int)npcProgress % NPC_CAR_HEIGHT) + NPC_CAR_OFFSET_Y;
if (npcBuf.y != npc1.y)
{
npcBuf.y = npc1.y;
lv_obj_set_y(ui_carNPC1, npc1.y);
}
if (haveCrashed(player, npc1))
{
active = true;
isRacing = false;
gameOver = true;
lv_label_set_text(ui_distanceLabel, "0");
lv_label_set_text(ui_speedLabel, "0");
lv_obj_clear_flag(ui_racePanel, LV_OBJ_FLAG_HIDDEN); /// Flags
lv_label_set_text(ui_raceButtonText, "Start");
lv_label_set_text(ui_raceLabel, "Your Score");
lv_label_set_text_fmt(ui_raceScore, "%dm", currentScore);
lv_obj_clear_flag(ui_raceInfo, LV_OBJ_FLAG_HIDDEN); /// Flags
if (currentScore > highScore)
{
highScore = currentScore;
lv_label_set_text(ui_raceLabel, "New High Score");
}
currentScore = 0;
}
counter++;
}
#endif
}