diff options
| -rw-r--r-- | Game.py | 128 | ||||
| -rw-r--r-- | GameView.py | 35 | ||||
| -rw-r--r-- | Snake.py | 6 | ||||
| -rwxr-xr-x | main.py | 27 |
4 files changed, 101 insertions, 95 deletions
@@ -15,32 +15,19 @@ from Walls import Walls Static = Union[PressurePlate, Trail, Door] -class Game: - """Class responsible for the main logic of a game. - For a game, this will probably be a singleton.""" - - def __init__(self, levels: list[str]): - self.snake: Optional[Snake] = None +class Level: + + def __init__(self, levelString: str): self.boxes: list[Box] = [] self.statics: list[Static] = [] - self.walls: Walls = Walls.empty() - self.levelIn: Optional['Vec2'] = None - self.level = -1 - self.levels = [] - self.levels = levels - self.nextLevel() - - - def nextLevel(self) -> None: - self.level += 1 - self.walls = Walls.fromString(self.levels[self.level]) - self.snake = None + self.walls = Walls.fromString(levelString) self.statics = [] + self.levelIn: Optional['Vec2'] = None self.boxes = [] y = 0 - for line in self.levels[self.level].split('\n'): + for line in levelString.split('\n'): x = 0 for char in line: if char == "b": @@ -49,7 +36,7 @@ class Game: if self.doorAt(Vec.Vec2(x, y)) == None: self.statics.append(Door(Vec.Vec2(x, y))) elif char == "_": - self.parseSwitchTrail(self.levels[self.level], Vec.Vec2(x, y)) + self.parseSwitchTrail(levelString, Vec.Vec2(x, y)) elif char == "I": self.levelIn = Vec.Vec2(x, y) x += 1 @@ -63,6 +50,15 @@ class Game: self.snake.heading = Vec.up + def doorAt(self, pos: Vec2) -> Optional[Door]: + for static in self.statics: + match static: + case Door(): + if static.pos == pos: + return static + return None + + def parseSwitchTrail(self, levelStr: str, platePos: Vec2) -> None: level = levelStr.split('\n') startSwitch = None @@ -132,45 +128,6 @@ class Game: return True return pos in map(lambda box: box.pos, self.boxes) - def tick(self) -> None: - match self.snake: - case Snake(): - self.snake.move() - - lastSnakeCell = self.snake.cells[0]#[len(self.snake.cells) - 1] - if (lastSnakeCell.x < 0 or lastSnakeCell.x >= self.width()) or (lastSnakeCell.y < 0 or lastSnakeCell.y >= self.height()): - self.nextLevel() - return - - for static in self.statics: - match static: - case PressurePlate(): - if static.isActive() and not self._movableSolidAt(static.pos): - static.deactivate() - elif (not static.isActive()) and self._movableSolidAt(static.pos): - static.activate() - for static in self.statics: - match static: - case Door(): - if static.isOpen() and not static.isActive(): - if not self._movableSolidAt(static.pos): - static.close() - - - def isLost(self) -> bool: - match self.snake: - case Snake(): return self.snake.hasCollided - case _: return False - - - def doorAt(self, pos: Vec2) -> Optional[Door]: - for static in self.statics: - match static: - case Door(): - if static.pos == pos: - return static - return None - def closedDoorAt(self, pos: Vec2) -> bool: res = False @@ -180,6 +137,7 @@ class Game: res = res or (static.pos == pos and not static.isOpen()) return res + def switchAt(self, pos: Vec2) -> Optional[PressurePlate]: for static in self.statics: match static: @@ -204,3 +162,55 @@ class Game: return True else: return False + + def isCompleted(self) -> bool: + snakeHead = self.snake.cells[0] + return (snakeHead.x < 0 or snakeHead.x >= self.width()) or (snakeHead.y < 0 or snakeHead.y >= self.height()) + + + +class Game: + """Class responsible for the main logic of a game. + For a game, this will probably be a singleton.""" + + def __init__(self, levels: list[str]): + self.levelIndex = 0 + self.levels = levels + self.level = Level(self.levels[self.levelIndex]) + + + def nextLevel(self) -> None: + self.levelIndex += 1 + self.level = Level(self.levels[self.levelIndex]) + + def restartLevel(self) -> None: + self.level = Level(self.levels[self.levelIndex]) + + + def tick(self) -> None: + + match self.level.snake: + case Snake(): + self.level.snake.move() + + for static in self.level.statics: + match static: + case PressurePlate(): + if static.isActive() and not self.level._movableSolidAt(static.pos): + static.deactivate() + elif (not static.isActive()) and self.level._movableSolidAt(static.pos): + static.activate() + for static in self.level.statics: + match static: + case Door(): + if static.isOpen() and not static.isActive(): + if not self.level._movableSolidAt(static.pos): + static.close() + + + def isLost(self) -> bool: + match self.level.snake: + case Snake(): return self.level.snake.hasCollided + case _: return False + + diff --git a/GameView.py b/GameView.py index a670d7c..6ec69fe 100644 --- a/GameView.py +++ b/GameView.py @@ -101,25 +101,26 @@ class GameView: def isRunning(self) -> bool: - return not self.game.isLost() + #return not self.game.isLost() + return True def width(self) -> int: - return self.game.width() * self.cellWidth + return self.game.level.width() * self.cellWidth def height(self) -> int: - return self.game.height() * self.cellWidth + return self.game.level.height() * self.cellWidth def render(self, surface: Surface) -> None: surface.fill("black") - for cell in self.game.walls.walls(): + for cell in self.game.level.walls.walls(): self._drawBoxOfColor(surface, "white", cell.x, cell.y) - for static in self.game.statics: + for static in self.game.level.statics: match static: case Door(): if static.isOpen(): @@ -134,14 +135,11 @@ class GameView: else: self._drawBoxOfColor(surface, "purple", static.pos.x, static.pos.y) - for box in self.game.boxes: + for box in self.game.level.boxes: self._drawBoxOfColor(surface, "brown", box.pos.x, box.pos.y) - match self.game.snake: - case None: raise ValueError("snake not found") - case _: - for cell in self.game.snake.cells: - self._drawBoxOfColor(surface, "red", cell.x, cell.y) + for cell in self.game.level.snake.cells: + self._drawBoxOfColor(surface, "red", cell.x, cell.y) def _drawBoxOfColor(self, surface: Surface, color: str, x: int, y: int) -> None: pygame.draw.rect(surface, color, pygame.Rect( @@ -158,21 +156,22 @@ class GameView: match self.nextControlDirection: case None: None case _: - get(self.game.snake).heading = self.nextControlDirection + self.game.level.snake.heading = self.nextControlDirection self.nextControlDirection = None -# match self.game.snake: -# case None: return None -# case _: -# self.game.snake.heading = self.nextControlDirection -# self.nextControlDirection = None self.game.tick() elif not self.timeBased: match self.nextControlDirection: case None: None case _: self._previousTick = time - get(self.game.snake).heading = self.nextControlDirection + self.game.level.snake.heading = self.nextControlDirection self.nextControlDirection = None self.game.tick() + if self.game.level.isCompleted(): + self.game.nextLevel() + + if self.game.isLost(): + self.game.restartLevel() + @@ -6,16 +6,16 @@ import Game class Snake: - def __init__(self, cells: list[Vec2], game: "Game.Game") -> None: + def __init__(self, cells: list[Vec2], level: "Game.Level") -> None: self.heading = Vec.up self.hasCollided = False self.cells = cells - self.game = game + self.level = level def move(self) -> None: nextPos = self.cells[0] + self.heading last = self.cells.pop() - if self.game.enter(nextPos, self.heading): + if self.level.enter(nextPos, self.heading): self.cells.insert(0, nextPos) else: self.cells.append(last) @@ -15,21 +15,18 @@ running = True while running: - match view.game.snake: - case None: raise ValueError("no snake") - case _: - for event in pygame.event.get(): - if event.type == pygame.QUIT: - running = False - elif event.type == pygame.KEYDOWN: - if event.key == pygame.K_w and view.game.snake.heading != Vec.up.neg(): - view.nextControlDirection = Vec.up - elif event.key == pygame.K_a and view.game.snake.heading != Vec.left.neg(): - view.nextControlDirection = Vec.left - elif event.key == pygame.K_r and view.game.snake.heading != Vec.down.neg(): - view.nextControlDirection = Vec.down - elif event.key == pygame.K_s and view.game.snake.heading != Vec.right.neg(): - view.nextControlDirection = Vec.right + for event in pygame.event.get(): + if event.type == pygame.QUIT: + running = False + elif event.type == pygame.KEYDOWN: + if event.key == pygame.K_w and view.game.level.snake.heading != Vec.up.neg(): + view.nextControlDirection = Vec.up + elif event.key == pygame.K_a and view.game.level.snake.heading != Vec.left.neg(): + view.nextControlDirection = Vec.left + elif event.key == pygame.K_r and view.game.level.snake.heading != Vec.down.neg(): + view.nextControlDirection = Vec.down + elif event.key == pygame.K_s and view.game.level.snake.heading != Vec.right.neg(): + view.nextControlDirection = Vec.right if view.isRunning(): view.update(pygame.time.get_ticks()) |
