Untitled
unknown
python
4 years ago
9.7 kB
7
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...