def create_objects(self) -> None: self.text = TextObject(game=self.game, text='FPS', color=Color.YELLOW, x=self.game.WIDTH - 50, y=15) self.objects.append(self.text)
def __init__(self, app): super().__init__(app) self.celest_objs = CelestialSpriteGroup() self.transient_objs = [] self.__camera_pos_disp = TextObject('X: 0, Y: 0 | Zoom: 0%', self.app.font, (0, 0, 0))
def create_labels(self): self.score_label = TextObject(c.score_offset, c.status_offset_y, lambda: f'SCORE: {self.score}', c.text_color, c.font_name, c.font_size) self.objects.append(self.score_label) self.lives_label = TextObject(c.lives_offset, c.status_offset_y, lambda: f'LIVES: {self.lives}', c.text_color, c.font_name, c.font_size) self.objects.append(self.lives_label)
def show_message(self, text, color=colors.WHITE, font_name='Arial', font_size=20, centralized=False): message = TextObject(c.screen_width // 2, c.screen_height // 2 + 20, lambda: text, color, font_name, font_size) self.draw() message.draw(self.surface, centralized) pygame.display.update() time.sleep(c.message_duration)
def add_field(self, text, format_type): if not self.fields: self.fields = [] if len(self.fields) == 10: raise ValueError('Maximum number of fields allowed is 10') self.fields.append(TextObject().add_text(text, format_type, 2000)) return self
def __init__(self, caption, width, height, frame_rate): """ Args: caption(str): name of the game width(int): width of surface height(int): height of surface frame_rate(int): speed of the game """ pygame.init() self.score = 0 self.text = TextObject(0, 0, (0, 0, 0), 'Score: {}'.format(self.score), 'monaco', 36) self.width = width self.height = height self.side_of_square = 15 self.default_length = 3 body_snake = [ ((width // 100) * self.side_of_square - self.side_of_square * i, (height // 200) * self.side_of_square) for i in range(self.default_length) ] self.objects = { 'Snake': Snake(body_snake, self.side_of_square, 'RIGHT', (0, 255, 0)), 'Apple': Apple( random.randrange(0, width // self.side_of_square) * self.side_of_square, random.randrange(0, height // self.side_of_square) * self.side_of_square, self.side_of_square, (255, 0, 0), self.width, self.height) } self.surface = pygame.display.set_mode((width, height)) self.frame_rate = frame_rate self.game_over = False pygame.display.set_caption(caption) self.time = time.time() self.bonus_apple = False self.clock = pygame.time.Clock()
class OverlayScene(BaseScene): last_datetime = datetime.now() current_datetime = datetime.now() def create_objects(self) -> None: self.text = TextObject(game=self.game, text='FPS', color=Color.YELLOW, x=self.game.WIDTH - 50, y=15) self.objects.append(self.text) def additional_logic(self) -> None: self.last_datetime = self.current_datetime self.current_datetime = datetime.now() delta = self.current_datetime - self.last_datetime milliseconds = int(delta.total_seconds() * 1000) if milliseconds != 0: fps = 1000 / milliseconds self.text.update_text(str(int(fps))) else: self.text.update_text('inf') def on_window_resize(self) -> None: self.text.move_center(x=self.game.WIDTH - 50, y=15)
def add_text(self, text, format_type): self.text = (TextObject().add_text(text, format_type, 3000)) return self
class CelestialScene(Scene): """ Celestial Scene Class - Handles graphical elements """ def __init__(self, app): super().__init__(app) self.celest_objs = CelestialSpriteGroup() self.transient_objs = [] self.__camera_pos_disp = TextObject('X: 0, Y: 0 | Zoom: 0%', self.app.font, (0, 0, 0)) def add_new_celestial(self, new_celestial): # New celestial instance with world_offset ctr = new_celestial.rect.center world_ctr = (ctr[0] + int(-self.camera.position.x), ctr[1] + int(-self.camera.position.y)) new_celestial.position = world_ctr # Set the group to the celestial new_celestial.neighbours = self.celest_objs # Add to sprite.Group() for processing self.celest_objs.add(new_celestial) # Add to scene sprite.Group() for drawing self.content.add(new_celestial) # Add vector arrows to for celestial arr_accel = VelocityArrow(new_celestial.position, new_celestial, color=(200, 0, 0), indicator_type=TYPE_ACCEL, thickness=1) arr_vel = VelocityArrow(new_celestial.position, new_celestial, color=(0, 70, 170), indicator_type=TYPE_VEL, thickness=1) self.transient_objs.append(arr_accel) self.transient_objs.append(arr_vel) return new_celestial def kill_all_objects(self): """ Private function to kill all objects """ # Iterate and call pygame.sprite.Sprite kill() function to remove from any pygame.sprite.Groups() for o in self.celest_objs: o.kill() # Clear all transients self.transient_objs.clear() print( f"Killed all objects: Celestials: {len(self.celest_objs)}, Transients: {len(self.transient_objs)}" ) def update(self, delta_time): """ Update Scene """ super().update(delta_time) # Update Camera Position Text Display cam_text = f"X: {self.camera.position.x}, Y: {self.camera.position.y} | Zoom: {self.camera.position.z+100}%" self.__camera_pos_disp.text = cam_text # Call update() method of all sprites in the sprite.Group() self.celest_objs.update(delta_time) # Iterate sprite group for o in self.celest_objs: # Update world offset for all items if isinstance(o, SpriteEntity): o.world_offset = self.camera.position # Reset 'just_calcd' variable for next frame if isinstance(o, CelestialObject): o.force_just_calcd = False # Iterate transient non-sprite graphical objects list (in reverse to protect when removing) for t in reversed(self.transient_objs): # Update world offset, call update() and remove expired Transients if isinstance(t, TransientDrawEntity): t.world_offset = self.camera.position t.update(delta_time) if t.dead: self.transient_objs.remove(t) def draw(self, surface: pygame.Surface): """ Draw function - Handles drawing any objects that are not automatically drawn through sprite.Group()s """ # Call super() draw() function to draw scene.content super().draw(surface) # Draw sprites in sprite.Group() self.celest_objs.draw(surface) # Iterate all Transient objects and call .draw() func for t in self.transient_objs: if isinstance(t, TransientDrawEntity): t.draw(surface) self.__camera_pos_disp.draw(surface)
class Game: """Main class. Attributes: score(int): score that user has text(str): string for drawing score width(int), height(int): size of surface side_of_square(int): objects(dict): objects that draw on the surface surface(pygame.Surface): surface frame_rate(int): speed of the game game_over(bool): status of the game time(time): value for checking when we must give a new bonus clock: parameter for frame rate """ def __init__(self, caption, width, height, frame_rate): """ Args: caption(str): name of the game width(int): width of surface height(int): height of surface frame_rate(int): speed of the game """ pygame.init() self.score = 0 self.text = TextObject(0, 0, (0, 0, 0), 'Score: {}'.format(self.score), 'monaco', 36) self.width = width self.height = height self.side_of_square = 15 self.default_length = 3 body_snake = [ ((width // 100) * self.side_of_square - self.side_of_square * i, (height // 200) * self.side_of_square) for i in range(self.default_length) ] self.objects = { 'Snake': Snake(body_snake, self.side_of_square, 'RIGHT', (0, 255, 0)), 'Apple': Apple( random.randrange(0, width // self.side_of_square) * self.side_of_square, random.randrange(0, height // self.side_of_square) * self.side_of_square, self.side_of_square, (255, 0, 0), self.width, self.height) } self.surface = pygame.display.set_mode((width, height)) self.frame_rate = frame_rate self.game_over = False pygame.display.set_caption(caption) self.time = time.time() self.bonus_apple = False self.clock = pygame.time.Clock() def check_problems(self): """Check snake coordinates. Returns: bool: True if all right, else False """ if not self.crash_into_wall(): return False if not self.crash_himself(): return False return True def crash_into_wall(self): """ Check that snake did not crash into wall. Returns: bool: True if all right, False if snake crashed into wall """ if self.objects['Snake'].head[0] < 0 or self.objects['Snake'].head[0] > self.width or \ self.objects['Snake'].head[1] < 0 or self.objects['Snake'].head[1] > self.height: return False return True def crash_himself(self): """ Check that snake did not crash himself. Returns: bool: True if all right, False if snake crashed himself """ for body_square in self.objects['Snake'].body[1:]: if self.objects['Snake'].head == (body_square.x_coordinate, body_square.y_coordinate): return False return True def handle_events(self): """ Read user clicks and send command to the snake. Returns: nothing """ for event in pygame.event.get(): if event.type == pygame.QUIT: pygame.quit() sys.exit() elif event.type == pygame.KEYDOWN: if event.key == pygame.K_RIGHT or event.key == pygame.K_d: self.objects['Snake'].new_direction('RIGHT') if event.key == pygame.K_LEFT or event.key == pygame.K_a: self.objects['Snake'].new_direction('LEFT') if event.key == pygame.K_UP or event.key == pygame.K_w: self.objects['Snake'].new_direction('UP') if event.key == pygame.K_DOWN or event.key == pygame.K_s: self.objects['Snake'].new_direction('DOWN') if event.key == pygame.K_ESCAPE: pygame.event.post(pygame.event.Event(pygame.QUIT)) def update(self): """ Update the state of the game. Check problems and check that snake eat apple or bonus Returns: nothing """ flag = True if self.bonus_apple: if self.objects['Snake'].head == ( self.objects['Bonus'].x_coordinate, self.objects['Bonus'].y_coordinate): self.score += 3 self.text.get_update('Score: {}'.format(self.score)) self.objects['Snake'].update() self.objects.pop('Bonus') flag = True self.bonus_apple = False elif time.time( ) - self.objects['Bonus'].time > self.objects['Bonus'].max_time: self.objects.pop('Bonus') self.time = time.time() self.bonus_apple = False if self.objects['Snake'].head == (self.objects['Apple'].x_coordinate, self.objects['Apple'].y_coordinate): self.score += 1 self.text.get_update('Score: {}'.format(self.score)) self.frame_rate += 0.5 self.objects['Snake'].update() self.objects['Apple'].update() elif flag: self.objects['Snake'].update() self.objects['Snake'].delete_tail() def draw(self): """ Draw all objects of the game. Returns: nothing """ for elem in self.objects: self.objects[elem].draw(self.surface) self.text.draw(self.surface) def get_bonus_apple(self): """ Create bonus and add in objects of the game. Returns: nothing """ if time.time() - self.time > 25: self.time = time.time() self.bonus_apple = True self.objects['Bonus'] = Bonus( random.randrange(0, self.width // self.side_of_square) * self.side_of_square, random.randrange(0, self.height // self.side_of_square) * self.side_of_square, self.side_of_square, (255, 255, 0), self.width, self.height) def run(self): """ Start the game. Returns: nothing """ while not self.game_over: self.surface.fill((244, 164, 96)) if not self.check_problems(): game_over(self.surface) break self.handle_events() self.get_bonus_apple() self.update() self.draw() pygame.display.update() self.clock.tick(self.frame_rate)