#pragma once #include #include #include #include #include #include #include #include "EventHandler.h" #include "BeamFiredEvent.h" #include "entt/entity/entity.hpp" #include "EntitySelectionChangedEvent.h" #include "Tick.h" #include "TickDriver.h" #include "VisualsConfig.h" #include "WorldCoordinates.h" class ArenaSimulation; class QPainter; class ArenaView : public QOpenGLWidget, public EventHandler { Q_OBJECT public: ArenaView(ArenaSimulation* sim, const VisualsConfig* visuals, QWidget* parent = nullptr); ~ArenaView() override; void setGameSpeed(double multiplier); double getGameSpeed() const; void togglePause(); void stopRendering(); protected: void paintGL() override; void mousePressEvent(QMouseEvent* event) override; void keyPressEvent(QKeyEvent* event) override; private slots: void onFrame(); private: void handleEvent(std::shared_ptr event) override; void drawTiles(QPainter& painter, const WorldCoordinates& coordinates); void drawBuildings(QPainter& painter, const WorldCoordinates& coordinates); void drawStations(QPainter& painter, const WorldCoordinates& coordinates); void drawDebris(QPainter& painter, const WorldCoordinates& coordinates); void drawShips(QPainter& painter, const WorldCoordinates& coordinates); void drawDebugSensorRanges(QPainter& painter, const WorldCoordinates& coordinates); void drawDebugTargetLines(QPainter& painter, const WorldCoordinates& coordinates); void drawBeams(QPainter& painter, const WorldCoordinates& coordinates); // The world <-> widget transform for the current viewport size. The arena // shows the whole world at once and never scrolls, so this fits the arena's // full extent into the widget; like GameWorldView's, it is a per-frame // snapshot rather than cached state. WorldCoordinates getCoordinates() const; std::optional entityPosition(entt::entity entity) const; struct ActiveBeam { BeamFiredEvent event; QVector2D targetOffset; }; // Beam lifetime in game ticks so beams freeze with the simulation when // paused or slowed, instead of fading on wall-clock time (REQ-SHP-FIRING-BEAM). static constexpr Tick kBeamLifetimeTicks = secondsToTicks(0.3); ArenaSimulation* m_sim; const VisualsConfig* m_visuals; TickDriver m_tickDriver; QElapsedTimer m_frameTimer; std::mt19937 m_rng; double m_gameSpeedMultiplier; double m_prevNonZeroSpeed; QTimer* m_renderTimer; std::vector m_activeBeams; bool m_finishedEmitted; std::optional m_selectedEntity; bool m_debugDraw; };