Oct-28-2023, 03:20 PM
(This post was last modified: Oct-28-2023, 03:20 PM by deanhystad.)
The function is not defined in the while loop, it is defined below the while loop. It is a convention to put the functions at the top of a module, but python doesn't care. Functions are compiled when the file is imported the first time, not during runtime, so it wouldn't matter if the function was defined in a loop.
Here's an example of how a snake game might be structured:
Here's an example of how a snake game might be structured:
import pygame from random import randint CUBE_SIZE = 25 CUBES_NUM = 20 WIDTH = CUBE_SIZE * CUBES_NUM class Segment(pygame.sprite.Sprite): """A segment of a snake""" def __init__(self, pos=(0, 0), color="green"): super().__init__() self.rect = pygame.Rect(0, 0, CUBE_SIZE, CUBE_SIZE) self.image = pygame.surface.Surface(self.rect.size) self.image.fill(color) self.at(list(pos)) def at(self, position): """Set my grid location.""" self.pos = position self.rect.x = self.pos[0] * CUBE_SIZE self.rect.y = self.pos[1] * CUBE_SIZE def draw(self, screen): """Draw self on screen.""" screen.blit(self.image, self.rect) class Food(Segment): """Something to eat.""" def __init__(self): """I randomly place myself on the screen.""" super().__init__([randint(1, CUBES_NUM - 2), randint(1, CUBES_NUM - 2)], "blue") class Snake(pygame.sprite.Group): """A group of segments that moves in a coordinated fasion.""" directions = ((1, 0), (0, 1), (-1, 0), (0, -1)) colors = ("green", "yellow") def __init__(self, segments): """Initialize the sname. segments is list of grid coordinates.""" super().__init__() color = "red" for i, segment in enumerate(segments, start=1): self.add(Segment(segment, color)) color = self.colors[i % len(self.colors)] self.head = self.sprites()[0] self.direction = 0 self.add_segment = False self.score = 0 def turn(self, turn): """Turn the snake left (-1) or right (1).""" self.direction = (self.direction + turn) % len(self.directions) def update(self): """Update all the segment positions.""" segments = self.sprites()[::-1] if self.add_segment: # New segment is at the tail end of the snake. self.add_segment = False self.add(Segment(segments[0].pos, self.colors[len(segments) % 2])) # Move all the snake sgments. Starting at the tail each segment moves # to the previous location of the next segment. for a, b in zip(segments, segments[1:]): a.at(b.pos) delta = self.directions[self.direction] self.head.at([self.head.pos[0] + delta[0], self.head.pos[1] + delta[1]]) # Check if the snake hit a wall pos = snake.head.pos if min(pos) < 0 or max(pos) >= CUBES_NUM: self.kill() return # Check if snake bit itself. for segment in segments[:-1]: if segment.pos == pos: self.kill() return def eats(self, food): """Return True if snake eats food.""" if len(self) > 0 and self.head.pos == food.pos: self.score += 1 food.kill() self.add_segment = True # Snake grows longer when it eats. return True return False def kill(self): """Kill all the segments.""" for segment in self.sprites(): segment.kill() pygame.init() screen = pygame.display.set_mode((WIDTH, WIDTH)) clock = pygame.time.Clock() snake = Snake([(x, 10) for x in range(10, 16)]) snake.direction = 2 food = Food() speed = 4 while len(snake) > 0: for event in pygame.event.get(): if event.type == pygame.QUIT: snake.kill() elif event.type == pygame.KEYDOWN: if event.key == pygame.K_LEFT: snake.turn(-1) elif event.key == pygame.K_RIGHT: snake.turn(1) snake.update() if snake.eats(food): speed += 1 food = Food() screen.fill("white") food.draw(screen) snake.draw(screen) pygame.display.update() clock.tick(speed) print("Your score =", snake.score)I left out all the challenging parts like multiple plays and leaderboards, but it is enough to give you an idea about how a snake like game can be designed. You don't have to use sprites and groups, but I think programming a game is much simpler if you do.