Monopoly — Portage moderne 0.1.0
Portage moderne C/C++23 du Monopoly de 1999
Loading...
Searching...
No Matches
BoardLightingController.cpp
Go to the documentation of this file.
2
3#include <algorithm>
4#include <array>
5#include <cmath>
6
8{
9 namespace
10 {
11 constexpr float Pi = 3.14159265358979323846F;
12 constexpr std::array<std::array<std::uint8_t, 3>, 6> PlayerColours{{
13 {{255U, 0U, 0U}},
14 {{ 0U, 0U, 255U}},
15 {{ 60U, 150U, 60U}},
16 {{255U, 255U, 0U}},
17 {{255U, 0U, 255U}},
18 {{255U, 128U, 0U}}
19 }};
20
21 [[nodiscard]] float accelerateInOut(float ratio) noexcept
22 {
23 ratio = std::clamp(ratio, 0.0F, 1.0F);
24 if (ratio < 0.5F)
25 return 0.5F - 0.5F * std::cos(ratio * Pi);
26 return 0.5F + 0.5F * std::sin((ratio - 0.5F) * Pi);
27 }
28
29 [[nodiscard]] std::array<float, 3> lerp3(
30 const std::array<float, 3>& start,
31 const std::array<float, 3>& end, float ratio) noexcept
32 {
33 return {
34 start[0] + (end[0] - start[0]) * ratio,
35 start[1] + (end[1] - start[1]) * ratio,
36 start[2] + (end[2] - start[2]) * ratio};
37 }
38
39 void approach(float& value, float target) noexcept
40 {
41 if (std::fabs(value - target) <= SpotlightColourIncrement)
42 value = target;
43 else if (value > target)
45 else
47 }
48
49 [[nodiscard]] std::array<float, 3> targetColour(
50 std::uint8_t colour) noexcept
51 {
52 constexpr float Magnifier = 0.75F / 255.0F;
53 const auto& rgb = PlayerColours[colour];
54 return {rgb[0] * Magnifier, rgb[1] * Magnifier,
55 rgb[2] * Magnifier};
56 }
57 }
58
60 {
61 lighting_ = {};
62 spotlightActive_ = false;
63 ascendingX_ = true;
64 ascendingZ_ = true;
65 fixedRatio_ = false;
66 fixedRatioValue_ = 0.0F;
67 startTarget_ = {240.0F, 300.0F, 240.0F};
68 endTarget_ = startTarget_;
69 currentTarget_ = startTarget_;
70 currentColour_ = {1.0F, 1.0F, 1.0F};
71 moveStartTick_ = 0;
72 moveEndTick_ = 0;
73 }
74
75 void BoardLightingController::beginSpotlight(std::uint64_t tick) noexcept
76 {
77 spotlightActive_ = true;
78 fixedRatio_ = false;
79 fixedRatioValue_ = 0.0F;
80 startTarget_ = {240.0F, 300.0F, 240.0F};
81 endTarget_ = startTarget_;
82 currentTarget_ = startTarget_;
83 moveStartTick_ = tick;
84 moveEndTick_ = tick;
85 }
86
87 std::array<float, 3> BoardLightingController::interpolatedTarget(
88 std::uint64_t tick) const noexcept
89 {
90 float ratio = fixedRatioValue_;
91 if (!fixedRatio_)
92 {
93 if (moveEndTick_ == moveStartTick_)
94 ratio = 1.0F;
95 else
96 ratio = static_cast<float>(tick - moveStartTick_) /
97 static_cast<float>(moveEndTick_ - moveStartTick_);
98 ratio = accelerateInOut(ratio);
99 }
100 else
101 ratio = std::clamp(ratio, 0.0F, 1.0F);
102 return lerp3(startTarget_, endTarget_, ratio);
103 }
104
105 void BoardLightingController::updateSpotlightMotion(
106 const BoardLightingInputs& inputs) noexcept
107 {
108 for (std::uint64_t t = 0; t < inputs.numberOfTicks; ++t)
109 {
110 const bool idle =
111 inputs.tick > inputs.lastBoardActivityTick + SpotlightIdleDelayTicks &&
112 inputs.board3DOn;
113 if (idle)
114 {
115 fixedRatio_ = false;
116 moveStartTick_ = inputs.tick;
117 moveEndTick_ = inputs.tick;
118 if (ascendingX_)
119 {
120 if (endTarget_[0] < 420.0F)
121 endTarget_[0] += SpotlightIdleIncrement;
122 else
123 ascendingX_ = false;
124 }
125 else if (endTarget_[0] > 0.0F)
126 endTarget_[0] -= SpotlightIdleIncrement;
127 else
128 ascendingX_ = true;
129
130 if (ascendingZ_)
131 {
132 if (endTarget_[2] < 420.0F)
133 endTarget_[2] += SpotlightIdleIncrement;
134 else
135 ascendingZ_ = false;
136 }
137 else if (endTarget_[2] > 0.0F)
138 endTarget_[2] -= SpotlightIdleIncrement;
139 else
140 ascendingZ_ = true;
141 }
142 else if (!inputs.tokenAnimationActive)
143 {
144 if (endTarget_ != inputs.tokenPosition)
145 {
146 startTarget_ = currentTarget_;
147 endTarget_ = inputs.tokenPosition;
148 fixedRatio_ = false;
149 moveStartTick_ = inputs.tick;
150 moveEndTick_ = inputs.tick + SpotlightFocusMoveTicks;
151 }
152 }
153 else
154 {
155 startTarget_ = currentTarget_;
156 endTarget_ = inputs.tokenPosition;
157 fixedRatio_ = true;
158 fixedRatioValue_ = SpotlightFollowRatio;
159 }
160 }
161 currentTarget_ = interpolatedTarget(inputs.tick);
162 }
163
164 void BoardLightingController::updateSpotlightColour(
165 const BoardLightingInputs& inputs) noexcept
166 {
167 const auto target = targetColour(inputs.playerColour);
168 for (std::uint64_t t = 0; t < inputs.numberOfTicks; ++t)
169 for (std::size_t channel = 0; channel < currentColour_.size(); ++channel)
170 approach(currentColour_[channel], target[channel]);
171 }
172
173 std::expected<engine::World3DLighting, std::string>
175 {
176 if (inputs.numberOfTicks == 0)
177 return lighting_;
178
179 const bool commonLightsOn = inputs.game3DOn && inputs.lightingOn;
180 const bool spotlightOn = commonLightsOn && inputs.board3DOn;
181 if (spotlightOn && inputs.playerColour >= PlayerColours.size())
182 return std::unexpected(
183 "board spotlight player colour is outside legacy 0..5 range");
184
185 const float ambient = commonLightsOn ? 0.53F : 0.84F;
186 lighting_.ambient = {ambient, ambient, ambient};
187
189 lighting_.boardReflection.color = {0.75F * 0.35F,
190 0.86F * 0.35F, 0.77F * 0.35F};
191 lighting_.boardReflection.direction = {0.0F, 1.0F, 0.0F};
192 lighting_.sun.enabled = commonLightsOn;
193 lighting_.sun.color = {0.28F, 0.28F, 0.28F};
194 lighting_.sun.direction = {0.0F, -1.0F, 0.0F};
195
196 lighting_.spotlight.enabled = spotlightOn;
197 if (!spotlightOn)
198 {
199 spotlightActive_ = false;
200 return lighting_;
201 }
202 if (!spotlightActive_)
203 beginSpotlight(inputs.tick);
204
205 updateSpotlightMotion(inputs);
206 updateSpotlightColour(inputs);
207 lighting_.spotlight.color = currentColour_;
208 lighting_.spotlight.position = {currentTarget_[0],
209 currentTarget_[1] + 200.0F, currentTarget_[2]};
210 lighting_.spotlight.direction = {0.0F, -1.0F, 0.0F};
211 lighting_.spotlight.attenuation = {0.0F, 1.0F, 0.0F};
212 lighting_.spotlight.range = 300.0F;
213 lighting_.spotlight.falloff = 4.0F;
214 lighting_.spotlight.theta = Pi / 7.0F;
215 lighting_.spotlight.phi = Pi / 2.0F;
216 return lighting_;
217 }
218}
unsigned index
int colour
std::uint16_t value
Definition Timers.cpp:16
data::DataId idle
std::expected< engine::World3DLighting, std::string > tick(const BoardLightingInputs &inputs)
constexpr std::uint64_t SpotlightIdleDelayTicks
constexpr std::uint64_t SpotlightFocusMoveTicks
World3DDirectionalLight boardReflection