import os import sys import pygame from PIL import Image, ImageDraw from pathlib import Path print(f"python executable: {sys.executable}") ### CONSTANTS ### # Convention: use capital letters for constants (= variables you leave unchanged) # Windows WIN_HEIGHT = 800 WIN_WIDTH = 500 # Define colors WHITE = (255, 255, 255) BLACK = (0, 0, 0) RED = (255, 0, 0) GREEN = (0, 255, 0) BLUE = (0, 0, 255) BG_COLOR = WHITE # Framerate FPS = 30 TIME_DELAY = int(1000 / FPS) # Game Constants SPEED = 12 ### FUNCTIONS ### ### CLASSES ### class Player(pygame.sprite.Sprite): def __init__(self, img_path, xy_center, v, mass): super().__init__() # call __init__ of parent class (i.e. of pygame.sprite.Sprite) # ASSIGN CLASS ATTRIBUTES if not os.path.exists(img_path): raise Exception("THE FOLLOWING FILE DOES NOT EXIST: {0}".format(img_path)) self.image = pygame.image.load(str(img_path)) # load image self.rect = self.image.get_rect() # create rectangle containing ball image self.rect.center = (int(xy_center[0]),int(xy_center[1])) # set center coords of ball self.mask = pygame.mask.from_surface(self.image) # creates a mask, used for collision detection (see manual about pygame.sprite.collide_mask()) self.mass = mass # give sprite a mass -> realistic collisions def update(self): # in each step, this method is called if self.rect.left <= 0: self.rect.left = 0 elif self.rect.right >= WIN_WIDTH: self.rect.right = WIN_WIDTH if self.rect.top <= 0: self.rect.top = 0 elif self.rect.bottom >= WIN_HEIGHT: self.rect.bottom = WIN_HEIGHT def collide(self,ball): pass class Ball(pygame.sprite.Sprite): """ Class for balls, derive from pygame's sprite class -> makes your life easier since you can use e.g. the collision detection of the sprite class """ def __init__(self, img_path, xy_center, v, mass): super().__init__() # call __init__ of parent class (i.e. of pygame.sprite.Sprite) # ASSIGN CLASS ATTRIBUTES if not os.path.exists(img_path): # check if folder of image exists raise Exception("THE FOLLOWING FILE DOES NOT EXIST: {0}".format(img_path)) self.image = pygame.image.load(str(img_path)) # load image self.rect = self.image.get_rect() # create rectangle containing ball image self.rect.center = (int(xy_center[0]),int(xy_center[1])) # set center coords of ball self.mask = pygame.mask.from_surface(self.image) # creates a mask, used for collision detection (see manual about pygame.sprite.collide_mask()) self.mass = mass # is relevant for realistic collisions def update(self): """ - update function gets executed in every step - determines motion of ball """ pass def collide(self,ball): """ ball self collides with other ball, given as argument this method updates velocities of BOTH balls """ pass class Game: """ Main GAME class """ def __init__(self): pygame.init() pygame.font.init() self.time_delay = TIME_DELAY self.screen = pygame.display.set_mode((WIN_WIDTH, WIN_HEIGHT)) # create screen which will display everything self.win = pygame.display.set_mode((WIN_WIDTH, WIN_HEIGHT)) pygame.display.set_caption("Bouncing Balls") # Game title def quit(self): pygame.quit() sys.exit(0) def play(self): # CREATE PLAYER player = Player(os.path.join("data","ball_r=100_col=0_255_0.png"),[150,550],[0,0],1) # CREATE GAME GROUPS Balls = pygame.sprite.Group() # CREATE OBJECTS AND ASSIGN TO GROUPS balls_list = [ Ball(os.path.join("data","ball_r=100_col=0_0_255.png"),[100,200],[0,0],1), Ball(os.path.join("data","ball_r=100_col=0_0_255.png"),[200,400],[0,0],1) ] Balls.add(balls_list) # GAME PERMANENT LOOP while True: pygame.time.delay(TIME_DELAY) # KEY EVENTS for event in pygame.event.get(): # Exit app if click quit button if event.type == pygame.QUIT: self.quit() # Naviation of player keys = pygame.key.get_pressed() if keys[pygame.K_UP]: player.rect.top -= SPEED # and so on ... # COLLISION DETECTION # see manual for all types of collisions: https://www.pygame.org/docs/ref/sprite.html#pygame.sprite.spritecollide # TODO: check for collisions between any two balls. If there is any, call the collision() method of the Ball class. for ball in balls_list: pass # UPDATE Balls.update() player.update() # DRAW self.screen.fill(BG_COLOR) # draw empty screen Balls.draw(self.screen) self.screen.blit(player.image, player.rect) pygame.display.update() pygame.quit() if __name__ == "__main__": Game().play()