Maze Game
Idea:
The idea for my game is to have a player cross a maze in which they will have to avoid a number of enemies. The player will have a limit visibility of the maze (delimited by a circle around the player character). The player will be able, however, to see the position of the enemies (at least that is the idea). It is kind of a PacMan inspired game but with a twist, you could say.
Here is a rough sketch of how the game will look (kind of):
I also very recently came up with the idea to set a theme for the game (I am creating my own sprites so I needed inspiration). Up until now, I have settled for a Harry Potter theme (I have a friend who is obsessed with Harry Potter) because I found these sprites on internet while I was looking for examples and they reminded me of it.
These are the sprites:
The following made me think about the dementors in the series.
Progress:
For this week I decided to focus on creating the maze (more specifically, been able to generate random mazes) and on going through the PGraphics library. I went through the documentation some online tutorials to better understand how to use it.
Note: the fact that I wrote that I decided to focus on these things means that I actually took a long time to understand PGraphics and even more on creating the code to generate the maze.
To create the maze, I decided to create a grid with cells. The program starts at the upper left cell. It checks for neighboring cells and selects a non-visited cell (one the program has not gone through) and removes a wall (line of the grid). Then it moves to that cell and checks for neighbor cells: the process repeats until a path has been formed. Then the program fills in the left out non-visited cells and randomly removes a wall from them to make them look like a maze. The program is recursive so the last position will be that at the beginning of the maze.
The following is a description of my thought process along with the written algorithm (taken from Wikipedia , there are a lot of options to choose from there).
I had a lot of problems writing the code.
At the beginning it was ok. I manage to create a grid and to be able to place in a different color the visited cell.
The problem came when we started to check the neighboring cells. The problem was the edges: sometimes the program will run well and would move to the neighbor cell, however, when the current cell was an edge, sometimes it choose a neighboring cell outside the canvas, so I had to write a case for that.
This is how it would look:
It was also quite hard to figure out how to assign the cells to certain variable (there was a lot of sketching and thinking involved behind that and it took a lot of time to figure out just how to show and remove the walls).
In many cases, what generate was something that did kind of look like a maze but that had no solution.
The problems where almost always associated with logic with what wall I was telling the program to remove. I watched some YouTube videos regarding maze generation to see how they removed the walls (all of them were in other programming languages, but the pseudocode was all I really needed to start fixing this mess).
After much struggling, yesterday I was finally able to generate a maze.
However in the morning, something happened (I think I might have erased something by accident). My code wasn’t working anymore.
After smashing my head against the wall all morning on my birthday because I couldn’t figure what was wrong, Professor Aaron illuminated me by asking with which function the cell was moving. I had accidentally erased the part in which the cell moved to the next to create a new path, and I completely missed it. Perhaps I’ve been staring at this code for so long that my mind was just assuming that it was there, because I swear, the fact that that part of the code was missing just completely went over my head.
I know have a code that works, 7amdullah!
This is the final result (also, yes, I keep switching colors and size because I wasn’t sure about which would look good, but now I decided for the theme of Harry Potter, I settled for this yellow color. Hopefully I won’t change it again).
Code:
Main Tab
int cols, rows; int cellSize = 50; ArrayList<Cell> grid = new ArrayList<Cell>(); Cell currentCell; ArrayList<Cell> stack = new ArrayList<Cell>(); void setup() { size(900, 900); //fullScreen(); cols = floor(width/cellSize); rows = floor(height/cellSize); //create Cell objects and add them to array list for (int j = 0; j < rows; j++) { for (int i = 0; i < cols; i++) { Cell newCell = new Cell(i, j); grid.add(newCell); } } //start the path at grid 0 currentCell = grid.get(0); } void draw() { background(51); //check that the grid displays correctly for (int i = 0; i < grid.size(); i++) { //I made the mistake of writing grid.length() instead of grid.size() grid.get(i).show(); } currentCell.visited = true; currentCell.highlight(); //currentCell.checkAdjacentCells(); // STEP 1 Cell nextCell = currentCell.checkAdjacentCells(); if (nextCell != null) { nextCell.visited = true; // STEP 2 stack.add(currentCell); //STEP 3: remove the walls removeWalls(currentCell, nextCell); // STEP 4 currentCell = nextCell; } //this is what corrected the problem with the null value else if (stack.size() > 0) { currentCell = stack.remove(stack.size()-1); } } void removeWalls(Cell current, Cell next) { int x = current.i - next.i; if (x == 1) { //remove left wall current.walls[3] = false; //remove right wall next.walls[1] = false; } else if (x == -1) { //remove left wall current.walls[1] = false; //remove right wall next.walls[3] = false; } int y = current.j - next.j; if (y == 1) { //remove bottom wall current.walls[0] = false; //remove top wall next.walls[2] = false; } else if (y == -1) { //remove top wall current.walls[2] = false; //remove bottom wall next.walls[0] = false; } }
Cell Object
class Cell { int i, j; //order of the walls is top, right, bottom, left //this will allow us to remove walls in the grid boolean[] walls = {true, true, true, true}; boolean visited = false; Cell(int indexI, int indexJ) { i = indexI; j = indexJ; } int index(int i, int j) { //return 0 for edge cases if (i < 0 || j < 0 || i > cols-1 || j > rows-1) { return 0; } //formula to calculate index (same as the one to calculate pixels) int index = i + j * cols; return index; } Cell checkAdjacentCells() { ArrayList<Cell> adjacentCells = new ArrayList<Cell>(); //get the cells adjacent to the cell the program is currently at Cell top = grid.get(index(i, j-1)); Cell right = grid.get(index(i+1, j)); Cell bottom = grid.get(index(i, j+1)); Cell left = grid.get(index(i-1, j)); if (top != null && !top.visited) { adjacentCells.add(top); } if (right != null && !right.visited) { adjacentCells.add(right); } if (bottom != null && !bottom.visited) { adjacentCells.add(bottom); } if (left != null && !left.visited) { adjacentCells.add(left); } if (adjacentCells.size() > 0) { int r = floor(random(0, adjacentCells.size())); return adjacentCells.get(r); } else { return null; } } void highlight() { int x = i*cellSize; int y = j*cellSize; noStroke(); fill(0, 255, 0); rect(x, y, cellSize, cellSize); } void show() { int x = i*cellSize; int y = j*cellSize; stroke(255); //if the walls are defined if (walls[0]) { line(x, y, x + cellSize, y); } if (walls[1]) { line(x + cellSize, y, x + cellSize, y + cellSize); } if (walls[2]) { line(x + cellSize, y + cellSize, x, y + cellSize); } if (walls[3]) { line(x, y + cellSize, x, y); } //line(x , y , x + cellSize, y); //line(x + cellSize, y , x + cellSize, y + cellSize); //line(x + cellSize, y + cellSize, x , y + cellSize); //line(x , y , x+ cellSize , y); //noFill(); //rect(x, y, cellSize, cellSize); //change color of a cell if it has been visited if (visited) { noStroke(); fill(255, 204, 102, 150); rect(x, y, cellSize, cellSize); } } }