Advertisement
Windspar

Pygame Clean Code and Collision Example

Feb 9th, 2020
354
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 8.01 KB | None | 0 0
  1. import pygame
  2. import itertools
  3. from pygame.sprite import Group, Sprite
  4.  
  5. map_data = [
  6.        [ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1],
  7.        [ 1,0,0,0,0,1,0,0,0,0,0,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
  8.        [ 1,0,0,0,0,1,0,0,0,0,0,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
  9.        [ 1,0,0,0,0,1,0,0,0,0,0,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
  10.        [ 1,0,0,0,0,1,0,0,0,0,0,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
  11.        [ 1,0,0,0,0,1,0,0,0,0,0,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
  12.        [ 1,0,0,0,0,1,0,0,0,0,0,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
  13.        [ 1,0,0,0,0,1,0,0,0,0,0,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
  14.        [ 1,0,0,0,0,1,0,0,0,0,0,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
  15.        [ 1,0,0,0,0,1,0,0,0,0,0,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
  16.        [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
  17.        [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
  18.        [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
  19.        [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
  20.        [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
  21.     ]
  22.  
  23. class Engine:
  24.     def __init__(self, caption, width, height, flags=0):
  25.         pygame.display.set_caption(caption)
  26.         self.surface = pygame.display.set_mode((width, height), flags)
  27.         self.rect = self.surface.get_rect()
  28.         self.clock = pygame.time.Clock()
  29.         self.running = False
  30.         self.delta = 0
  31.         self.fps = 60
  32.  
  33.     def idle(self):
  34.         self.delta = self.clock.tick(self.fps)
  35.  
  36. class Point:
  37.     def __init__(self, x, y):
  38.         self.x = x
  39.         self.y = y
  40.  
  41.     def __add__(self, rhs):
  42.         return Point(self.x + rhs.x, self.y + rhs.y)
  43.  
  44.     def __sub__(self, rhs):
  45.         return Point(self.x - rhs.x, self.y - rhs.y)
  46.  
  47.     def __mul__(self, rhs):
  48.         return Point(self.x * rhs.x, self.y * rhs.y)
  49.  
  50.     def __truediv__(self, rhs):
  51.         return Point(self.x / rhs.x, self.y / rhs.y)
  52.  
  53.     def __floordiv__(self, rhs):
  54.         return Point(self.x // rhs.x, self.y // rhs.y)
  55.  
  56.     def __iter__(self):
  57.         yield self.x
  58.         yield self.y
  59.  
  60. class MovementKeys:
  61.     def __init__(self, up, down, left, right):
  62.         self.up = up
  63.         self.down = down
  64.         self.left = left
  65.         self.right = right
  66.  
  67. class Player(Sprite):
  68.     def __init__(self, image, movement_keys, position, anchor="topleft"):
  69.         Sprite.__init__(self)
  70.         self.image = image
  71.         self.rect = image.get_rect(**{anchor: position})
  72.         self.center = pygame.Vector2(self.rect.center)
  73.         self.speed = 8 * 0.01
  74.  
  75.         self.key = movement_keys
  76.  
  77.     def get_position(self, size):
  78.         return Point(int(self.center.x // size.x), int(self.center.y // size.y))
  79.  
  80.     def update(self, delta, keys_pressed, grid):
  81.         direction = pygame.Vector2(0, 0)
  82.         if keys_pressed[self.key.up]:
  83.             direction.y -= 1
  84.  
  85.         if keys_pressed[self.key.down]:
  86.             direction.y += 1
  87.  
  88.         if keys_pressed[self.key.left]:
  89.             direction.x -= 1
  90.  
  91.         if keys_pressed[self.key.right]:
  92.             direction.x += 1
  93.  
  94.         if direction != pygame.Vector2(0, 0):
  95.             direction.normalize_ip()
  96.             old_center = pygame.Vector2(self.center)
  97.             self.center += direction * self.speed * delta
  98.             self.rect.center = self.center
  99.  
  100.             # Collision
  101.             if grid.collide(self):
  102.                 self.center = old_center
  103.                 self.rect.center = self.center
  104.  
  105. class Grid:
  106.     def __init__(self, screen_size, block_size):
  107.         self.block_range = Point(int(screen_size.x / block_size.x) + 1,
  108.                                  int(screen_size.y / block_size.y) + 1)
  109.         self.block_size = block_size
  110.         self.position = Point(0, 0)
  111.  
  112.     def collide(self, player):
  113.         rects = self.get_rects(player.get_position(self.block_size))
  114.         for rect in rects:
  115.             if rect.colliderect(player.rect):
  116.                 return True
  117.  
  118.         return False
  119.  
  120.     def collide_list(self, player):
  121.         rect_list = []
  122.         rects = self.get_rects(player.get_position(self.block_size))
  123.         for rect in rects:
  124.             if rect.colliderect(player.rect):
  125.                 rect_list.append(rect)
  126.  
  127.         return rect_list
  128.  
  129.     def get_rects(self, position):
  130.         rect = pygame.Rect(0, 0, *self.block_size)
  131.         rect_list = []
  132.         for x, y in itertools.product(range(position.x - 1, position.x + 2), range(position.y - 1, position.y + 2)):
  133.             try:
  134.                 if map_data[y][x] == 1:
  135.                     rect.topleft = x * self.block_size.x, y * self.block_size.y
  136.                     rect_list.append(rect.copy())
  137.             except:
  138.                 pass
  139.  
  140.         return rect_list
  141.  
  142.     def draw(self, surface):
  143.         rect = pygame.Rect(0, 0, *self.block_size)
  144.         color = pygame.Color('gray30')
  145.         for x, y in itertools.product(range(self.position.x, self.block_range.x), range(self.position.y, self.block_range.y)):
  146.             try:
  147.                 if map_data[y][x] == 1:
  148.                     rect.topleft = x * self.block_size.x, y * self.block_size.y
  149.                     surface.fill(color, rect)
  150.             except:
  151.                 pass
  152.  
  153. class GameVariables:
  154.     def __init__(self, engine):
  155.         self.engine = engine
  156.         self.sprites = Group()
  157.         self.block_size = Point(32, 32)
  158.         self.player_size = Point(24, 24)
  159.         self.grid = Grid(Point(*engine.rect.size), self.block_size)
  160.         self.player_blue = self.create_player(pygame.Color('dodgerblue'), engine.rect.center, "center")
  161.         self.sprites.add(self.player_blue)
  162.  
  163.     def create_player(self, color, position, anchor):
  164.         surface = pygame.Surface(tuple(self.player_size))
  165.         surface.fill(pygame.Color('dodgerblue'))
  166.         movement_keys = MovementKeys(pygame.K_w, pygame.K_s, pygame.K_a, pygame.K_d)
  167.         return Player(surface, movement_keys, position, anchor)
  168.  
  169. def main():
  170.     pygame.init()
  171.     engine = Engine("Player Movement And Collision", 500, 500)
  172.     background = pygame.Color('black')
  173.     game = GameVariables(engine)
  174.  
  175.     engine.running = True
  176.     while engine.running:
  177.         for event in pygame.event.get():
  178.             if event.type == pygame.QUIT:
  179.                 engine.running = False
  180.  
  181.         # Logic
  182.         keys_pressed = pygame.key.get_pressed()
  183.         game.sprites.update(engine.delta, keys_pressed, game.grid)
  184.  
  185.         # Drawing
  186.         engine.surface.fill(background)
  187.         game.grid.draw(engine.surface)
  188.         game.sprites.draw(engine.surface)
  189.         pygame.display.update()
  190.  
  191.         # Sleeping
  192.         engine.idle()
  193.  
  194. main()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement