draw beam wider at the source than at the target
This commit is contained in:
@@ -15,11 +15,13 @@
|
|||||||
#include <QDir>
|
#include <QDir>
|
||||||
#include <QFont>
|
#include <QFont>
|
||||||
#include <QKeyEvent>
|
#include <QKeyEvent>
|
||||||
|
#include <QLinearGradient>
|
||||||
#include <QMessageBox>
|
#include <QMessageBox>
|
||||||
#include <QMouseEvent>
|
#include <QMouseEvent>
|
||||||
#include <QPainter>
|
#include <QPainter>
|
||||||
#include <QPen>
|
#include <QPen>
|
||||||
#include <QPolygonF>
|
#include <QPolygonF>
|
||||||
|
#include <QRadialGradient>
|
||||||
#include <QRegion>
|
#include <QRegion>
|
||||||
#include <QStringList>
|
#include <QStringList>
|
||||||
#include <QTimer>
|
#include <QTimer>
|
||||||
@@ -1487,6 +1489,9 @@ void GameWorldView::drawDebugOverlay(QPainter& painter)
|
|||||||
|
|
||||||
void GameWorldView::drawBeams(QPainter& painter)
|
void GameWorldView::drawBeams(QPainter& painter)
|
||||||
{
|
{
|
||||||
|
const QPainter::RenderHints savedHints = painter.renderHints();
|
||||||
|
painter.setRenderHint(QPainter::Antialiasing, true);
|
||||||
|
|
||||||
for (const ActiveBeam& beam : m_activeBeams)
|
for (const ActiveBeam& beam : m_activeBeams)
|
||||||
{
|
{
|
||||||
const std::optional<QVector2D> shooterPos = entityPosition(beam.event.shooter);
|
const std::optional<QVector2D> shooterPos = entityPosition(beam.event.shooter);
|
||||||
@@ -1500,10 +1505,55 @@ void GameWorldView::drawBeams(QPainter& painter)
|
|||||||
case BeamKind::Repair: color = m_visuals->beams.repairColor; break;
|
case BeamKind::Repair: color = m_visuals->beams.repairColor; break;
|
||||||
case BeamKind::Salvage: color = m_visuals->beams.salvageColor; break;
|
case BeamKind::Salvage: color = m_visuals->beams.salvageColor; break;
|
||||||
}
|
}
|
||||||
painter.setPen(QPen(color, m_visuals->beams.widthPx));
|
|
||||||
painter.drawLine(worldToWidget(*shooterPos),
|
const QPointF s = worldToWidget(*shooterPos);
|
||||||
worldToWidget(*targetPos + beam.targetOffset));
|
const QPointF t = worldToWidget(*targetPos + beam.targetOffset);
|
||||||
|
|
||||||
|
// Unit direction/perpendicular of the beam in widget space. A degenerate
|
||||||
|
// zero-length beam (shooter and target coincide) has no direction to
|
||||||
|
// taper along, so skip it.
|
||||||
|
const QVector2D delta(static_cast<float>(t.x() - s.x()),
|
||||||
|
static_cast<float>(t.y() - s.y()));
|
||||||
|
const float lengthPx = delta.length();
|
||||||
|
if (lengthPx < 0.001f) { continue; }
|
||||||
|
const QVector2D dir = delta / lengthPx;
|
||||||
|
const QVector2D perp(-dir.y(), dir.x());
|
||||||
|
|
||||||
|
// Directional taper: draw the beam as a quad that is wide at the shooter
|
||||||
|
// and narrows to a faint tip at the target, so it reads as an arrow
|
||||||
|
// pointing away from whoever fired it. Without this, a beam strung
|
||||||
|
// between two nearby ships is symmetric and gives no cue which end is the
|
||||||
|
// source (the readability problem this addresses).
|
||||||
|
const float widthPx = std::max(1.0f, static_cast<float>(m_visuals->beams.widthPx));
|
||||||
|
const float baseHalf = widthPx * 1.f;
|
||||||
|
const float tipHalf = widthPx * 0.35f;
|
||||||
|
|
||||||
|
QPolygonF quad;
|
||||||
|
quad << QPointF(s.x() + static_cast<qreal>(perp.x() * baseHalf),
|
||||||
|
s.y() + static_cast<qreal>(perp.y() * baseHalf))
|
||||||
|
<< QPointF(s.x() - static_cast<qreal>(perp.x() * baseHalf),
|
||||||
|
s.y() - static_cast<qreal>(perp.y() * baseHalf))
|
||||||
|
<< QPointF(t.x() - static_cast<qreal>(perp.x() * tipHalf),
|
||||||
|
t.y() - static_cast<qreal>(perp.y() * tipHalf))
|
||||||
|
<< QPointF(t.x() + static_cast<qreal>(perp.x() * tipHalf),
|
||||||
|
t.y() + static_cast<qreal>(perp.y() * tipHalf));
|
||||||
|
|
||||||
|
QColor bright = color;
|
||||||
|
bright.setAlpha(255);
|
||||||
|
QColor faint = color;
|
||||||
|
faint.setAlpha(90);
|
||||||
|
|
||||||
|
QLinearGradient bodyGrad(s, t);
|
||||||
|
bodyGrad.setColorAt(0.0, bright);
|
||||||
|
bodyGrad.setColorAt(1.0, faint);
|
||||||
|
|
||||||
|
painter.setPen(Qt::NoPen);
|
||||||
|
painter.setBrush(bodyGrad);
|
||||||
|
painter.drawPolygon(quad);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
painter.setBrush(Qt::NoBrush);
|
||||||
|
painter.setRenderHints(savedHints);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GameWorldView::drawOverlays(QPainter& painter)
|
void GameWorldView::drawOverlays(QPainter& painter)
|
||||||
|
|||||||
Reference in New Issue
Block a user