96 lines
2.8 KiB
C++
96 lines
2.8 KiB
C++
#pragma once
|
|
|
|
#include <optional>
|
|
#include <random>
|
|
#include <vector>
|
|
|
|
#include <QElapsedTimer>
|
|
#include <QOpenGLWidget>
|
|
#include <QTimer>
|
|
#include <QVector2D>
|
|
|
|
#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<BeamFiredEvent>
|
|
{
|
|
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<const BeamFiredEvent> 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<QVector2D> 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<ActiveBeam> m_activeBeams;
|
|
bool m_finishedEmitted;
|
|
|
|
std::optional<entt::entity> m_selectedEntity;
|
|
|
|
bool m_debugDraw;
|
|
};
|