Python Forum
[PyGame] Made my first Python program: Snake. Please help me improve it
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
[PyGame] Made my first Python program: Snake. Please help me improve it
#8
You might get some ideas off of this code.
Still small bug. Push key direction to fast will collide with own body.
import pygame
from random import randint, choice


pygame.init()
SQR_SIZE = 20

# Simple Tick Timer
class Timer:
    ticks = 0

    def __init__(self, interval, callback):
        self.tick = Timer.ticks + interval
        self.interval = interval
        self.callback = callback

    def elapse(self):
        trip = False

        while Timer.ticks > self.tick:
            self.tick += self.interval
            trip = True

        if trip:
            self.callback(self)

# simple interface
class SceneInterface:
    def on_draw(self, surface):
        pass

    def on_event(self, event):
        pass

    def on_quit(self, game):
        game.running = False

    def on_update(self):
        pass

class Game:
    def __init__(self):
        # Basic pygame setup
        pygame.display.set_caption('Snake Example')
        self.rect = pygame.Rect(0, 0, 800, 600)
        self.surface = pygame.display.set_mode(self.rect.size)
        self.clock = pygame.time.Clock()

        # scene basic
        self.flip_scene = None

    def mainloop(self, start_scene):
        self.delta = 0
        self.running = True
        self.scene = start_scene
        while self.running:
            if self.flip_scene:
                self.scene = self.flip_scene
                self.flip_scene = None

            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    self.scene.on_quit(self)
                else:
                    self.scene.on_event(event)

            Timer.ticks = pygame.time.get_ticks()

            self.scene.on_update()
            self.scene.on_draw(self.surface)
            pygame.display.update()
            self.delta = self.clock.tick(60)

class Snake:
    def __init__(self, rect, eats, dies):
        self.head = pygame.Rect(*rect.center, SQR_SIZE, SQR_SIZE)
        self.body = [tuple(self.head.topleft) for x in range(3)]
        self.direction = choice([pygame.K_UP, pygame.K_DOWN, pygame.K_LEFT, pygame.K_RIGHT])
        self.color = pygame.Color('Lawngreen')
        self.timer = Timer(200, self.moving)
        self.bounds = rect.copy()
        self.eaten = eats
        self.dies = dies

    def draw(self, surface):
        for body in self.body:
            rect = pygame.Rect(body[0], body[1], SQR_SIZE, SQR_SIZE)
            surface.fill(self.color, rect)

    def update(self):
        self.timer.elapse()

    def move(self, x, y):
        pos = self.body[0]
        self.head.topleft = pos[0] + x * SQR_SIZE, pos[1] + y * SQR_SIZE
        if self.head.topleft in self.body:
            self.dies()
        elif not self.bounds.contains(self.head):
            self.dies()
        else:
            if self.eaten(self.head.topleft):
                self.body = [self.head.topleft] + self.body
            else:
                self.body = [self.head.topleft] + self.body[:-1]

    def moving(self, timer):
        if self.direction == pygame.K_UP:
            self.move(0, -1)
        elif self.direction == pygame.K_DOWN:
            self.move(0, 1)
        elif self.direction == pygame.K_LEFT:
            self.move(-1, 0)
        elif self.direction == pygame.K_RIGHT:
            self.move(1, 0)

class DeathScene(SceneInterface):
    def __init__(self, game, play):
        font = pygame.font.Font(None, 32)
        self.death = font.render('You Have Died', 1, pygame.Color('Firebrick'))
        self.rect = self.death.get_rect()
        self.rect.center = game.rect.center
        self.play = play
        self.game = game

    def on_draw(self, surface):
        self.play.on_draw(surface)
        surface.blit(self.death, self.rect)

    def on_event(self, event):
        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_SPACE:
                self.play.new_game()
                self.game.flip_scene = self.play
            elif event.key == pygame.K_ESCAPE:
                self.on_quit(self.game)

class PlayScene(SceneInterface):
    def __init__(self, game):
        self.game = game
        self.new_game()
        self.food_image = pygame.Surface((SQR_SIZE, SQR_SIZE))
        self.food_image.fill(pygame.Color('Yellow'))

    def new_game(self):
        self.snake = Snake(self.game.rect, self.snake_eats, self.snake_dies)
        self.create_food()

    def create_food(self):
        g = self.game.rect
        pos = randint(0, g.w / SQR_SIZE - 1), randint(0, g.h / SQR_SIZE - 1)
        while pos in self.snake.body:
            pos = randint(0, g.w / SQR_SIZE), randint(0, g.h / SQR_SIZE)

        self.food = pos[0] * SQR_SIZE, pos[1] * SQR_SIZE

    def snake_eats(self, head):
        if self.food == head:
            self.create_food()
            return True
        return False

    def snake_dies(self):
        self.game.flip_scene = DeathScene(self.game, self)

    def on_draw(self, surface):
        surface.fill(pygame.Color('Black'))
        self.snake.draw(surface)
        surface.blit(self.food_image, self.food)

    def on_update(self):
        self.snake.update()

    def on_event(self, event):
        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_UP:
                if self.snake.direction != pygame.K_DOWN:
                    self.snake.direction = event.key
            elif event.key == pygame.K_DOWN:
                if self.snake.direction != pygame.K_UP:
                    self.snake.direction = event.key
            elif event.key == pygame.K_LEFT:
                if self.snake.direction != pygame.K_RIGHT:
                    self.snake.direction = event.key
            elif event.key == pygame.K_RIGHT:
                if self.snake.direction != pygame.K_LEFT:
                    self.snake.direction = event.key
            elif event.key == pygame.K_ESCAPE:
                self.on_quit(self.game)

def main():
    game = Game()
    play_scene = PlayScene(game)
    game.mainloop(play_scene)
    pygame.quit()

if __name__ == '__main__':
    main()
99 percent of computer problems exists between chair and keyboard.
Reply


Messages In This Thread
RE: Made my first Python program: Snake. Please help me improve it - by Windspar - Feb-19-2019, 07:08 PM

Possibly Related Threads…
Thread Author Replies Views Last Post
  how to add segments to the snake body blacklight 1 3,009 Sep-13-2023, 07:33 AM
Last Post: angelabarrios
  [PyGame] Snake game: how to get an instance for my snake's body multiple times? hajebazil 2 2,266 Jan-30-2022, 04:58 AM
Last Post: hajebazil
  help with snake game blacklight 3 2,712 Jul-30-2020, 01:13 AM
Last Post: nilamo
  Snake Game - obstacle problem Samira 3 5,811 Oct-31-2019, 02:58 PM
Last Post: Samira
  Creating Snake game in Turtle Shadower 1 8,724 Feb-11-2019, 07:00 PM
Last Post: woooee
  [PyGame] Basic Snake game (using OOP) PyAlex 1 12,690 Sep-10-2018, 09:02 PM
Last Post: Mekire
  [PyGame] Snake not changing directions in Snake Game Bjdamaster 4 5,095 Aug-13-2018, 05:09 AM
Last Post: Bjdamaster
  [PyGame] Snake controls not working jakegold98 5 6,608 Dec-12-2017, 01:45 AM
Last Post: Windspar

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020