From d1e189722cbd49475c16d51d6dd3d7eef307aabf Mon Sep 17 00:00:00 2001 From: Elwin Date: Wed, 26 Jun 2024 22:15:31 +0200 Subject: brightness control and gameplay bug fix --- puzzle/neo/main.cpp | 199 +++++++++++++++++++++++++++++++++++----------------- 1 file changed, 135 insertions(+), 64 deletions(-) diff --git a/puzzle/neo/main.cpp b/puzzle/neo/main.cpp index f636b55..5958ea5 100644 --- a/puzzle/neo/main.cpp +++ b/puzzle/neo/main.cpp @@ -10,6 +10,7 @@ #define LED_COLOR_OFF 0x000000 // Color of the LEDs in OFF state #define LED_COLOR_RED 0xFF0000 // Red color for UNINIT state #define LED_COLOR_ORANGE 0xFFA500 // Orange color for IDLE state +#define brightness 0.3 // Set brightness Adafruit_NeoTrellis t_array[MATRIX_SIZE / 4][MATRIX_SIZE / 4] = { {Adafruit_NeoTrellis(PB_ADDR_ADA_NEO_1), @@ -32,21 +33,57 @@ bool ledState = false; // Puzzle state pb_global_state_t puzzleState = PB_GS_NOINIT; +/** + * Scales the brightness of a color. + * + * @param color The color to be scaled. + * @param scale The scale factor. + * + * @return The scaled color. + * + * @throws None. + */ +uint32_t scaleBrightness(uint32_t color, float scale) { + uint8_t r = (color >> 16) & 0xFF; + uint8_t g = (color >> 8) & 0xFF; + uint8_t b = color & 0xFF; + + r = uint8_t(r * scale); + g = uint8_t(g * scale); + b = uint8_t(b * scale); + + return (uint32_t(r) << 16) | (uint32_t(g) << 8) | uint32_t(b); +} + +/** + * Toggles the state of adjacent LEDs based on the input coordinates. + * + * @param x The x-coordinate of the LED to toggle. + * @param y The y-coordinate of the LED to toggle. + * + * @throws None + */ void toggleAdjacentLEDs(int x, int y) { - for (int dx = -1; dx <= 1; ++dx) { - for (int dy = -1; dy <= 1; ++dy) { - if (dx == 0 && dy == 0) continue; // Skip the center button itself - int nx = x + dx, ny = y + dy; - if (nx >= 0 && nx < MATRIX_SIZE && ny >= 0 && ny < MATRIX_SIZE) { - neoMatrix[nx][ny] = !neoMatrix[nx][ny]; - trellis.setPixelColor(nx * MATRIX_SIZE + ny, - neoMatrix[nx][ny] ? LED_COLOR_ON - : LED_COLOR_OFF); - } - } - } + for (int dx = -1; dx <= 1; ++dx) { + for (int dy = -1; dy <= 1; ++dy) { + int nx = x + dx, ny = y + dy; + if (nx >= 0 && nx < MATRIX_SIZE && ny >= 0 && ny < MATRIX_SIZE) { + neoMatrix[nx][ny] = !neoMatrix[nx][ny]; // Toggle each adjacent LED + uint32_t color = neoMatrix[nx][ny] ? LED_COLOR_ON : LED_COLOR_OFF; + trellis.setPixelColor(nx * MATRIX_SIZE + ny, scaleBrightness(color, brightness)); + } + } + } } + +/** + * Checks if the NeoPuzzle is solved. + * + * @return true if all LEDs in the NeoPuzzle are off, false otherwise. + * + * @throws None + */ bool isNeoPuzzleSolved() { for (int i = 0; i < MATRIX_SIZE; i++) { for (int j = 0; j < MATRIX_SIZE; j++) { @@ -57,6 +94,15 @@ bool isNeoPuzzleSolved() { return true; } +/** + * Callback function triggered by a Trellis button press event. + * + * @param evt the key event containing information about the button press + * + * @return 0 indicating the success of the callback + * + * @throws None + */ TrellisCallback buttonCallback(keyEvent evt) { int x = evt.bit.NUM / MATRIX_SIZE; int y = evt.bit.NUM % MATRIX_SIZE; @@ -72,6 +118,13 @@ TrellisCallback buttonCallback(keyEvent evt) { return 0; } +/** + * Initializes the serial communication and checks if the NeoTrellis board is initialized successfully. + * If the initialization fails, it sets the module state to PB_GS_NOINIT and prints an error message. + * Finally, it sets the module state to PB_GS_PLAYING. + * + * @throws None + */ void setup() { Serial.begin(115200); while (!Serial) @@ -80,70 +133,88 @@ void setup() { Serial.println("Failed to initialize NeoTrellis"); pb_hook_mod_state_write(PB_GS_NOINIT); } + pb_hook_mod_state_write(PB_GS_PLAYING); } +/** + * Initializes the game field based on the current state of the NeoMatrix. + * + * @return None + * + * @throws None + */ void set_game_field() { - if (gamefield == false) { - // Initialize the matrix with a checkerboard pattern - bool toggle = false; - for (int i = 0; i < MATRIX_SIZE; i++) { - for (int j = 0; j < MATRIX_SIZE; j++) { - neoMatrix[i][j] = toggle; - toggle = !toggle; - trellis.setPixelColor(i * MATRIX_SIZE + j, neoMatrix[i][j] - ? LED_COLOR_ON - : LED_COLOR_OFF); - } - toggle = !toggle; - } - trellis.show(); - - // Register the callback for each key - for (int i = 0; i < MATRIX_SIZE * MATRIX_SIZE; i++) { - trellis.activateKey(i, SEESAW_KEYPAD_EDGE_RISING, true); - trellis.activateKey(i, SEESAW_KEYPAD_EDGE_FALLING, true); - trellis.registerCallback(i, buttonCallback); - } - gamefield = true; - } + if (!gamefield) { + bool toggle = false; + for (int i = 0; i < MATRIX_SIZE; i++) { + for (int j = 0; j < MATRIX_SIZE; j++) { + neoMatrix[i][j] = toggle; + uint32_t color = neoMatrix[i][j] ? LED_COLOR_ON : LED_COLOR_OFF; + trellis.setPixelColor(i * MATRIX_SIZE + j, scaleBrightness(color, brightness)); + toggle = !toggle; + } + toggle = !toggle; + } + trellis.show(); + + for (int i = 0; i < MATRIX_SIZE * MATRIX_SIZE; i++) { + trellis.activateKey(i, SEESAW_KEYPAD_EDGE_RISING, true); + trellis.activateKey(i, SEESAW_KEYPAD_EDGE_FALLING, true); + trellis.registerCallback(i, buttonCallback); + } + gamefield = true; + } } + pb_global_state_t pb_hook_mod_state_read() { return puzzleState; } void pb_hook_mod_state_write(pb_global_state_t state) { puzzleState = state; } +/** + * Function to flash the corners of a matrix with a specified color. + * + * @param color The color value to be used for flashing. + * + * @return None + * + * @throws None + */ void flashCorners(uint32_t color) { - unsigned long currentMillis = millis(); - - if (currentMillis - previousMillis >= interval) { - previousMillis = currentMillis; - ledState = !ledState; - - for (int i = 0; i < MATRIX_SIZE / 4; i++) { - for (int j = 0; j < MATRIX_SIZE / 4; j++) { - int baseIndex = (i * 4 * MATRIX_SIZE) + (j * 4); - if (ledState) { - trellis.setPixelColor(baseIndex, color); // Top-left corner - trellis.setPixelColor(baseIndex + 3, - color); // Top-right corner - trellis.setPixelColor(baseIndex + 3 * MATRIX_SIZE, - color); // Bottom-left corner - trellis.setPixelColor(baseIndex + 3 * MATRIX_SIZE + 3, - color); // Bottom-right corner - } else { - trellis.setPixelColor(baseIndex, LED_COLOR_OFF); - trellis.setPixelColor(baseIndex + 3, LED_COLOR_OFF); - trellis.setPixelColor(baseIndex + 3 * MATRIX_SIZE, - LED_COLOR_OFF); - trellis.setPixelColor(baseIndex + 3 * MATRIX_SIZE + 3, - LED_COLOR_OFF); - } - } - } - trellis.show(); - } + unsigned long currentMillis = millis(); + if (currentMillis - previousMillis >= interval) { + previousMillis = currentMillis; + ledState = !ledState; + color = scaleBrightness(color, brightness); // Scale color brightness + + for (int i = 0; i < MATRIX_SIZE / 4; i++) { + for (int j = 0; j < MATRIX_SIZE / 4; j++) { + int baseIndex = (i * 4 * MATRIX_SIZE) + (j * 4); + if (ledState) { + trellis.setPixelColor(baseIndex, color); + trellis.setPixelColor(baseIndex + 3, color); + trellis.setPixelColor(baseIndex + 3 * MATRIX_SIZE, color); + trellis.setPixelColor(baseIndex + 3 * MATRIX_SIZE + 3, color); + } else { + trellis.setPixelColor(baseIndex, LED_COLOR_OFF); + trellis.setPixelColor(baseIndex + 3, LED_COLOR_OFF); + trellis.setPixelColor(baseIndex + 3 * MATRIX_SIZE, LED_COLOR_OFF); + trellis.setPixelColor(baseIndex + 3 * MATRIX_SIZE + 3, LED_COLOR_OFF); + } + } + } + trellis.show(); + } } +/** + * This function handles the different states of the puzzle game. + * It reads button events and updates the game field accordingly. + * + * @return void + * + * @throws None + */ void loop() { switch (puzzleState) { case PB_GS_PLAYING: -- cgit v1.2.3