pymaze
Differences
This shows you the differences between two versions of the page.
| Next revision | Previous revision | ||
| pymaze [2023/11/10 03:52] – created appledog | pymaze [2023/11/10 07:25] (current) – appledog | ||
|---|---|---|---|
| Line 1: | Line 1: | ||
| = PyMaze | = PyMaze | ||
| + | Normally this would be a very simple example of a game, maybe even in Season 1. However, if it is used there only introduce the very simple maze algorithms! | ||
| + | |||
| + | == main.py | ||
| + | < | ||
| + | from Window import Window | ||
| + | from Game import Game | ||
| + | |||
| + | def main(): | ||
| + | window = Window() | ||
| + | window.setLogo(" | ||
| + | window.setCaption(" | ||
| + | window.setSize(800, | ||
| + | window.setFont(" | ||
| + | |||
| + | game = Game(window) | ||
| + | game.start() | ||
| + | |||
| + | if __name__ == " | ||
| + | main() | ||
| + | </ | ||
| + | |||
| + | As you can see from this code, this is going to be a pygame terminal framework game. We're going to use a 2x wide (40 column) font for this for aesthetic purposes. | ||
| + | |||
| + | == Game.py | ||
| + | Standard, but there are some changes to draw(), update() and so forth. Also observe the changes to the game data at the start of the class. | ||
| + | |||
| + | < | ||
| + | import random | ||
| + | import pygame | ||
| + | from Maze import Maze | ||
| + | |||
| + | class Game: | ||
| + | def __init__(self, | ||
| + | self.window = window | ||
| + | self.screen = window.screen | ||
| + | self.font = window.font | ||
| + | self.logo = window.logo | ||
| + | |||
| + | # Game Data | ||
| + | self.FPS = 60 | ||
| + | self.clock = pygame.time.Clock() | ||
| + | |||
| + | self.maze = Maze(19, 14, 30, 30) | ||
| + | self.maze.binary_tree_maze() | ||
| + | self.maze.cwidth = 32 | ||
| + | self.maze.cheight = 32 | ||
| + | |||
| + | self.px = 1 | ||
| + | self.py = 1 | ||
| + | self.tx = random.randint(0, | ||
| + | self.ty = random.randint(0, | ||
| + | |||
| + | |||
| + | def start(self): | ||
| + | while True: | ||
| + | self.checkEvents() | ||
| + | self.update() | ||
| + | self.draw() | ||
| + | self.clock.tick(self.FPS) | ||
| + | |||
| + | def update(self): | ||
| + | if self.px == self.tx and self.py == self.ty: | ||
| + | print(" | ||
| + | self.quit() | ||
| + | |||
| + | def draw(self): | ||
| + | self.screen.fill((0, | ||
| + | self.maze.draw(self.screen) | ||
| + | self.drawText(self.tx, | ||
| + | self.drawText(self.px, | ||
| + | pygame.display.flip() | ||
| + | |||
| + | def checkEvents(self): | ||
| + | for event in pygame.event.get(): | ||
| + | # Window Quit Event | ||
| + | if event.type == pygame.QUIT: | ||
| + | self.quit() | ||
| + | return | ||
| + | |||
| + | # Keyboard Events | ||
| + | if event.type == pygame.KEYDOWN: | ||
| + | if event.key == pygame.K_q: | ||
| + | self.quit() | ||
| + | elif event.key == pygame.K_LEFT: | ||
| + | if not self.maze.get_wall(self.px, | ||
| + | self.px = self.px - 1 | ||
| + | elif event.key == pygame.K_RIGHT: | ||
| + | if not self.maze.get_wall(self.px, | ||
| + | self.px = self.px + 1 | ||
| + | elif event.key == pygame.K_UP: | ||
| + | if not self.maze.get_wall(self.px, | ||
| + | self.py = self.py - 1 | ||
| + | elif event.key == pygame.K_DOWN: | ||
| + | if not self.maze.get_wall(self.px, | ||
| + | self.py = self.py + 1 | ||
| + | |||
| + | def drawText(self, | ||
| + | text_surface = self.font.render(text, | ||
| + | x = self.window.fontwidth * at_x | ||
| + | y = self.window.fontheight * at_y | ||
| + | self.screen.blit(text_surface, | ||
| + | |||
| + | def quit(self): | ||
| + | quit() | ||
| + | exit() | ||
| + | </ | ||
| + | |||
| + | == Window.py | ||
| + | Unchanged. | ||
| + | |||
| + | == Cell.py | ||
| + | < | ||
| + | class Cell: | ||
| + | def __init__(self): | ||
| + | self.north = True | ||
| + | self.east = True | ||
| + | self.west = True | ||
| + | self.south = True | ||
| + | self.wall_color = " | ||
| + | </ | ||
| + | |||
| + | Just a simple class to store the info about walls. | ||
| + | |||
| + | == Maze.py | ||
| + | The work is done here. Note the requirement for class Cell (shown above): | ||
| + | |||
| + | < | ||
| + | import random | ||
| + | import pygame | ||
| + | from Cell import Cell | ||
| + | |||
| + | class Maze: | ||
| + | def __init__(self, | ||
| + | self.width = w | ||
| + | self.height = h | ||
| + | self.cwidth = cw | ||
| + | self.cheight = ch | ||
| + | |||
| + | self.map = [[Cell() for _ in range(w)] for _ in range(h)] | ||
| + | |||
| + | def get_wall(self, | ||
| + | if d == ' | ||
| + | return True | ||
| + | elif d == ' | ||
| + | return True | ||
| + | elif d == ' | ||
| + | return True | ||
| + | elif d == ' | ||
| + | return True | ||
| + | |||
| + | # fail false. | ||
| + | return False | ||
| + | |||
| + | def set_wall(self, | ||
| + | if d == " | ||
| + | self.map[y][x].north = s | ||
| + | if y > 0: | ||
| + | self.map[y-1][x].north = s | ||
| + | |||
| + | elif d == " | ||
| + | self.map[y][x].east = s | ||
| + | if x < self.width: | ||
| + | self.map[y][x+1].west = s | ||
| + | |||
| + | elif d == " | ||
| + | self.map[y][x].west = s | ||
| + | if x > 0: | ||
| + | self.map[y][x-1].east = s | ||
| + | |||
| + | elif d == " | ||
| + | self.map[y][x].south = s | ||
| + | if y < self.width: | ||
| + | self.map[y+1][x].north = s | ||
| + | |||
| + | else: | ||
| + | print(" | ||
| + | quit() | ||
| + | exit() | ||
| + | |||
| + | def draw(self, screen): | ||
| + | line_color = " | ||
| + | |||
| + | for y in range(self.height): | ||
| + | for x in range(self.width): | ||
| + | c = self.map[y][x] | ||
| + | ax = 2 + x * self.cwidth | ||
| + | ay = 2 + y * self.cheight | ||
| + | bx = ax + self.cwidth | ||
| + | by = ay + self.cheight | ||
| + | if c.north: | ||
| + | pygame.draw.line(screen, | ||
| + | if c.south: | ||
| + | pygame.draw.line(screen, | ||
| + | if c.west: | ||
| + | pygame.draw.line(screen, | ||
| + | if c.east: | ||
| + | pygame.draw.line(screen, | ||
| + | |||
| + | |||
| + | def binary_tree_maze(self): | ||
| + | for x in range(self.width): | ||
| + | for y in range(self.height): | ||
| + | if x == self.width - 1 and y == self.height - 1: | ||
| + | continue | ||
| + | elif x == self.width - 1: | ||
| + | self.set_wall(x, | ||
| + | elif y == self.height - 1: | ||
| + | self.set_wall(x, | ||
| + | else: | ||
| + | if random.choice([True, | ||
| + | self.set_wall(x, | ||
| + | else: | ||
| + | self.set_wall(x, | ||
| + | </ | ||
| + | |||
| + | === Binary Tree Maze Algorithm | ||
| + | The binary tree maze algorithm is a simple algorithm for generating mazes. It is often used in computer graphics, game development, | ||
| + | |||
| + | The binary tree maze algorithm works by iteratively deciding whether to create passages to the east or south, resulting in a maze with paths that resemble a binary tree structure. The randomness adds variability to the generated mazes. This algorithm is relatively easy to understand, making it suitable for beginners exploring maze generation algorithms and basic grid-based world generation. | ||
| + | |||
| + | # Iteration over Cells: | ||
| + | ** The code iterates over each cell in the maze, represented by x and y coordinates. | ||
| + | # Corner Cells Handling: | ||
| + | ** The algorithm checks if the current cell is at the bottom-right corner of the maze (x == self.width - 1 and y == self.height - 1). If so, it continues to the next iteration, skipping the cell. This ensures that the bottom-right cell remains open. | ||
| + | ** If the cell is on the rightmost edge but not the bottom-right corner, a passage is opened to the south (self.set_wall(x, | ||
| + | ** If the cell is on the bottom edge but not the bottom-right corner, a passage is opened to the east (self.set_wall(x, | ||
| + | # Inner Cells: | ||
| + | ** For inner cells (not on the right or bottom edge), a decision is made using random.choice([True, | ||
| + | ** If True, a passage is opened to the east (self.set_wall(x, | ||
| + | ** If False, a passage is opened to the south (self.set_wall(x, | ||
pymaze.1699588336.txt.gz · Last modified: 2023/11/10 03:52 by appledog
