import math import cocos import pyglet.window.key as key from app import keyboard_state class RTSCameraMotion(cocos.actions.Action): scale_levels = [0.5, 0.8, 1.0, 1.5, 2.0, 3.0, 5.0, 10.0] def __init__(self): super().__init__() def step(self, dt): position = getattr(self.target, 'position', (0, 0)) speed = getattr(self.target, 'speed', (0, 0)) force = getattr(self.target, 'force', 10000) mu_k = getattr(self.target, 'mu_k', 9) scale_request_idx = getattr(self.target, 'scale_request_idx', 3) # Handle Acceleration speed = (speed[0] + (keyboard_state[key.RIGHT] - keyboard_state[key.LEFT]) * dt * force, speed[1] + (keyboard_state[key.UP] - keyboard_state[key.DOWN]) * dt * force) # Handle Damping ds = (-mu_k*speed[0]*dt, -mu_k*speed[1]*dt) speed = (speed[0]+ds[0] if abs(ds[0]) < abs(speed[0]) else 0, speed[1]+ds[1] if abs(ds[1]) < abs(speed[1]) else 0) # Update position and speed self.target.speed = speed self.target.position = (position[0] + speed[0]*dt, position[1] + speed[1]*dt) if scroller := getattr(self.target, 'scroller'): scroller.set_focus(self.target.x, self.target.y) scroller.scale += 5*(self.scale_levels[scale_request_idx] - scroller.scale)*dt # Keep object in bounds as calculated by the scroller if self.target.x != scroller.restricted_fx: self.target.position = (scroller.restricted_fx, self.target.position[1]) self.target.speed = (0.0, self.target.speed[1]) if self.target.y != scroller.restricted_fy: self.target.position = (self.target.position[0], scroller.restricted_fy) self.target.speed = (self.target.speed[1], 0.0) class RTSCamera(cocos.layer.ScrollingManager): def __init__(self): pass def init(self): super().__init__() self.cam = cocos.cocosnode.CocosNode() self.cam.scroller = self self.cam_layer = cocos.layer.ScrollableLayer() self.cam_layer.add(self.cam) self.cam_motion = RTSCameraMotion() self.cam.do(self.cam_motion) self.add(self.cam_layer) self.overlay_layer = cocos.layer.ScrollableLayer() self.add(self.overlay_layer, z=1) @property def cam_position(self): return self.cam.position @cam_position.setter def cam_position(self, new_position): self.cam.position = new_position def zoom(self, delta): scale_request_idx_new = getattr(self.cam, 'scale_request_idx', 3) + delta if 0 <= scale_request_idx_new < len(self.cam_motion.scale_levels): self.cam.scale_request_idx = scale_request_idx_new camera = RTSCamera()