Untitled
unknown
python
3 years ago
9.7 kB
5
Indexable
import math import arcade from uuid import uuid4 import pyglet.gl from pyglet.math import Vec2 from src.managers.event_manager import * class ArcadePort(object): def __init__(self, width, height, engine): self.width, self.height = width, height # Strong References self.engine = engine self.event_manager = self.engine.event_manager self.event_manager.register_listener(self) # States self.debug = False # Main Camera self.camera = arcade.Camera(self.width, self.height) self.camera_proj = None self.camera_zoom = 1.0 self.camera_zoom_range = Vec2(0.51, 3) self.center_point = Vec2(self.width / 2, self.height / 2) self.camera_pos = Vec2(-self.width / 2, -self.height / 2) # GUI Camera self.camera_gui = arcade.Camera(self.width, self.height) # Box Dragging Function self.drag_box_position = None self.drag_box_size = None # Camera Dragging Function self.initial_position = None def notify(self, event: Event): """ Notify by the event manager (if the instance was registered) """ # Fetch the current state of the engine. current_state = self.engine.state_machine.peek() if isinstance(event, InitializeEvent): self.initialize() if isinstance(event, TickEvent): self.viewport_draw() if current_state == self.engine.state_machine.STATE_BATTLE_MODE: if isinstance(event, MouseWheelEvent): if self.camera_zoom_range[0] <= self.camera_zoom <= self.camera_zoom_range[1]: self.camera_zoom -= 0.05 * event.wheel_value if self.camera_zoom > self.camera_zoom_range[1]: self.camera_zoom = self.camera_zoom_range[1] if self.camera_zoom < self.camera_zoom_range[0]: self.camera_zoom = self.camera_zoom_range[0] if isinstance(event, InputEvent): if event.symbol == 103: self.debug = not self.debug if event.symbol == 122: if self.camera_zoom > self.camera_zoom_range[0]: self.camera_zoom -= 0.05 if event.symbol == 115: if self.camera_zoom < self.camera_zoom_range[1]: self.camera_zoom += 0.05 if event.symbol == 65363: self.camera_pos = Vec2(self.camera_pos.x + 10, self.camera_pos.y) if event.symbol == 65361: self.camera_pos = Vec2(self.camera_pos.x - 10, self.camera_pos.y) if event.symbol == 65362: self.camera_pos = Vec2(self.camera_pos.x, self.camera_pos.y + 10) if event.symbol == 65364: self.camera_pos = Vec2(self.camera_pos.x, self.camera_pos.y - 10) if isinstance(event, MouseInputEvent): # Left Mouse Click if event.button == 1: if event.drag: if self.drag_box_position is None: self.drag_box_position = Vec2(event.x, event.y) self.drag_box_size = Vec2(self.drag_box_position.x - event.x, self.drag_box_position.y - event.y) # Middle Mouse Button if event.button == 2: if event.drag: if self.initial_position is None: self.initial_position = Vec2(event.x, event.y) # Calculate the delta between the initial position and the current mouse position. movement_delta = Vec2(self.initial_position.x - event.x, self.initial_position.y - event.y) # Update the camera position with the delta. self.camera_pos = Vec2(self.camera_pos.x + movement_delta.x * self.camera_zoom, self.camera_pos.y + movement_delta.y * self.camera_zoom) # Update the initial position self.initial_position = Vec2(event.x, event.y) # Update the box drag if the player is currently dragging it. if self.drag_box_position is not None: self.drag_box_size = Vec2(self.drag_box_position.x - event.x, self.drag_box_position.y - event.y) # If the mouse input is released if isinstance(event, ReleaseMouseEvent): # Reset the drag box if event.button == 1: self.drag_box_position = None self.drag_box_size = None # Reset the camera dragging if event.button == 2: self.initial_position = None def initialize(self): # Initialize the viewport texture. Mandatory for the zoom. size = (int(self.width * self.camera_zoom), int(self.height * self.camera_zoom)) self.internal_texture = arcade.Texture.create_empty(str(uuid4()), size) self.internal_sprite = arcade.Sprite(center_x=self.width / 2, center_y=self.height / 2, texture=self.internal_texture) self.internal_sprite_list = arcade.SpriteList() self.internal_sprite_list.append(self.internal_sprite) def update_internal(self): # Calculate the offset between the current screen and the new one to center the zoom properly. camera_border = Vec2(self.center_point.x - ((self.width * self.camera_zoom) / 2), self.center_point.y - ((self.height * self.camera_zoom) / 2)) # Calculate the project based on the camera world position, the current zoom and the camera borders. self.camera_proj = self.camera_pos.x + math.floor(camera_border.x * 2), self.camera_pos.x + math.floor( (self.width * self.camera_zoom)), \ self.camera_pos.y + math.floor(camera_border.y * 2), self.camera_pos.y + math.floor( (self.height * self.camera_zoom)) # Use the project with the internal_texture and render the arcade.SpriteList() objects. with self.internal_sprite_list.atlas.render_into(self.internal_texture, projection=self.camera_proj) as fbo: # Clear the texture fbo.clear(arcade.color.BLACK) # Draw arcade.SpriteList() for x in range(self.engine.battle_manager.map_size.x): for y in range(self.engine.battle_manager.map_size.y): self.engine.battle_manager.map.tile_map[x, y].sprite.draw(filter=pyglet.gl.GL_NEAREST, pixelated=True) for unit in self.engine.battle_manager.battalions.units: unit.sprite.draw(filter=pyglet.gl.GL_NEAREST, pixelated=True) # Draw outline if the battalion is selected if self.engine.battle_manager.selected_battalion is not None: for unit in self.engine.battle_manager.selected_battalion.units: arcade.draw_rectangle_outline(unit.sprite.center_x, unit.sprite.center_y, 16, 16, arcade.color.RED, 1) if unit.new_position is not None and self.debug: arcade.draw_line(unit.position.x, unit.position.y, unit.new_position.x, unit.new_position.y, arcade.color.GREEN) # --- DEBUG --- # Selection Square if self.debug: self.engine.battle_manager.selection_box_collider.draw() # Cost Field for x in range(self.engine.battle_manager.map_size.x): for y in range(self.engine.battle_manager.map_size.y): arcade.draw_rectangle_outline(x * 32, y * 32, 32, 32, arcade.color.GREEN, 2) text = str(self.engine.battle_manager.map.tile_map[x, y].tile_cost) arcade.draw_text(text, x * 32 - 16, y * 32, arcade.color.RED, 10) def viewport_draw(self): """ Render the screen. """ # This command has to happen before we start drawing. arcade.start_render() # Switch to the main camera self.camera.use() # If the battle manager loaded his files if self.engine.battle_manager.initialized: # Update the internal texture based on the zoom level. self.update_internal() # Draw the internal textures. self.internal_sprite_list.draw() # Switch to the GUI camera self.camera_gui.use() # Draw the GUI arcade.draw_rectangle_filled(self.width / 2, 20, self.width, 40, arcade.color.ALMOND) text = f"Zoom Level: {self.camera_zoom}" arcade.draw_text(text, 10, 10, arcade.color.BLACK_BEAN, 16) # Draw Selection Mouse Box if self.drag_box_size is not None: # Find the center and the w,h based on the position and size of the drag box. center = Vec2(self.drag_box_position.x - self.drag_box_size.x / 2, self.drag_box_position.y - self.drag_box_size.y / 2) arcade.draw_rectangle_outline(center.x, center.y, self.drag_box_size.x, self.drag_box_size.y, arcade.color.BLUE, 2)
Editor is loading...