123 lines
3.4 KiB
Python
123 lines
3.4 KiB
Python
|
# -------------------------------
|
||
|
# Difficult Rocket
|
||
|
# Copyright © 2020-2023 by shenjackyuanjie 3695888@qq.com
|
||
|
# All rights reserved
|
||
|
# -------------------------------
|
||
|
|
||
|
# Huge thanks to pyglet developers
|
||
|
|
||
|
from typing import Tuple, Optional
|
||
|
|
||
|
|
||
|
class Camera:
|
||
|
"""
|
||
|
|
||
|
>>> from pyglet.window import Window
|
||
|
>>> window = Window()
|
||
|
|
||
|
>>> camera = Camera(window)
|
||
|
>>> @window.event
|
||
|
|
||
|
>>> def on_draw():
|
||
|
>>> camera.begin()
|
||
|
>>> window.clear()
|
||
|
>>> camera.end()
|
||
|
|
||
|
"""
|
||
|
def __init__(self,
|
||
|
window,
|
||
|
zoom: Optional[float] = 1.0,
|
||
|
dx: Optional[float] = 1.0,
|
||
|
dy: Optional[float] = 1.0,
|
||
|
min_zoom: Optional[float] = 1.0,
|
||
|
max_zoom: Optional[float] = 1.0) -> None:
|
||
|
self.window = window
|
||
|
self.dx = dx
|
||
|
self.dy = dy
|
||
|
self.zoom = zoom
|
||
|
self.min_zoom = min_zoom
|
||
|
self.max_zoom = max_zoom
|
||
|
|
||
|
def get_view(self):
|
||
|
return self.window.view
|
||
|
|
||
|
@property
|
||
|
def position(self) -> Tuple[float, float]:
|
||
|
return self.dx, self.dy
|
||
|
|
||
|
@position.setter
|
||
|
def position(self, value: Tuple[float, float]):
|
||
|
self.dx, self.dy = value
|
||
|
|
||
|
@property
|
||
|
def zoom_level(self) -> float:
|
||
|
return self.zoom
|
||
|
|
||
|
@zoom_level.setter
|
||
|
def zoom_level(self, value: float) -> None:
|
||
|
self.zoom = min(max(value, self.min_zoom), self.max_zoom)
|
||
|
|
||
|
def begin(self) -> None:
|
||
|
view = self.window.view
|
||
|
x = self.window.width / self.zoom + (self.dx / self.zoom)
|
||
|
y = self.window.height / self.zoom + (self.dy / self.zoom)
|
||
|
|
||
|
view_matrix = view.translate((x * self.zoom, y * self.zoom, 0))
|
||
|
view_matrix = view_matrix.scale((self.zoom, self.zoom, 1))
|
||
|
|
||
|
self.window.view = view_matrix
|
||
|
|
||
|
def end(self) -> None:
|
||
|
view = self.window.view
|
||
|
x = self.window.width / self.zoom + (self.dx / self.zoom)
|
||
|
y = self.window.height / self.zoom + (self.dy / self.zoom)
|
||
|
|
||
|
view_matrix = view.scale((1.0 / self.zoom, 1.0 / self.zoom, 1))
|
||
|
view_matrix = view_matrix.translate((-x * self.zoom, -y * self.zoom, 0))
|
||
|
|
||
|
self.window.view = view_matrix
|
||
|
|
||
|
def __enter__(self):
|
||
|
self.begin()
|
||
|
return self
|
||
|
|
||
|
def __exit__(self, exc_type, exc_val, exc_tb):
|
||
|
self.end()
|
||
|
|
||
|
|
||
|
class CenterCamera(Camera):
|
||
|
"""
|
||
|
A camera that centers the view on the center of the window
|
||
|
|
||
|
>>> from pyglet.window import Window
|
||
|
>>> window = Window()
|
||
|
|
||
|
>>> camera = CenterCamera(window)
|
||
|
>>> @window.event
|
||
|
|
||
|
>>> def on_draw():
|
||
|
>>> camera.begin()
|
||
|
>>> window.clear()
|
||
|
>>> camera.end()
|
||
|
|
||
|
"""
|
||
|
def begin(self) -> None:
|
||
|
view = self.window.view
|
||
|
x = self.window.width / 2.0 / self.zoom + (self.dx / self.zoom)
|
||
|
y = self.window.height / 2.0 / self.zoom + (self.dy / self.zoom)
|
||
|
|
||
|
view_matrix = view.translate((x * self.zoom, y * self.zoom, 0))
|
||
|
view_matrix = view_matrix.scale((self.zoom, self.zoom, 1))
|
||
|
|
||
|
self.window.view = view_matrix
|
||
|
|
||
|
def end(self) -> None:
|
||
|
view = self.window.view
|
||
|
x = self.window.width / 2.0 / self.zoom + (self.dx / self.zoom)
|
||
|
y = self.window.height / 2.0 / self.zoom + (self.dy / self.zoom)
|
||
|
|
||
|
view_matrix = view.scale((1.0 / self.zoom, 1.0 / self.zoom, 1))
|
||
|
view_matrix = view_matrix.translate((-x * self.zoom, -y * self.zoom, 0))
|
||
|
|
||
|
self.window.view = view_matrix
|
||
|
|