Skip to content

topdownengine.camera Reference

Camera

Class that represents the Camera.

Attributes:

Name Type Description
real_position Vector2

The position of the camera, excluding screenshake.

screenshake_offset Vector2

The current screenshake offset.

focus_game_object GameObject | None

The GameObject to center the camera on. If None, the Camera will not center on any GameObject.

screenshake dict[str, float]

Current screenshake dictionary.

position Vector2

The position of the camera, factoring screenshake.

Source code in topdownengine/camera.py
class Camera:
    """Class that represents the Camera.

    Attributes:
        real_position (pygame.Vector2): The position of the camera, excluding screenshake.
        screenshake_offset (pygame.Vector2): The current screenshake offset.
        focus_game_object (GameObject|None): The GameObject to center the camera on. If None, the Camera will not center on any GameObject.
        screenshake (dict[str,float]): Current screenshake dictionary.
        position (pygame.Vector2): The position of the camera, factoring screenshake.
    """
    def __init__(self):
        "Initialize the camera."
        self.real_position = pg.Vector2()
        self.screenshake_offset = pg.Vector2()
        self.focus_game_object = None
        self.screenshake = {"duration": 0, "intensity": 0}

    @property
    def position(self) -> pg.Vector2:
        "Get the position of the camera with screenshake."
        return self.real_position + (self.screenshake_offset if self.screenshake["duration"] > 0 else pg.Vector2())

    def update_screenshake(self, dt: float) -> None:
        """Update the screenshake offset.

        Args:
            dt (float): The deltatime
        """
        if self.screenshake["duration"] > 0:
            self.screenshake_offset = pg.Vector2(
                random.uniform(-self.screenshake["intensity"], self.screenshake["intensity"]),
                random.uniform(-self.screenshake["intensity"], self.screenshake["intensity"]),
            )
        self.screenshake["duration"] = max(0, self.screenshake["duration"] - (dt/1000)) # dt is in milliseconds

    def track_game_object(self, dt: float) -> None:
        """Tracks the `focus_game_object` by snapping instantly to it.

        Args:
            dt (float): The deltatime
        """
        screen = pg.display.get_surface()
        self.real_position = pg.Vector2(self.focus_game_object.position) - pg.Vector2(
            screen.width / GameObject.SCALE / 2, 
            screen.height / GameObject.SCALE / 2
        )

    def handle_bounds(self) -> None:
        "Handle camera bounds."
        self.real_position.x = max(0, self.position.x)
        self.real_position.y = max(0, self.position.y)

    def update(self, dt: float) -> None:
        """Update the Camera.

        Args:
            dt (float): The deltatime.
        """        
        self.update_screenshake(dt)

        if self.focus_game_object:
            self.track_game_object(dt)

        # Bounds
        self.handle_bounds()

position property

Get the position of the camera with screenshake.

__init__()

Initialize the camera.

Source code in topdownengine/camera.py
def __init__(self):
    "Initialize the camera."
    self.real_position = pg.Vector2()
    self.screenshake_offset = pg.Vector2()
    self.focus_game_object = None
    self.screenshake = {"duration": 0, "intensity": 0}

handle_bounds()

Handle camera bounds.

Source code in topdownengine/camera.py
def handle_bounds(self) -> None:
    "Handle camera bounds."
    self.real_position.x = max(0, self.position.x)
    self.real_position.y = max(0, self.position.y)

track_game_object(dt)

Tracks the focus_game_object by snapping instantly to it.

Parameters:

Name Type Description Default
dt float

The deltatime

required
Source code in topdownengine/camera.py
def track_game_object(self, dt: float) -> None:
    """Tracks the `focus_game_object` by snapping instantly to it.

    Args:
        dt (float): The deltatime
    """
    screen = pg.display.get_surface()
    self.real_position = pg.Vector2(self.focus_game_object.position) - pg.Vector2(
        screen.width / GameObject.SCALE / 2, 
        screen.height / GameObject.SCALE / 2
    )

update(dt)

Update the Camera.

Parameters:

Name Type Description Default
dt float

The deltatime.

required
Source code in topdownengine/camera.py
def update(self, dt: float) -> None:
    """Update the Camera.

    Args:
        dt (float): The deltatime.
    """        
    self.update_screenshake(dt)

    if self.focus_game_object:
        self.track_game_object(dt)

    # Bounds
    self.handle_bounds()

update_screenshake(dt)

Update the screenshake offset.

Parameters:

Name Type Description Default
dt float

The deltatime

required
Source code in topdownengine/camera.py
def update_screenshake(self, dt: float) -> None:
    """Update the screenshake offset.

    Args:
        dt (float): The deltatime
    """
    if self.screenshake["duration"] > 0:
        self.screenshake_offset = pg.Vector2(
            random.uniform(-self.screenshake["intensity"], self.screenshake["intensity"]),
            random.uniform(-self.screenshake["intensity"], self.screenshake["intensity"]),
        )
    self.screenshake["duration"] = max(0, self.screenshake["duration"] - (dt/1000)) # dt is in milliseconds

SmoothTrackerCamera

Bases: Camera

A subclass of Camera with smoother tracking logic.

Source code in topdownengine/camera.py
class SmoothTrackerCamera(Camera):
    "A subclass of Camera with smoother tracking logic."

    def track_game_object(self, dt: float):
        """Tracks the `focus_game_object` by smoothly moving to its position.

        Args:
            dt (float): The deltatime
        """
        screen = pg.display.get_surface()
        target_position = pg.Vector2(self.focus_game_object.position) - pg.Vector2(
            screen.width / GameObject.SCALE / 2, 
            screen.height / GameObject.SCALE / 2
        )

        self.real_position += (target_position - self.real_position) * (dt / 1000) * 5

position property

Get the position of the camera with screenshake.

__init__()

Initialize the camera.

Source code in topdownengine/camera.py
def __init__(self):
    "Initialize the camera."
    self.real_position = pg.Vector2()
    self.screenshake_offset = pg.Vector2()
    self.focus_game_object = None
    self.screenshake = {"duration": 0, "intensity": 0}

handle_bounds()

Handle camera bounds.

Source code in topdownengine/camera.py
def handle_bounds(self) -> None:
    "Handle camera bounds."
    self.real_position.x = max(0, self.position.x)
    self.real_position.y = max(0, self.position.y)

track_game_object(dt)

Tracks the focus_game_object by smoothly moving to its position.

Parameters:

Name Type Description Default
dt float

The deltatime

required
Source code in topdownengine/camera.py
def track_game_object(self, dt: float):
    """Tracks the `focus_game_object` by smoothly moving to its position.

    Args:
        dt (float): The deltatime
    """
    screen = pg.display.get_surface()
    target_position = pg.Vector2(self.focus_game_object.position) - pg.Vector2(
        screen.width / GameObject.SCALE / 2, 
        screen.height / GameObject.SCALE / 2
    )

    self.real_position += (target_position - self.real_position) * (dt / 1000) * 5

update(dt)

Update the Camera.

Parameters:

Name Type Description Default
dt float

The deltatime.

required
Source code in topdownengine/camera.py
def update(self, dt: float) -> None:
    """Update the Camera.

    Args:
        dt (float): The deltatime.
    """        
    self.update_screenshake(dt)

    if self.focus_game_object:
        self.track_game_object(dt)

    # Bounds
    self.handle_bounds()

update_screenshake(dt)

Update the screenshake offset.

Parameters:

Name Type Description Default
dt float

The deltatime

required
Source code in topdownengine/camera.py
def update_screenshake(self, dt: float) -> None:
    """Update the screenshake offset.

    Args:
        dt (float): The deltatime
    """
    if self.screenshake["duration"] > 0:
        self.screenshake_offset = pg.Vector2(
            random.uniform(-self.screenshake["intensity"], self.screenshake["intensity"]),
            random.uniform(-self.screenshake["intensity"], self.screenshake["intensity"]),
        )
    self.screenshake["duration"] = max(0, self.screenshake["duration"] - (dt/1000)) # dt is in milliseconds