Min пре 7 година
комит
21f5e05986
1 измењених фајлова са 177 додато и 0 уклоњено
  1. 177 0
      snake.py

+ 177 - 0
snake.py

@@ -0,0 +1,177 @@
+from typing import List
+import pygame
+from random import randint
+
+
+class Pos:
+    def __init__(self, x, y):
+        self.x, self.y = int(x), int(y)
+
+    @classmethod
+    def random(cls):
+        return cls(randint(0, Game.MAP.x - 1), randint(0, Game.MAP.y - 1))
+
+    def copy(self):
+        return Pos(self.x, self.y)
+
+    def __eq__(self, other):
+        return self.x == other.x and self.y == other.y
+
+
+class Colours:
+    BACKGROUND = (0, 0, 0)
+    FOREGROUND = (255, 0, 0)
+    SNAKE = (0, 255, 0)
+    FOOD = (0, 0, 255)
+
+
+class Game:
+    MAP = Pos(20, 20)
+    CUBE = 20
+    FPS = 60
+    SPEED = 120
+    DEBUG = False
+
+    def __init__(self):
+        start_pos = Pos(self.MAP.x / 2, self.MAP.y / 2)
+        self.snake = Snake(start_pos)
+        self.dead = False
+        self.running = True
+        self.score = 0
+
+        self.screen = pygame.display.set_mode((self.MAP.y * self.CUBE, self.MAP.x * self.CUBE))
+        self.clock = pygame.time.Clock()
+        self.timer = 0.0
+        self.font = pygame.font.SysFont('Arial', 20, True, False)
+
+    def proc_events(self, e):
+        if e.type == pygame.QUIT:
+            self.running = False
+        if e.type != pygame.KEYDOWN:
+            return
+
+        if e.key == pygame.K_SPACE and self.dead:
+            start_pos = Pos(self.MAP.x / 2, self.MAP.y / 2)
+            self.snake = Snake(start_pos)
+            self.dead = False
+
+        if e.key == pygame.K_UP:
+            if self.snake.dir != 1:
+                self.snake.dir_next = 0
+
+        elif e.key == pygame.K_DOWN:
+            if self.snake.dir != 0:
+                self.snake.dir_next = 1
+
+        elif e.key == pygame.K_LEFT:
+            if self.snake.dir != 3:
+                self.snake.dir_next = 2
+
+        elif e.key == pygame.K_RIGHT:
+            if self.snake.dir != 2:
+                self.snake.dir_next = 3
+
+        elif e.key == pygame.K_d:
+            self.DEBUG = not self.DEBUG
+
+        elif e.key == pygame.K_ESCAPE:
+            self.running = False
+
+    def loop(self):
+        for event in pygame.event.get():
+            self.proc_events(event)
+
+        if self.dead:
+            text = self.font.render(f"SCORE: {self.score}", True, Colours.FOREGROUND)
+            self.screen.blit(text, (self.MAP.x * self.CUBE / 2, self.MAP.y * self.CUBE / 2))
+            pygame.display.flip()
+            self.clock.tick(30)
+            return
+
+        if 0 > self.snake.head.x or self.snake.head.x >= self.MAP.x or \
+            0 > self.snake.head.y or self.snake.head.y >= self.MAP.y:
+            self.dead = True
+
+        self.screen.fill(Colours.BACKGROUND)
+        pygame.draw.rect(
+            self.screen, Colours.FOOD,
+            (self.snake.food.y * self.CUBE, self.snake.food.x * self.CUBE, self.CUBE - 1, self.CUBE - 1), 0)
+
+        for c in self.snake.body:
+            pygame.draw.rect(
+                self.screen, Colours.SNAKE,
+                (c.y * self.CUBE, c.x * self.CUBE, self.CUBE - 1, self.CUBE - 1), 0)
+
+        self.timer += self.clock.get_time()
+        if self.timer >= self.SPEED:
+            self.timer = 0.0
+            if self.snake.dir_next == 0:
+                self.snake.head.x -= 1
+            elif self.snake.dir_next == 1:
+                self.snake.head.x += 1
+            elif self.snake.dir_next == 2:
+                self.snake.head.y -= 1
+            else:
+                self.snake.head.y += 1
+            self.snake.dir = self.snake.dir_next
+
+            if self.snake.collide(self.snake.head):
+                self.dead = True
+
+            if self.snake.head == self.snake.food:
+                self.snake.add_food()
+                self.snake.size += 1
+                self.score += 1
+
+            self.snake.move()
+
+        if self.DEBUG:
+            text1 = self.font.render(
+                f"X: {self.snake.head.x:02d} Y: {self.snake.head.y:02d} "
+                f"S: {self.snake.size} FPS: {self.clock.get_fps():.1f}",
+                True, Colours.FOREGROUND)
+            text2 = self.font.render(
+                f"F X: {self.snake.food.x:02d} Y: {self.snake.food.y:02d} S: {self.score}",
+                True, Colours.FOREGROUND)
+            self.screen.blit(text1, (10, 10))
+            self.screen.blit(text2, (10, 32))
+
+        pygame.display.flip()
+        self.clock.tick(60)
+
+
+class Snake:
+    def __init__(self, start: Pos, size=3, dir=0):
+        self.size: int = size
+        self.head: Pos = start
+        self.body: List[Pos] = [start.copy()]
+        self.dir: int = dir  # Direction 0=N, 1=S, 2=W, 3=E
+        self.dir_next: int = dir  # Next direction
+        self.food: Pos = None
+        self.add_food()
+
+    def add_food(self):
+        self.food = Pos.random()
+        while self.collide(self.food):
+            self.food = Pos.random()
+
+    def collide(self, pos: Pos) -> bool:
+        for l in self.body:
+            if pos == l:
+                return True
+        return False
+
+    def move(self):
+        self.body.append(self.head.copy())
+        if len(self.body) > self.size:
+            self.body.pop(0)
+
+
+if __name__ == '__main__':
+    pygame.init()
+    pygame.display.set_caption("Snake")
+    game = Game()
+    game.DEBUG = True
+    while game.running:
+        game.loop()
+    pygame.quit()