def __init__(self): Scene.__init__(self) # The order in which components are created determine the order of script execution demo_background = GameObject(self, name="Demo Background") Transform(demo_background, scale=Vector2D(2, 2)) SpriteRenderer( demo_background, Sprite.from_path("./demo_assets/sprites/demo_background.jpg"), update_on_draw=False) demo_player = GameObject(self, name="Demo Player") Transform(demo_player, scale=Vector2D(2, 2)) SpriteRenderer( demo_player, Sprite.from_path("./demo_assets/sprites/demo_player.png")) DemoMovement(demo_player) main_camera = GameObject(self, name="Main Camera", parent=demo_player) Transform(main_camera) Camera( main_camera, [0, 0, Screen().screen_size()[0], Screen().screen_size()[1]]) demo_text = GameObject(self, name="Demo Text") Transform(demo_text, position=Vector2D(-Screen().screen_size()[0] / 2, -Screen().screen_size()[1] / 2)) SpriteRenderer(demo_text, align_x="right", align_y="bottom") Text(demo_text, font="./demo_assets/fonts/calling_code.ttf", font_size=40, text="Demo Text", color=Color.RGBA(255, 87, 51), background_color=Color.RGBA(0, 0, 0, 200)) # The order in which game_objects are added to the list determines the order of rendering and execution self.game_objects.append(demo_background) self.game_objects.append(demo_player) self.game_objects.append(demo_text) self.game_objects.append(main_camera)
def __init__(self, game_object, position=None, scale=None, rotation=None): # type: (GameObject, Vector2D, Vector2D, float) -> None Component.__init__(self, game_object) if isinstance(position, Vector2D): self.position = position else: self.position = Vector2D(0, 0) if isinstance(scale, Vector2D): self.__scale = scale else: self.__scale = Vector2D(1, 1) if isinstance(rotation, int): self.__rotation = rotation else: self.__rotation = 0.0
def __init__(self, game_object, sprite=None, update_on_draw=False, align_x="center", align_y="center"): # type: (GameObject, Sprite, bool, str, str) -> None Component.__init__(self, game_object) self.__sprite = sprite # type: Sprite self.transform = None # type: Transform self.__sprite_transformed = None # type: pygame.Surface self.sprite_size = Vector2D(0, 0) self.__current_world_scale = Vector2D(1, 1) self.__current_world_rotation = 0 self.update_on_draw = update_on_draw self.align_x = align_x self.align_y = align_y
def on_draw(self, camera): # type: (Camera) -> None if not isinstance(self.__sprite, Sprite): Debug.log_warning("sprite parameter not Sprite object", self) return # self.update_sprite(camera) if self.update_on_draw: self.update_sprite() # Position in the world sprite_world_position = self.sprite_world_position # type: Vector2D # Position of the screen in the world screen_in_world_position = camera.screen_in_world_position # type: Vector2D # Position of the sprite relative to the screen sprite_in_screen_position = sprite_world_position sprite_in_screen_position.relative_to(screen_in_world_position) render_area = [0, 0, self.sprite_size.x, self.sprite_size.y] # We do not render what isn't visible if sprite_in_screen_position.x < 0: render_area[0] = min(-sprite_in_screen_position.x, self.sprite_size.x) sprite_in_screen_position.x += render_area[0] if sprite_in_screen_position.y < 0: render_area[1] = min(-sprite_in_screen_position.y, self.sprite_size.y) sprite_in_screen_position.y += render_area[1] if sprite_in_screen_position.x + ( self.sprite_size.x - render_area[0]) > camera.render_size[0]: render_area[2] = max( camera.render_size[0] - sprite_in_screen_position.x, 0) if sprite_in_screen_position.y + ( self.sprite_size.y - render_area[1]) > camera.render_size[1]: render_area[3] = max( camera.render_size[1] - sprite_in_screen_position.y, 0) sprite_in_screen_position += Vector2D(0, 0, lst=camera.render_pos) if render_area[0] == render_area[2] or render_area[1] == render_area[3]: return Screen.screen().blit(self.__sprite_transformed, sprite_in_screen_position.list(), render_area)
def update(self): # This demo movement will move the player using WASD, without ever rotating nor scaling the object. # We create an empty movement vector, which will be the vector we will move towards after taking player input movement_vector = Vector2D(0, 0) # We check if we have W pressed # Up movement means subtracting from the y direction if self.input_manager.get_key(pygame.K_w): movement_vector.y -= 1 # We check if we have A pressed # Left movement means subtracting from the x direction if self.input_manager.get_key(pygame.K_a): movement_vector.x -= 1 # We check if we have S pressed # Down movement means adding to the y direction if self.input_manager.get_key(pygame.K_s): movement_vector.y += 1 # We check if we have D pressed # Right movement means adding from the x direction if self.input_manager.get_key(pygame.K_d): movement_vector.x += 1 # The movement vector right now would be larger if we went in a straight line # than if we went in a diagonal # Going in a straight line (directly upwards, for example) would result of a length of 1. # However going diagonally would result in a length of sqrt(1^2 + 1^2) because of the # pythagorean theorem # We fix this by normalizing the vector. This way it ends up being an unit vector. movement_vector.normalize() # Now we will multiply the movement vector by the speed we had to make the length of out unit vector the # same as the length we want, our speed. movement_vector *= self.move_speed # Frame rate can vary depending on the number of components and game objects in the scene, # so we cannot assume the timing between frames will be constant # The Time.delta_time method returns the time passed from the previous frame to the current one, this way, # regardless of the frame rate, we will move at the same speed per second # To use Time.delta_time we multiply the movement_vector by Time.delta_time movement_vector *= Time.delta_time() # To end the movement, we add the movement_vector to our current local position self.transform.position = self.transform.position + movement_vector
def __init__(self, size=None, flags=pygame.HWSURFACE | pygame.SRCALPHA, surface=None): # type: (Vector2D, int, pygame.Surface) -> None if size is None and surface is None: Debug.log_error("No size and no surface", "Sprite Object") return if size is not None: self.sprite_surface = pygame.Surface(size.list(), flags=flags) self.sprite_size = size.copy() else: self.sprite_surface = surface self.sprite_size = Vector2D(surface.get_width(), surface.get_height())
def __update_sprite(self): if not self.sprite_renderer or not isinstance(self.__color, Color.RGBA): return # Render the text if isinstance(self.outline_color, Color.RGBA): new_sprite_surface = TextBetterRender.render( self.__text, self.__font_object, color=self.__color.list(), outline_color=self.outline_color.list(), opx=self.outline_width, anti_alias=self.anti_alias) else: new_sprite_surface = self.__font_object.render( self.__text, self.anti_alias, self.__color.list()) alpha_surface = Sprite( size=Vector2D(0, 0, new_sprite_surface.get_size())) alpha_surface.sprite_surface.fill((255, 255, 255, self.__color.a)) alpha_surface.sprite_surface.blit(new_sprite_surface, (0, 0), special_flags=pygame.BLEND_RGBA_MULT) self.sprite_renderer.sprite = alpha_surface