Zappy GUI
C++ graphic client: renderer, camera, network
Loading...
Searching...
No Matches
BroadcastBehavior.cpp
Go to the documentation of this file.
2
3#include <cmath>
4#include <cstdlib>
5#include <vector>
6
7static constexpr float RING_Y = 0.05f;
8static constexpr float JITTER_RANGE = 0.08f;
9
10static inline float frand() { return static_cast<float>(rand()) / static_cast<float>(RAND_MAX); }
11
12BroadcastBehavior::BroadcastBehavior(VisualState& visual, float server_tick_rate, float maxRadius,
13 float mapWidth, float mapHeight)
14 : _visual(visual),
15 _duration(7.0f / server_tick_rate),
16 _maxRadius(maxRadius),
17 _halfW(mapWidth / 2.0f),
18 _halfH(mapHeight / 2.0f)
19{
20 _lines.resize(RING_POINTS);
22
23 // scatter seeds — randomized once at spawn
24 _seeds.resize(SCATTER_COUNT);
25 for (auto& s : _seeds) {
26 s.angleOffset = (frand() - 0.5f) * (2.0f * PI / RING_POINTS) * 0.8f;
27 s.radialJitter = (frand() - 0.5f) * 2.0f * JITTER_RANGE;
28 s.alphaScale = 0.4f + frand() * 0.6f;
29 s.sizeScale = 0.5f + frand() * 1.0f;
30 // blue spectrum: royal blue → cyan → white-blue
31 unsigned char r = static_cast<unsigned char>(frand() * 60);
32 unsigned char g = static_cast<unsigned char>(80 + frand() * 140);
33 unsigned char b = static_cast<unsigned char>(200 + frand() * 55);
34 s.color = {r, g, b, 255};
35 }
36
37 // scatter particles
38 for (int i = 0; i < SCATTER_COUNT; i++) {
39 _particles[i].size = (0.04f + frand() * 0.06f) * 0.8f;
40 _particles[i].active = true;
41 _particles[i].delay = 0.0f;
42 _particles[i].color = _seeds[i].color;
43 _particles[i].alpha = 1.0f;
44 }
45}
46
47static float wrapCoord(float val, float half)
48{
49 float full = half * 2.0f;
50 val = fmodf(val + half, full);
51 if (val < 0.0f) val += full;
52 return val - half;
53}
54
56{
57 _elapsed += dt;
58
59 float t = _elapsed / _duration;
60 float radius = t * _maxRadius;
61 // fade only starts at 80% of the animation
62 float alpha = t < 0.8f ? 1.0f : 1.0f - (t - 0.8f) / 0.2f;
63
64 // ring as line segments — precompute all anchor positions, then build segments
65 Color ringColor = {30, 100, 255, 255};
66 std::vector<Vector3> anchors(RING_POINTS);
67 for (int i = 0; i < RING_POINTS; i++) {
68 float angle = (2.0f * PI * i) / RING_POINTS;
69 anchors[i] = {wrapCoord(_visual.pos.x + radius * cosf(angle), _halfW), RING_Y,
70 wrapCoord(_visual.pos.z + radius * sinf(angle), _halfH)};
71 }
72 for (int i = 0; i < RING_POINTS; i++) {
73 Vector3 a = anchors[i];
74 Vector3 b = anchors[(i + 1) % RING_POINTS];
75 bool seam = fabsf(a.x - b.x) > _halfW || fabsf(a.z - b.z) > _halfH;
76 _lines[i] = {a, b, ringColor, seam ? 0.0f : alpha};
77 }
78
79 // scatter particles
80 for (int i = 0; i < SCATTER_COUNT; i++) {
81 const ScatterSeed& s = _seeds[i];
82 float baseAngle = (2.0f * PI * i) / SCATTER_COUNT;
83 float angle = baseAngle + s.angleOffset;
84 float r = radius + s.radialJitter;
85 float px = wrapCoord(_visual.pos.x + r * cosf(angle), _halfW);
86 float pz = wrapCoord(_visual.pos.z + r * sinf(angle), _halfH);
87 _particles[i].pos = {px, RING_Y + (frand() - 0.5f) * 0.1f, pz};
88 _particles[i].alpha = alpha * s.alphaScale;
89 }
90}
91
93{
94 if (_elapsed < _duration) return false;
95 _particles.clear();
96 _lines.clear();
97 return true;
98}
static float wrapCoord(float val, float half)
static constexpr float RING_Y
static float frand()
static constexpr float JITTER_RANGE
std::vector< Particle > _particles
std::vector< LineSegment > _lines
void update(float dt) override
static constexpr int RING_POINTS
static constexpr int SCATTER_COUNT
bool isDone() const override
Returns true when the behavior has completed and can be removed.
BroadcastBehavior(VisualState &visual, float server_tick_rate, float maxRadius, float mapWidth, float mapHeight)
std::vector< ScatterSeed > _seeds
Visual-only state for an entity, driven by behaviors each frame. Logical state (x,...