diff options
| -rw-r--r-- | .gitignore | 1 | ||||
| -rw-r--r-- | Game.py | 68 | ||||
| -rw-r--r-- | GameView.py | 56 | ||||
| -rw-r--r-- | Snake.py | 23 | ||||
| -rw-r--r-- | Vec.py | 23 | ||||
| -rwxr-xr-x | main.py | 44 |
6 files changed, 215 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..bee8a64 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +__pycache__ @@ -0,0 +1,68 @@ + +from Snake import Snake +from Vec import Vec2 + +class Walls: + """Contains the walls of a game. + Supports iterating over the walls and checking if there is a wall at a specific coordinate. + Useful as a wrapper to later increase performance of these operations.""" + + _walls = [] + + def __init__(self, walls): + self._walls = walls + + def fromString(wallString): + walls = [] + y = 0 + for line in wallString.split('\n'): + x = 0 + for char in line: + if char == "#": + walls.append(Vec2(x, y)) + x += 1 + y += 1 + return Walls(walls) + + def walls(self): + return self._walls + + def wallAt(self, pos): + return (pos in self._walls) + + def width(self): + return max(self._walls, key=lambda p: p.x).x + 1 + + def height(self): + return max(self._walls, key=lambda p: p.y).y + 1 + + +class Game: + """Class responsible for the main logic of a game. + For a game, this will probably be a singleton.""" + + snake = Snake([Vec2(6, 6), Vec2(6, 7), Vec2(6,8), Vec2(7,8)]) + walls = Walls.fromString("""############### +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# ### # +# # +###############""") + + def width(self): return self.walls.width() + def height(self): return self.walls.height() + + def tick(self): + self.snake.move() + + def isLost(self): + return self.snake.headInTail() or self.walls.wallAt(self.snake.head()) + diff --git a/GameView.py b/GameView.py new file mode 100644 index 0000000..241914c --- /dev/null +++ b/GameView.py @@ -0,0 +1,56 @@ + +from Game import Game +import pygame + +class GameView: + + + game = Game() + + cellWidth = 64 + + _tickTime = 700 + + _previousTick = None + + nextControlDirection = None + + + def isRunning(self): return not self.game.isLost() + + + def width(self): return self.game.width() * self.cellWidth + + + def height(self): return self.game.height() * self.cellWidth + + + def render(self, surface): + + surface.fill("black") + + for cell in self.game.snake.cells: + pygame.draw.rect(surface, "red", pygame.Rect( + cell.x*self.cellWidth, + cell.y*self.cellWidth, + self.cellWidth, + self.cellWidth + )) + + for cell in self.game.walls.walls(): + pygame.draw.rect(surface, "white", pygame.Rect( + cell.x*self.cellWidth, + cell.y*self.cellWidth, + self.cellWidth, + self.cellWidth + )) + + + def update(self, time): + if (self._previousTick == None) or (self._previousTick + self._tickTime <= time): + self._previousTick = time + if self.nextControlDirection != None: + self.game.snake.heading = self.nextControlDirection + self.nextControlDirection = None + self.game.tick() + diff --git a/Snake.py b/Snake.py new file mode 100644 index 0000000..81c3b0b --- /dev/null +++ b/Snake.py @@ -0,0 +1,23 @@ + +import Vec + +class Snake: + + cells = [] + heading = Vec.up + + def __init__(self, cells): + self.cells = cells + + def move(self): + self.cells.pop() + self.cells.insert(0, self.cells[0] + self.heading) + + def headInTail(self): + res = False + for i in range(1, len(self.cells)): + res = res or (self.cells[0] == self.cells[i]) + return res + + def head(self): + return self.cells[0] @@ -0,0 +1,23 @@ + +class Vec2: + + x = 0 + y = 0 + + def __init__(self, x, y): + self.x = x + self.y = y + + def __add__(self, other): + return Vec2(self.x + other.x, self.y + other.y) + + def __eq__(self, other): + return (other != None) and (self.x == other.x) and (self.y == other.y) + + def neg(self): + return Vec2(-self.x, -self.y) + +right = Vec2(1, 0) +up = Vec2(0, -1) +left = Vec2(-1, 0) +down = Vec2(0, 1) @@ -0,0 +1,44 @@ +#!/bin/python + +import pygame +import Vec +from GameView import GameView + + +view = GameView() + +nextControlDirection = None +pygame.init +screen = pygame.display.set_mode((view.width(), view.height())) +clock = pygame.time.Clock() +running = True + +while running: + + for event in pygame.event.get(): + if event.type == pygame.QUIT: + running = False + + keys = pygame.key.get_pressed() + if keys[pygame.K_w] and view.game.snake.heading != Vec.up.neg(): + view.nextControlDirection = Vec.up + elif keys[pygame.K_a] and view.game.snake.heading != Vec.left.neg(): + view.nextControlDirection = Vec.left + elif keys[pygame.K_r] and view.game.snake.heading != Vec.down.neg(): + view.nextControlDirection = Vec.down + elif keys[pygame.K_s] and view.game.snake.heading != Vec.right.neg(): + view.nextControlDirection = Vec.right + + if view.isRunning(): + view.update(pygame.time.get_ticks()) + + # fill the screen with a color to wipe away anything from last frame + screen.fill("purple") + + view.render(screen) + + pygame.display.flip() + + clock.tick(60) # limits FPS to 60 + +pygame.quit() |
