Help with a Maze Game

Hello,

I'm trying to create a simple maze game using the Adafruit 1.8" Color TFT Shield w/microSD and Joystick - v 2. Adafruit 1.8 Color TFT Shield w/microSD and Joystick [v 2] : ID 802 : $34.95 : Adafruit Industries, Unique & fun DIY electronics and kits

I created the maze walls using a coordinate system that passes variables x1, x2, y1 and y2 so the program can check with if statements to allow the user to move in a certain direction or not.

Fist Issue
The player pixel is supposed to start inside the maze but gets kicked out next to the starting point.

Second issue
The player can't enter the maze.

Third issue
Without the top, right, left and bottom walls only DOWN and UP buttons work. Down moves the player off screen even with 3 - 4 moves than back on the screen with UP however many moves are needed.
With the walls the DOWN button moves the player to the left.

#include <Adafruit_GFX.h>    // Core graphics library
#include <Adafruit_ST7735.h> // Hardware-specific library for ST7735
#include <Adafruit_ST7789.h> // Hardware-specific library for ST7789
#include <SPI.h>
#include <SD.h>
#include <Adafruit_seesaw.h>
#include <Adafruit_TFTShield18.h>

Adafruit_TFTShield18 ss;

#define SD_CS    4  // Chip select line for SD card on Shield
#define TFT_CS  10  // Chip select line for TFT display on Shield
#define TFT_DC   8  // Data/command line for TFT on Shield
#define TFT_RST  9  // Reset line for TFT is handled by seesaw!-1

Adafruit_ST7735 tft = Adafruit_ST7735(TFT_CS, TFT_DC, TFT_RST);

int x = 16; 
int y = 73; 

// Wall coordinates
const int WALL_COORDS[][4] = {
//  <->   up   <->   down
//  0     0     0     0
  {0, 0, 127, 0},     // top
  {127, 0, 127, 159}, // right
  {0, 159, 127, 159}, // bottom
  {0, 0, 0, 159},     // left
  // Draw the walls of the maze
  //Horizontal
  {9, 24, 121, 24},
  {23, 38, 65, 38},
  {65, 52, 107, 52},
  {9, 66, 37, 66},
  {51, 66, 93, 66},
  {23, 80, 65, 80},
  {93, 80, 107, 80},
  {9, 108, 37, 108},
  {9, 108, 37, 108},
  {37, 94, 51, 94},
  {65, 108, 79, 108},
  {93, 108, 107, 108},
  {23, 122, 65, 122},
  {79, 122, 93, 122},
  {9, 136, 121, 136},
  //Vertical
  {9, 24, 9, 66},
  {93, 24, 93, 38},
  {121, 24, 121, 122},
  {23, 38, 23, 52},
  {51, 38, 51, 66},
  {79, 38, 79, 52},
  {107, 38, 107, 94},
  {37, 52, 37, 66},
  {23, 66, 23, 94},
  {79, 66, 79, 122},
  {9, 80, 9, 136},
  {65, 80, 65, 108},
  {93, 80, 93, 108},
  {37, 94, 37, 108},
  {51, 94, 51, 122},
  {107, 108, 107, 136}
};

void setup(void) {
  Serial.begin(9600);
  while (!Serial);
  
  // start by disabling both SD and TFT
  pinMode(TFT_CS, OUTPUT);
  digitalWrite(TFT_CS, HIGH);
  pinMode(SD_CS, OUTPUT);
  digitalWrite(SD_CS, HIGH);

  // Start seesaw helper chip
  if (!ss.begin()){
    Serial.println("seesaw could not be initialized!");
    while(1);
  }

  // Start set the backlight off
  ss.setBacklight(TFTSHIELD_BACKLIGHT_OFF);
  // Reset the TFT
  ss.tftReset();

  // Use this initializer if using a 1.8" TFT screen:
  tft.initR(INITR_BLACKTAB);      // Init ST7735S chip, black tab
  tft.fillScreen(ST77XX_CYAN);

  for (int32_t i=TFTSHIELD_BACKLIGHT_OFF; i<TFTSHIELD_BACKLIGHT_ON; i+=100) {
    ss.setBacklight(i);
    delay(1);
  }

  uint16_t time = millis();
  tft.fillScreen(ST77XX_BLUE);
  time = millis() - time;

  // Draw Maze
  mazeWalls(ST77XX_YELLOW);
  delay(500);
}

void loop() {
  uint32_t buttons = ss.readButtons();

  // a single pixel
  tft.drawPixel(x, y, ST77XX_RED);

  // Check if the user's next move will intersect with a wall
  bool canMove = true;
  int nextX = x, nextY = y;
  if (buttons & TFTSHIELD_BUTTON_DOWN) {
    nextX -= 14;
    if (nextX < 0 || nextX > 127) { // out of bounds
      canMove = false;
    } else {
      // Check if the next move intersects with a wall
      for (int i = 0; i < sizeof(WALL_COORDS) / sizeof(WALL_COORDS[0]); i++) {
        int x1 = WALL_COORDS[i][0];
        int y1 = WALL_COORDS[i][1];
        int x2 = WALL_COORDS[i][2];
        int y2 = WALL_COORDS[i][3];
        if (x1 == x2 && x1 == nextX && y1 <= y && y2 >= y ||
            y1 == y2 && y1 == nextY && x1 <= x && x2 >= x) {
          canMove = false;
          break;
        }
      }
    }
  } else if (buttons & TFTSHIELD_BUTTON_LEFT) {
    nextY -= 14;
    if (nextY < 0 || nextY > 159) { // out of bounds
      canMove = false;
    } else {
      // Check if the next move intersects with a wall
      for (int i = 0; i < sizeof(WALL_COORDS) / sizeof(WALL_COORDS[0]); i++) {
        int x1 = WALL_COORDS[i][0];
        int y1 = WALL_COORDS[i][1];
        int x2 = WALL_COORDS[i][2];
        int y2 = WALL_COORDS[i][3];
        if (x1 == x2 && x1 == nextX && y1 <= y && y2 >= y ||
            y1 == y2 && y1 == nextY && x1 <= x && x2 >= x) {
          canMove = false;
          break;
        }
      }
    }
  }else if (buttons & TFTSHIELD_BUTTON_UP) {
    nextX += 14;
    if (nextX < 0 || nextX > 127) { // out of bounds
      canMove = false;
    } else {
      // Check if the next move intersects with a wall
      for (int i = 0; i < sizeof(WALL_COORDS) / sizeof(WALL_COORDS[0]); i++) {
        int x1 = WALL_COORDS[i][0];
        int y1 = WALL_COORDS[i][1];
        int x2 = WALL_COORDS[i][2];
        int y2 = WALL_COORDS[i][3];
        if (x1 == x2 && x1 == nextX && y1 <= y && y2 >= y ||
            y1 == y2 && y1 == nextY && x1 <= x && x2 >= x) {
          canMove = false;
          break;
        }
      }
    }
  }else if (buttons & TFTSHIELD_BUTTON_RIGHT) {
    nextY += 14;
    if (nextY < 0 || nextY > 159) { // out of bounds
      canMove = false;
    } else {
      // Check if the next move intersects with a wall
      for (int i = 0; i < sizeof(WALL_COORDS) / sizeof(WALL_COORDS[0]); i++) {
        int x1 = WALL_COORDS[i][0];
        int y1 = WALL_COORDS[i][1];
        int x2 = WALL_COORDS[i][2];
        int y2 = WALL_COORDS[i][3];
        if (x1 == x2 && x1 == nextX && y1 <= y && y2 >= y ||
            y1 == y2 && y1 == nextY && x1 <= x && x2 >= x) {
          canMove = false;
          break;
        }
      }
    }
  }

  // Move the user if allowed
  if (canMove) {
    tft.drawPixel(x, y, ST77XX_BLUE);
    if (buttons & TFTSHIELD_BUTTON_DOWN) {
      x = nextX;
    } else if (buttons & TFTSHIELD_BUTTON_LEFT) {
      y = nextY;
    } else if (buttons & TFTSHIELD_BUTTON_UP) {
      x = nextX;
    } else if (buttons & TFTSHIELD_BUTTON_RIGHT) {
      y = nextY;
    }
  }
  delay(200);
}

void mazeWalls(uint16_t color) {
  // Draw the walls of the maze
  for (int i = 0; i < sizeof(WALL_COORDS) / sizeof(WALL_COORDS[0]); i++) {
    int x1 = WALL_COORDS[i][0];
    int y1 = WALL_COORDS[i][1];
    int x2 = WALL_COORDS[i][2];
    int y2 = WALL_COORDS[i][3];
    tft.drawLine(x1, y1, x2, y2, color);
  }
}

Let me know if you have any questions or need more info.

Thanks

I don't understand why the player is moving 14 pixels at a time

Hi John, The 1.8" screen is 128x160 pixels I want a square maze over all so I chose the smaller 128 as the reference and did a few calculations till I found 112pixels/8units(maze sections vertical and horizontal) = 14 pixels unit size. Which is the movement right/left/up/down.

Edit for more detail:
The player starts in a center unit then each movement the player is again centered in the next unit.

Hi @satchell78 ,

Welcome to the forum..
Very nice little maze you made..

I simm'd it..

Your maze in a sim..

seems to work pretty good..

have fun.. ~q

2 Likes

Hi qubits-us, That's awesome! Works great in the sim and code is cleaned up.

Thank You

1 Like

This is where the fact that wokwi simulations can work poorly or not at all on an iPad gets frustrating.

Not leaving the beach early, but I do look forward to running it on a real machine.

Nice work both of yous.

a7

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.