#include #include #include "main.h" int scrollPosition = 32; // Start COMPLETELY off-screen right int currentChar = 0; unsigned long lastScrollTime = 0; unsigned long lastCharTime = 0; int textIndex = 0; bool textChanged = false; int lastXOffset = 32; // Track last position for clearing int Left =44; unsigned long currentMillis; // 8x8 pixel retro game characters - OPTIMIZED FOR VISIBILITY uint8_t retro[][8] = { // Pac-Man (open mouth) - MORE DETAILED {0x3C, 0x7E, 0xE7, 0xC3, 0xC3, 0xE7, 0x7E, 0x3C}, // Pac-Man (closed mouth) {0x3C, 0x7E, 0xFF, 0xFF, 0xFF, 0xFF, 0x7E, 0x3C}, // Blinky Ghost (red) {0x3C, 0x7E, 0xFF, 0xFF, 0xFF, 0xFF, 0x5A, 0x7E}, // Pinky Ghost {0x3C, 0x7E, 0xFF, 0xFF, 0xFF, 0xFF, 0x7E, 0x3C}, // Space Invader 1 {0x18, 0x3C, 0x7E, 0xDB, 0xFF, 0x24, 0x5A, 0x42}, // Space Invader 2 {0x18, 0x3C, 0x7E, 0xDB, 0xBD, 0x24, 0x5A, 0x42}, // Mario - BETTER DETAIL {0x18, 0x3C, 0x7E, 0xDB, 0x7E, 0x3C, 0x5A, 0x7E}, // Luigi {0x18, 0x3C, 0x7E, 0xDB, 0x7E, 0x3C, 0x7E, 0x5A}, // Donkey Kong {0x18, 0x3C, 0x7E, 0xFF, 0xFF, 0x7E, 0x3C, 0x18}, // Barrel {0x3C, 0x42, 0x81, 0x81, 0x81, 0x81, 0x42, 0x3C}, // Tetris L-block {0x40, 0x40, 0x40, 0x40, 0x7C, 0x7C, 0x7C, 0x7C}, // Tetris Square {0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C}, // Galaga Ship {0x18, 0x3C, 0x7E, 0xFF, 0x7E, 0x3C, 0x18, 0x00}, // Galaga Enemy {0x24, 0x5A, 0xBD, 0xDB, 0xDB, 0xBD, 0x5A, 0x24}, // Frogger {0x18, 0x3C, 0x5A, 0xFF, 0xFF, 0x7E, 0x3C, 0x18}, // Dig Dug {0x18, 0x3C, 0x7E, 0xFF, 0xFF, 0x7E, 0x3C, 0x18}, // Q*bert {0x81, 0x42, 0x24, 0x18, 0x18, 0x24, 0x42, 0x81}, // Centipede {0x66, 0xFF, 0xFF, 0xFF, 0x7E, 0x3C, 0x18, 0x00}, // Missile Command Base {0x18, 0x3C, 0x7E, 0xFF, 0xFF, 0x7E, 0x3C, 0x18}, // Asteroids Ship {0x18, 0x3C, 0x66, 0xFF, 0xFF, 0x66, 0x3C, 0x18}, // Defender Ship {0x18, 0x3C, 0x7E, 0xFF, 0xFF, 0x7E, 0x3C, 0x18}, // Robotron 2084 {0x3C, 0x42, 0x99, 0xA5, 0xA5, 0x99, 0x42, 0x3C}, // Burger Time Chef {0x3C, 0x42, 0x81, 0x99, 0x99, 0x81, 0x42, 0x3C}, // Bubble Bobble Dragon {0x3C, 0x42, 0x81, 0x81, 0x81, 0x81, 0x42, 0x3C}, // Bomberman {0x3C, 0x42, 0x99, 0xBD, 0xBD, 0x99, 0x42, 0x3C}, // Arkanoid Paddle {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, // Pong Paddle {0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80}, // Tetris T-block {0x00, 0x10, 0x38, 0x7C, 0x10, 0x10, 0x10, 0x00}, // Zelda Triforce {0x18, 0x3C, 0x7E, 0xFF, 0x18, 0x3C, 0x18, 0x00}, // Metroid Samus {0x18, 0x3C, 0x7E, 0xFF, 0xFF, 0x7E, 0x3C, 0x18}, // Castlevania {0x00, 0x18, 0x3C, 0x7E, 0x3C, 0x18, 0x00, 0x00}, // Contra Soldier {0x3C, 0x42, 0x81, 0x81, 0x81, 0x81, 0x42, 0x3C}, // Double Dragon {0x18, 0x3C, 0x7E, 0xFF, 0xFF, 0x7E, 0x3C, 0x18}, // Street Fighter Hadouken {0x00, 0x00, 0x18, 0x3C, 0x3C, 0x18, 0x00, 0x00}, // Sonic {0x3C, 0x42, 0x81, 0x99, 0x81, 0x42, 0x3C, 0x00}, // Megaman {0x18, 0x3C, 0x7E, 0xFF, 0xFF, 0x7E, 0x3C, 0x18}, // Extra Monsters (red/black only) // Dracula (Castlevania style) {0x3C, 0x42, 0xA5, 0x81, 0xA5, 0x99, 0x42, 0x3C}, // Frankenstein Monster {0x7E, 0xDB, 0xFF, 0xFF, 0xE7, 0xE7, 0xDB, 0x7E}, // Demon Face {0x3C, 0x7E, 0xDB, 0xFF, 0xFF, 0xDB, 0x7E, 0x3C}, // Skull {0x3C, 0x7E, 0xDB, 0xFF, 0xFF, 0xDB, 0x7E, 0x3C}, // Bat {0x18, 0x3C, 0x7E, 0xFF, 0x7E, 0x3C, 0x18, 0x00}, // Spider {0x24, 0x5A, 0xBD, 0xFF, 0xFF, 0xBD, 0x5A, 0x24}, // Dragon Head {0x3C, 0x7E, 0xFF, 0xE7, 0xE7, 0xFF, 0x7E, 0x3C}, // Ogre {0x7E, 0xFF, 0xDB, 0xFF, 0xFF, 0xDB, 0xFF, 0x7E}, // Zombie {0x3C, 0x7E, 0xDB, 0xFF, 0xFF, 0xDB, 0x7E, 0x3C}, // Alien (Space Invader boss style) {0x18, 0x3C, 0x7E, 0xDB, 0xFF, 0xDB, 0x7E, 0x3C}, // Classic UFO (flying saucer) {0x00, 0x3C, 0x7E, 0xFF, 0xFF, 0x7E, 0x3C, 0x00}, // Alien Invader (wide arms) {0x18, 0x3C, 0x7E, 0xDB, 0xFF, 0xDB, 0x7E, 0x3C}, // Alien Crab (Space Invaders style) {0x3C, 0x7E, 0xFF, 0x5A, 0x5A, 0xFF, 0x7E, 0x3C}, // Saucer with beam {0x00, 0x3C, 0x7E, 0xFF, 0x7E, 0x3C, 0x18, 0x18}, // Rocket Ship {0x18, 0x3C, 0x7E, 0x18, 0x18, 0x18, 0x18, 0x18}, // Alien Face (big eyes) {0x3C, 0x42, 0xA5, 0x81, 0xA5, 0x99, 0x42, 0x3C}, // UFO with antenna {0x00, 0x3C, 0x7E, 0xFF, 0xFF, 0x7E, 0x5A, 0x24}, // Space Fighter (Galaga style) {0x18, 0x3C, 0x7E, 0xFF, 0x7E, 0x3C, 0x18, 0x00}, // Alien Octopus {0x3C, 0x7E, 0xFF, 0x5A, 0x5A, 0xFF, 0x7E, 0x3C}, // Mothership {0x7E, 0xFF, 0xDB, 0xFF, 0xFF, 0xDB, 0xFF, 0x7E} }; const int TOTAL_CHARS = sizeof(retro) / sizeof(retro[0]); // COMPREHENSIVE RETRO GAME NAMES FOR SCROLLING TEXT const char* gameTexts[] = { "PAC-MAN * MS. PAC-MAN * GALAGA * DONKEY KONG * SPACE INVADERS * ASTEROIDS * DEFENDER */" "CENTIPEDE * FROGGER * DIG DUG * BURGERTIME * QBERT * JOUST * ROBOTRON * TETRIS * /" "ARKANOID * PONG * BREAKOUT * TEMPEST * STAR WARS * TRON * ZAXXON * BUBBLE BOBBLE * /" "GHOSTS N GOBLINS * DOUBLE DRAGON * STREET FIGHTER * FINAL FIGHTER * CONTRA * CASTLEVANIA * /" "METROID * MEGA MAN * SONIC * MARIO BROS * SUPER MARIO * ZELDA * PUNCH OUT * OUTRUN * /" "AFTER BURNER * GYRUSS * TIME PILOT * 1942 * SPY HUNTER * POLE POSITION * OUTLAWS * /" "GAUNTLET * RAMPAGE * ALTERED BEAST * GOLDEN AXE * SHINOBI * STRIDER * /" "TEENAGE MUTANT NINJA TURTLES * SIMPSONS * X-MEN * CAPTAIN COMMANDO * /" "CADILLACS AND DINOSAURS * KING OF FIGHTERS * METAL SLUG * DARKSTALKERS * /" "MARVEL VS CAPCOM * HOUSE OF THE DEAD * TIME CRISIS * VIRTUA FIGHTER * /" "TEKKEN * SOUL CALIBUR * DANCE DANCE REVOLUTION * BEATMANIA /" "POKEMON * KIRBY'S ADVENTURE * EARTHBOUND * CHRONO TRIGGER * FINAL FANTASY /" "QUAKE * DUKE NUKEM * WOLFENSTEIN 3D * " }; void drawCharAtPosition(uint8_t charData[8], int xOffset) { // SIMPLIFIED - Only clear the column that's being left behind int columnToClear = xOffset + 8; // The column RIGHT of the character if (columnToClear >= 0 && columnToClear < Left) { for (int y = 0; y < 8; y++) { mx2.setPoint(y, columnToClear, false); } } // Draw the 8x8 character at current position for (int x = 0; x < 8; x++) { int displayX = x + xOffset; if (displayX >= 0 && displayX < Left) { for (int y = 0; y < 8; y++) { bool pixelOn = (charData[y] >> (7 - x)) & 0x01; mx2.setPoint(y, displayX, pixelOn); } } } } void anime1() { // ===== PANEL 1: GAME NAMES SCROLLING ===== if (parola.displayAnimate()) { parola.displayReset(); textChanged = true; } // Change text occasionally for variety if (textChanged && (currentMillis % (TEXT_CHANGE_MIN * 60000) == 0)) { textIndex = (textIndex + 1) % (sizeof(gameTexts) / sizeof(gameTexts[0])); parola.displayText(gameTexts[textIndex], PA_CENTER, 0, 0, PA_SCROLL_LEFT, PA_SCROLL_LEFT); textChanged = false; // LED effect for text change for (int i = 0; i < 3; i++) { digitalWrite(LED_BUILTIN, HIGH); delay(100); digitalWrite(LED_BUILTIN, LOW); delay(100); } } // ===== PANEL 2: CHARACTER SCROLLING ===== // Update scroll position if (currentMillis - lastScrollTime >= SCROLL_SPEED_MS) { scrollPosition--; lastScrollTime = currentMillis; // Draw character at current position drawCharAtPosition(retro[currentChar], scrollPosition); // Check if character has completely scrolled off screen LEFT side if (scrollPosition <= -OFFSCREEN_BUFFER) { scrollPosition = 32; // Reset to off-screen right currentChar = (currentChar + 1) % TOTAL_CHARS; // Clear the entire display before starting new character mx2.clear(); // LED feedback for character change digitalWrite(LED_BUILTIN, HIGH); delay(10); digitalWrite(LED_BUILTIN, LOW); Serial.print("Character changed to: "); Serial.println(currentChar); } } // Change character automatically every few seconds if (currentMillis - lastCharTime >= CHAR_CHANGE_MS) { currentChar = (currentChar + 1) % TOTAL_CHARS; lastCharTime = currentMillis; scrollPosition = 32; // Restart from off-screen right mx2.clear(); // Clear display for fresh start // Double blink for character change digitalWrite(LED_BUILTIN, HIGH); delay(30); digitalWrite(LED_BUILTIN, LOW); delay(30); digitalWrite(LED_BUILTIN, HIGH); delay(30); digitalWrite(LED_BUILTIN, LOW); Serial.print("Auto character change to: "); Serial.println(currentChar); } }