Update DiceModalGame with a restricted board view and interactive dice challenge
This commit is contained in:
@@ -6,6 +6,8 @@
|
|||||||
#include "input_manager.h"
|
#include "input_manager.h"
|
||||||
#include "MonopolyBoardRenderer.h"
|
#include "MonopolyBoardRenderer.h"
|
||||||
#include "ModalButtonHelper.h"
|
#include "ModalButtonHelper.h"
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
class DiceModalGame : public Game {
|
class DiceModalGame : public Game {
|
||||||
int dice1, dice2;
|
int dice1, dice2;
|
||||||
@@ -14,6 +16,13 @@ class DiceModalGame : public Game {
|
|||||||
int players_count;
|
int players_count;
|
||||||
bool dismissed;
|
bool dismissed;
|
||||||
|
|
||||||
|
int from_pos;
|
||||||
|
int correct_destination;
|
||||||
|
int options[3];
|
||||||
|
bool option_visible[3];
|
||||||
|
int selected_choice;
|
||||||
|
bool show_error;
|
||||||
|
|
||||||
void draw_die(int x, int y, int size, int value) {
|
void draw_die(int x, int y, int size, int value) {
|
||||||
// Die base
|
// Die base
|
||||||
renderer->draw_rounded_rectangle(x, y, size, size, 4, true, false);
|
renderer->draw_rounded_rectangle(x, y, size, size, 4, true, false);
|
||||||
@@ -49,75 +58,139 @@ class DiceModalGame : public Game {
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
DiceModalGame(uint16_t width, uint16_t height, LowLevelRenderer* renderer, LowLevelGUI* gui, InputManager* input_manager, int d1, int d2, const BoardTile* from, const BoardTile* to, Player* p, int count)
|
DiceModalGame(uint16_t width, uint16_t height, LowLevelRenderer* renderer, LowLevelGUI* gui, InputManager* input_manager, int d1, int d2, const BoardTile* from, const BoardTile* to, Player* p, int count)
|
||||||
: Game(width, height, renderer, gui, input_manager), dice1(d1), dice2(d2), from_tile(from), to_tile(to), players(p), players_count(count), dismissed(false) {}
|
: Game(width, height, renderer, gui, input_manager), dice1(d1), dice2(d2), from_tile(from), to_tile(to), players(p), players_count(count), dismissed(false) {
|
||||||
|
|
||||||
|
// Find from_pos
|
||||||
|
from_pos = 0;
|
||||||
|
for(int i=0; i<40; i++) {
|
||||||
|
if(&MONOPOLY_BOARD[i] == from_tile) {
|
||||||
|
from_pos = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
correct_destination = (from_pos + dice1 + dice2) % BOARD_SIZE;
|
||||||
|
selected_choice = -1;
|
||||||
|
show_error = false;
|
||||||
|
for(int i=0; i<3; i++) option_visible[i] = true;
|
||||||
|
|
||||||
|
// Generate fake options
|
||||||
|
int fake1 = (from_pos + (rand() % 11 + 2)) % BOARD_SIZE;
|
||||||
|
if (fake1 == correct_destination) fake1 = (fake1 + 1) % BOARD_SIZE;
|
||||||
|
|
||||||
|
int fake2 = (from_pos + (rand() % 11 + 2)) % BOARD_SIZE;
|
||||||
|
while (fake2 == correct_destination || fake2 == fake1) {
|
||||||
|
fake2 = (from_pos + (rand() % 11 + 2)) % BOARD_SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
int rand_pos = rand() % 3;
|
||||||
|
if (rand_pos == 0) {
|
||||||
|
options[0] = correct_destination;
|
||||||
|
options[1] = fake1;
|
||||||
|
options[2] = fake2;
|
||||||
|
} else if (rand_pos == 1) {
|
||||||
|
options[0] = fake1;
|
||||||
|
options[1] = correct_destination;
|
||||||
|
options[2] = fake2;
|
||||||
|
} else {
|
||||||
|
options[0] = fake1;
|
||||||
|
options[1] = fake2;
|
||||||
|
options[2] = correct_destination;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void init() override {
|
void init() override {
|
||||||
dismissed = false;
|
dismissed = false;
|
||||||
|
selected_choice = -1;
|
||||||
|
show_error = false;
|
||||||
|
for(int i=0; i<3; i++) option_visible[i] = true;
|
||||||
ModalButtonHelper::set_monopoly_regions(input_manager, width, height);
|
ModalButtonHelper::set_monopoly_regions(input_manager, width, height);
|
||||||
}
|
}
|
||||||
Type get_type() const override { return Type::MONOPOLY_DICE; }
|
Type get_type() const override { return Type::MONOPOLY_DICE; }
|
||||||
|
|
||||||
bool update(const InputEvent& event) override {
|
bool update(const InputEvent& event) override {
|
||||||
// Only B dismisses now, so A can still be used for "change action" (even if it does nothing here)
|
if (event.type == INPUT_BUTTON_0) { // Select
|
||||||
|
int start_choice = selected_choice;
|
||||||
|
do {
|
||||||
|
selected_choice = (selected_choice + 1) % 3;
|
||||||
|
} while (!option_visible[selected_choice] && selected_choice != start_choice);
|
||||||
|
|
||||||
|
show_error = false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
if (event.type == INPUT_BUTTON_1) {
|
if (event.type == INPUT_BUTTON_1) {
|
||||||
dismissed = true;
|
if (selected_choice == -1 || !option_visible[selected_choice]) return false;
|
||||||
|
|
||||||
|
if (options[selected_choice] == correct_destination) {
|
||||||
|
dismissed = true;
|
||||||
|
} else {
|
||||||
|
option_visible[selected_choice] = false;
|
||||||
|
show_error = true;
|
||||||
|
selected_choice = -1;
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void draw() override {
|
void draw() override {
|
||||||
renderer->clear_buffer();
|
renderer->clear_buffer();
|
||||||
|
|
||||||
MonopolyBoardRenderer::draw_board_perimeter(renderer, width, height, players, players_count, (to_tile ? -1 /* or some index */ : -1)); // Keep it simple for now or pass relevant pos
|
// Draw the restricted board perimeter
|
||||||
// Let's pass the destination position to highlight it during the dice roll
|
MonopolyBoardRenderer::draw_board_perimeter(renderer, width, height, players, players_count, -1, -1, from_pos, (from_pos + 12) % BOARD_SIZE);
|
||||||
int target_pos = -1;
|
|
||||||
for(int i=0; i<40; i++) if(&MONOPOLY_BOARD[i] == to_tile) target_pos = i;
|
|
||||||
MonopolyBoardRenderer::draw_board_perimeter(renderer, width, height, players, players_count, target_pos);
|
|
||||||
|
|
||||||
// --- Inner UI (Center Area) ---
|
// --- Inner UI (Center Area) ---
|
||||||
int cw = width / 7;
|
int cw = width / 7;
|
||||||
int ch = height / 7;
|
int ch = height / 7;
|
||||||
int ix = cw + 2, iy = ch + 2;
|
int ix = cw + 2;
|
||||||
int iw = width - 2 * cw - 4, ih = height - 2 * ch - 4;
|
int iy = ch + 2;
|
||||||
|
int iw = width - 2 * cw - 4;
|
||||||
|
int ih = height - 2 * ch - 4;
|
||||||
|
|
||||||
// Window background (White box)
|
// Window background (White box)
|
||||||
renderer->draw_filled_rectangle(ix, iy, iw, ih, false, 0); // Clear central area
|
renderer->draw_filled_rectangle(ix, iy, iw, ih, false, 0);
|
||||||
renderer->draw_rectangle(ix, iy, iw, ih, true, 1); // Border
|
renderer->draw_rectangle(ix, iy, iw, ih, true, 2);
|
||||||
|
renderer->draw_rectangle(ix + 3, iy + 3, iw - 6, ih - 6, true, 1);
|
||||||
|
|
||||||
// Header
|
// Header
|
||||||
renderer->draw_filled_rectangle(ix + 2, iy + 2, iw - 4, 30, true, 1);
|
renderer->draw_filled_rectangle(ix + 4, iy + 4, iw - 8, 30, true, 1);
|
||||||
renderer->set_text_color(false);
|
renderer->set_text_color(false);
|
||||||
renderer->draw_string_scaled(ix + (iw - (int)strlen("==DICE ROLL==") * 12) / 2, iy + 10, "==DICE ROLL==", 2);
|
renderer->draw_string_scaled(ix + (iw - (int)strlen("DICE CHALLENGE") * 12) / 2, iy + 10, "DICE CHALLENGE", 2);
|
||||||
renderer->set_text_color(true);
|
renderer->set_text_color(true);
|
||||||
|
|
||||||
// Dice
|
// Dice
|
||||||
int dice_size = 50;
|
int dice_size = 40;
|
||||||
int dice_y = iy + 45;
|
int dice_y = iy + 45;
|
||||||
draw_die(ix + iw / 2 - dice_size - 10, dice_y, dice_size, dice1);
|
draw_die(ix + 20, dice_y, dice_size, dice1);
|
||||||
draw_die(ix + iw / 2 + 10, dice_y, dice_size, dice2);
|
draw_die(ix + 20 + dice_size + 10, dice_y, dice_size, dice2);
|
||||||
|
|
||||||
// Total
|
// --- Prompt ---
|
||||||
char buf[32];
|
int prompt_y = dice_y + dice_size + 10;
|
||||||
snprintf(buf, sizeof(buf), "TOTAL: %d", dice1 + dice2);
|
renderer->draw_string_scaled(ix + 20, prompt_y, "WHERE WILL YOU LAND?", 1);
|
||||||
renderer->draw_string_scaled(ix + (iw - 100) / 2, dice_y + dice_size + 10, buf, 2);
|
|
||||||
|
|
||||||
// Movement info
|
// --- Options ---
|
||||||
int info_y = dice_y + dice_size + 30;
|
int opt_y = prompt_y + 20;
|
||||||
char move_buf[64];
|
for (int i = 0; i < 3; i++) {
|
||||||
if (from_tile && to_tile) {
|
if (!option_visible[i]) {
|
||||||
snprintf(move_buf, sizeof(move_buf), "FROM: %s", from_tile->name);
|
opt_y += 25;
|
||||||
renderer->draw_string_scaled(ix + 10, info_y, move_buf, 2);
|
continue;
|
||||||
info_y += 24;
|
}
|
||||||
snprintf(move_buf, sizeof(move_buf), "TO: %s", to_tile->name);
|
char opt_buf[64];
|
||||||
renderer->draw_string_scaled(ix + 10, info_y, move_buf, 2);
|
snprintf(opt_buf, sizeof(opt_buf), "%s %d: %s", (selected_choice == i ? ">" : " "), i+1, MONOPOLY_BOARD[options[i]].name);
|
||||||
|
|
||||||
|
if (selected_choice == i) renderer->draw_filled_rectangle(ix + 15, opt_y - 2, iw - 30, 22, true, 1);
|
||||||
|
if (selected_choice == i) renderer->set_text_color(false);
|
||||||
|
|
||||||
|
// Truncate name if too long
|
||||||
|
if (strlen(opt_buf) > 30) opt_buf[30] = '\0';
|
||||||
|
renderer->draw_string_scaled(ix + 20, opt_y, opt_buf, 2);
|
||||||
|
renderer->set_text_color(true);
|
||||||
|
opt_y += 25;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Button
|
if (show_error) {
|
||||||
int btn_w = 120, btn_h = 25;
|
renderer->draw_string_scaled(ix + (iw - 10 * 12) / 2, iy + ih - 30, "TRY AGAIN!", 2);
|
||||||
int btn_x = ix + (iw - btn_w) / 2;
|
}
|
||||||
int btn_y = iy + ih - 35;
|
|
||||||
renderer->draw_filled_rectangle(btn_x, btn_y, btn_w, btn_h, true, 1);
|
|
||||||
renderer->set_text_color(false);
|
|
||||||
renderer->draw_string_scaled(btn_x + 5, btn_y + 5, "> CONTINUE", 2);
|
|
||||||
renderer->set_text_color(true);
|
|
||||||
|
|
||||||
ModalButtonHelper::draw_virtual_buttons(renderer, input_manager);
|
ModalButtonHelper::draw_virtual_buttons(renderer, input_manager);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -117,34 +117,43 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void draw_board_perimeter(LowLevelRenderer* renderer, int width, int height, Player* players, int players_count, int currentPlayerPos = -1, int observer_idx = -1) {
|
static void draw_board_perimeter(LowLevelRenderer* renderer, int width, int height, Player* players, int players_count, int currentPlayerPos = -1, int observer_idx = -1, int limit_start = -1, int limit_end = -1) {
|
||||||
int cw = width / 7; // Corner width
|
int cw = width / 7; // Corner width
|
||||||
int ch = height / 7; // Corner height
|
int ch = height / 7; // Corner height
|
||||||
int rw = (width - 2 * cw) / 9; // Regular tile width
|
int rw = (width - 2 * cw) / 9; // Regular tile width
|
||||||
int rh = (height - 2 * ch) / 9; // Regular tile height
|
int rh = (height - 2 * ch) / 9; // Regular tile height
|
||||||
|
|
||||||
|
auto should_draw = [&](int index) {
|
||||||
|
if (limit_start == -1 || limit_end == -1) return true;
|
||||||
|
if (limit_start <= limit_end) {
|
||||||
|
return index >= limit_start && index <= limit_end;
|
||||||
|
} else {
|
||||||
|
return index >= limit_start || index <= limit_end;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// --- Bottom Row: 0 to 10 (Right to Left) ---
|
// --- Bottom Row: 0 to 10 (Right to Left) ---
|
||||||
draw_tile(renderer, width - cw, height - ch, cw, ch, 0, true, players, players_count, 0, currentPlayerPos, observer_idx); // GO
|
if (should_draw(0)) draw_tile(renderer, width - cw, height - ch, cw, ch, 0, true, players, players_count, 0, currentPlayerPos, observer_idx); // GO
|
||||||
for (int i = 1; i < 10; ++i) {
|
for (int i = 1; i < 10; ++i) {
|
||||||
draw_tile(renderer, width - cw - i * rw, height - ch, rw, ch, i, false, players, players_count, 0, currentPlayerPos, observer_idx);
|
if (should_draw(i)) draw_tile(renderer, width - cw - i * rw, height - ch, rw, ch, i, false, players, players_count, 0, currentPlayerPos, observer_idx);
|
||||||
}
|
}
|
||||||
draw_tile(renderer, 0, height - ch, cw, ch, 10, true, players, players_count, 1, currentPlayerPos, observer_idx); // JAIL
|
if (should_draw(10)) draw_tile(renderer, 0, height - ch, cw, ch, 10, true, players, players_count, 1, currentPlayerPos, observer_idx); // JAIL
|
||||||
|
|
||||||
// --- Left Column: 11 to 19 (Bottom to Top) ---
|
// --- Left Column: 11 to 19 (Bottom to Top) ---
|
||||||
for (int i = 11; i < 20; ++i) {
|
for (int i = 11; i < 20; ++i) {
|
||||||
draw_tile(renderer, 0, height - ch - (i - 10) * rh, cw, rh, i, false, players, players_count, 1, currentPlayerPos, observer_idx);
|
if (should_draw(i)) draw_tile(renderer, 0, height - ch - (i - 10) * rh, cw, rh, i, false, players, players_count, 1, currentPlayerPos, observer_idx);
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- Top Row: 20 to 30 (Left to Right) ---
|
// --- Top Row: 20 to 30 (Left to Right) ---
|
||||||
draw_tile(renderer, 0, 0, cw, ch, 20, true, players, players_count, 2, currentPlayerPos, observer_idx); // FREE PARKING
|
if (should_draw(20)) draw_tile(renderer, 0, 0, cw, ch, 20, true, players, players_count, 2, currentPlayerPos, observer_idx); // FREE PARKING
|
||||||
for (int i = 21; i < 30; ++i) {
|
for (int i = 21; i < 30; ++i) {
|
||||||
draw_tile(renderer, cw + (i - 21) * rw, 0, rw, ch, i, false, players, players_count, 2, currentPlayerPos, observer_idx);
|
if (should_draw(i)) draw_tile(renderer, cw + (i - 21) * rw, 0, rw, ch, i, false, players, players_count, 2, currentPlayerPos, observer_idx);
|
||||||
}
|
}
|
||||||
draw_tile(renderer, width - cw, 0, cw, ch, 30, true, players, players_count, 3, currentPlayerPos, observer_idx); // GO TO JAIL
|
if (should_draw(30)) draw_tile(renderer, width - cw, 0, cw, ch, 30, true, players, players_count, 3, currentPlayerPos, observer_idx); // GO TO JAIL
|
||||||
|
|
||||||
// --- Right Column: 31 to 39 (Top to Bottom) ---
|
// --- Right Column: 31 to 39 (Top to Bottom) ---
|
||||||
for (int i = 31; i < 40; ++i) {
|
for (int i = 31; i < 40; ++i) {
|
||||||
draw_tile(renderer, width - cw, ch + (i - 31) * rh, cw, rh, i, false, players, players_count, 3, currentPlayerPos, observer_idx);
|
if (should_draw(i)) draw_tile(renderer, width - cw, ch + (i - 31) * rh, cw, rh, i, false, players, players_count, 3, currentPlayerPos, observer_idx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user