switch to ECS architecture

This commit is contained in:
2026-05-22 20:31:39 +02:00
parent c18c4e4804
commit ca07cbaf0e
34 changed files with 1943 additions and 2074 deletions

View File

@@ -20,7 +20,7 @@
#include "Building.h"
#include "BuildingSystem.h"
#include "BeltSystem.h"
#include "Scrap.h"
#include "EcsComponents.h"
#include "ScrapSystem.h"
#include "Ship.h"
#include "ShipSystem.h"
@@ -55,11 +55,11 @@ Rotation rotateCounterClockwise(Rotation r)
return Rotation::East;
}
ShipRole shipRole(const Ship& ship)
ShipRole shipRoleFromComponents(bool isEnemy, bool hasCargo, bool hasRepairTool)
{
if (ship.isEnemy) { return ShipRole::Enemy; }
if (ship.cargo.has_value()) { return ShipRole::Salvage; }
if (ship.repairTool.has_value()) { return ShipRole::Repair; }
if (isEnemy) { return ShipRole::Enemy; }
if (hasCargo) { return ShipRole::Salvage; }
if (hasRepairTool){ return ShipRole::Repair; }
return ShipRole::PlayerCombat;
}
@@ -160,11 +160,11 @@ void GameWorldView::onFrame()
for (const FireEvent& fe : fires)
{
float maxRadius = 0.125f;
const Building* tBld = m_sim->buildings().findBuilding(fe.target);
if (tBld)
if (m_sim->admin().isValid(fe.target)
&& m_sim->admin().hasAll<StationBody>(fe.target))
{
const int shorter = std::min(tBld->footprint.width(),
tBld->footprint.height());
const StationBody& sb = m_sim->admin().get<StationBody>(fe.target);
const int shorter = std::min(sb.footprint.width(), sb.footprint.height());
maxRadius = shorter / 2.0f;
}
@@ -443,21 +443,13 @@ EntityId GameWorldView::siteAtTile(QPoint tile) const
}
std::optional<QVector2D> GameWorldView::entityPosition(EntityId id) const
std::optional<QVector2D> GameWorldView::entityPosition(entt::entity entity) const
{
const Ship* ship = m_sim->ships().findShip(id);
if (ship)
if (!m_sim->admin().isValid(entity) || !m_sim->admin().hasAll<Position>(entity))
{
return ship->position;
return std::nullopt;
}
const Building* bldg = m_sim->buildings().findBuilding(id);
if (bldg)
{
return QVector2D(
bldg->anchor.x() + bldg->footprint.width() * 0.5f,
bldg->anchor.y() + bldg->footprint.height() * 0.5f);
}
return std::nullopt;
return m_sim->admin().get<Position>(entity).value;
}
void GameWorldView::stepSpeed(int delta)
@@ -790,7 +782,7 @@ void GameWorldView::drawBeltItems(QPainter& painter)
void GameWorldView::drawScrap(QPainter& painter)
{
const float r = tilePx() * 0.2f;
for (const Scrap& scrap : m_sim->scraps().allScraps())
for (const ScrapInfo& scrap : m_sim->scraps().allScrapInfo())
{
const QPointF center = worldToWidget(scrap.position);
painter.setBrush(QColor(128, 110, 90));
@@ -802,52 +794,58 @@ void GameWorldView::drawScrap(QPainter& painter)
void GameWorldView::drawShips(QPainter& painter)
{
for (const Ship& ship : m_sim->ships().allShips())
{
const ShipRole role = shipRole(ship);
const std::map<ShipRole, ShipVisuals>::const_iterator it =
m_visuals->ships.find(role);
if (it == m_visuals->ships.end()) { continue; }
m_sim->admin().forEach<ShipIdentity, Position, Facing, Faction>(
[&](entt::entity e, const ShipIdentity& /*si*/, const Position& pos,
const Facing& facing, const Faction& fac)
{
const bool hasCargo = m_sim->admin().hasAll<SalvageCargo>(e);
const bool hasRepair = m_sim->admin().hasAll<RepairTool>(e);
const ShipRole role = shipRoleFromComponents(fac.isEnemy, hasCargo, hasRepair);
const std::map<ShipRole, ShipVisuals>::const_iterator it =
m_visuals->ships.find(role);
if (it == m_visuals->ships.end()) { return; }
const QPointF center = worldToWidget(ship.position);
const QVector2D dir(std::cos(ship.facing), std::sin(ship.facing));
const QVector2D perp(-dir.y(), dir.x());
const QPointF center = worldToWidget(pos.value);
const QVector2D dir(std::cos(facing.radians), std::sin(facing.radians));
const QVector2D perp(-dir.y(), dir.x());
const float fwd = tilePx() * 0.45f;
const float side = tilePx() * 0.25f;
const float fwd = tilePx() * 0.45f;
const float side = tilePx() * 0.25f;
QPolygonF tri;
tri << QPointF(center.x() + static_cast<qreal>(dir.x() * fwd),
center.y() + static_cast<qreal>(dir.y() * fwd))
<< QPointF(center.x() + static_cast<qreal>(perp.x() * side - dir.x() * side),
center.y() + static_cast<qreal>(perp.y() * side - dir.y() * side))
<< QPointF(center.x() + static_cast<qreal>(-perp.x() * side - dir.x() * side),
center.y() + static_cast<qreal>(-perp.y() * side - dir.y() * side));
QPolygonF tri;
tri << QPointF(center.x() + static_cast<qreal>(dir.x() * fwd),
center.y() + static_cast<qreal>(dir.y() * fwd))
<< QPointF(center.x() + static_cast<qreal>(perp.x() * side - dir.x() * side),
center.y() + static_cast<qreal>(perp.y() * side - dir.y() * side))
<< QPointF(center.x() + static_cast<qreal>(-perp.x() * side - dir.x() * side),
center.y() + static_cast<qreal>(-perp.y() * side - dir.y() * side));
painter.setPen(QPen(it->second.outline, 1));
painter.setBrush(it->second.fill);
painter.drawPolygon(tri);
}
painter.setPen(QPen(it->second.outline, 1));
painter.setBrush(it->second.fill);
painter.drawPolygon(tri);
});
}
void GameWorldView::drawDebugSensorRanges(QPainter& painter)
{
painter.setBrush(Qt::NoBrush);
for (const Ship& ship : m_sim->ships().allShips())
{
const ShipRole role = shipRole(ship);
const std::map<ShipRole, ShipVisuals>::const_iterator it =
m_visuals->ships.find(role);
if (it == m_visuals->ships.end()) { continue; }
m_sim->admin().forEach<ShipIdentity, Position, Facing, Faction, SensorRange>(
[&](entt::entity e, const ShipIdentity& /*si*/, const Position& pos,
const Facing& /*facing*/, const Faction& fac, const SensorRange& sensor)
{
const bool hasCargo = m_sim->admin().hasAll<SalvageCargo>(e);
const bool hasRepair = m_sim->admin().hasAll<RepairTool>(e);
const ShipRole role = shipRoleFromComponents(fac.isEnemy, hasCargo, hasRepair);
const std::map<ShipRole, ShipVisuals>::const_iterator it =
m_visuals->ships.find(role);
if (it == m_visuals->ships.end()) { return; }
const float range = ship.sensorRange;
const QPointF center = worldToWidget(ship.position);
const qreal radiusPx = static_cast<qreal>(range)
* static_cast<qreal>(tilePx());
painter.setPen(QPen(it->second.outline, 1));
painter.drawEllipse(center, radiusPx, radiusPx);
}
const QPointF center = worldToWidget(pos.value);
const qreal radiusPx = static_cast<qreal>(sensor.value)
* static_cast<qreal>(tilePx());
painter.setPen(QPen(it->second.outline, 1));
painter.drawEllipse(center, radiusPx, radiusPx);
});
}
void GameWorldView::drawBeams(QPainter& painter)

View File

@@ -17,6 +17,8 @@
#include "BuildingType.h"
#include "EntityId.h"
#include "FireEvent.h"
#include "entt/entity/entity.hpp"
#include "GameConfig.h"
#include "Rotation.h"
#include "Tick.h"
@@ -109,7 +111,7 @@ private:
void placeBlueprintAtTile(QPoint center);
std::optional<QVector2D> entityPosition(EntityId id) const;
std::optional<QVector2D> entityPosition(entt::entity entity) const;
void stepSpeed(int delta);
void placeAtTile(QPoint tile);