"""Camera module - manages zoom and pan for a 2D viewport.""" import pygame as pg class Camera: """2D camera with zoom and world/screen coordinate conversion. Attributes: zoom (float): Current zoom multiplier, clamped to [0.5, 4.0]. offset (pg.math.Vector2): Top-left world position currently in view. """ def __init__(self): self.zoom = 2 self.offset = pg.math.Vector2(0, 0) def world_to_screen(self, pos): """Convert a world-space position to screen pixels.""" return ( int((pos[0] - self.offset.x) * self.zoom), int((pos[1] - self.offset.y) * self.zoom), ) def screen_to_world(self, pos): """Convert a screen pixel position to world-space coordinates.""" return ( pos[0] / self.zoom + self.offset.x, pos[1] / self.zoom + self.offset.y, ) def move(self, dx, dy): """Pan the camera by (dx, dy) in world-space units.""" self.offset.x += dx self.offset.y += dy def change_zoom(self, amount): """Adjust zoom by amount, clamped to [0.5, 4.0].""" self.zoom += amount self.zoom = max(0.5, min(self.zoom, 4.0)) def zoom_offset(self, screen_pos, zoom_factor): """Zoom toward screen_pos, keeping the world point under it stationary.""" world_before = self.screen_to_world(screen_pos) self.change_zoom(zoom_factor) world_after = self.screen_to_world(screen_pos) # Compensate offset so the point under the cursor doesn't shift self.offset.x += world_before[0] - world_after[0] self.offset.y += world_before[1] - world_after[1]