Peoplemon  0.1.0
Peoplemon 3 game source documentation
Sandstorm.cpp
Go to the documentation of this file.
1 #include "Sandstorm.hpp"
2 
3 #include <BLIB/Cameras/2D/Camera2D.hpp>
4 #include <BLIB/Util/Random.hpp>
5 #include <Core/Properties.hpp>
6 
7 namespace core
8 {
9 namespace map
10 {
11 namespace weather
12 {
13 namespace sandstorm
14 {
15 struct Sand {
16  glm::vec2 pos;
17 
18  Sand() = default;
19 
20  Sand(const glm::vec2& pos)
21  : pos(pos) {}
22 };
23 
24 struct Swirl {
25  glm::vec2 pos;
26  float angle;
28  float scale;
29 
30  Swirl() = default;
31 
32  Swirl(float x, float y)
33  : pos(x, y) {
34  angle = bl::util::Random::get<float>(0.f, 2.f * bl::math::Pi);
35  angularVelocity = bl::math::degreesToRadians(bl::util::Random::get<float>(560.f, 820.f));
36  if (bl::util::Random::chance(1, 2)) { angularVelocity *= -1.f; }
37  scale = bl::util::Random::get<float>(0.75f, 1.2f);
38  }
39 };
40 
41 struct GpuSwirl {
42  glm::vec2 pos;
43  float angle;
44  float scale;
45 
46  GpuSwirl() = default;
47 
48  GpuSwirl& operator=(const Swirl& swirl) {
49  pos = swirl.pos;
50  angle = swirl.angle;
51  scale = swirl.scale;
52  return *this;
53  }
54 };
55 
57  std::uint32_t textureId;
58  glm::vec2 textureCenter;
59  float alpha;
60  float radius;
61 };
62 
63 } // namespace sandstorm
64 } // namespace weather
65 } // namespace map
66 } // namespace core
67 
68 namespace bl
69 {
70 namespace pcl
71 {
76 
77 template<>
78 struct RenderConfigMap<Sand> {
79  static constexpr std::uint32_t PipelineId = core::Properties::SandstormSandPipelineId;
80  static constexpr bool ContainsTransparency = true;
81 
82  static constexpr bool CreateRenderPipeline = true;
83 
84  static constexpr std::initializer_list<std::uint32_t> RenderPassIds =
85  bl::pcl::RenderConfigDefaults<Sand>::RenderPassIds;
86 
89  bl::pcl::RenderConfigDescriptorList<bl::rc::ds::TexturePoolFactory,
90  bl::rc::ds::Scene2DFactory,
91  bl::pcl::DescriptorSetFactory<Sand, Sand>>;
92 
93  static constexpr bool EnableDepthTesting = true;
94  static constexpr VkPrimitiveTopology Topology = VK_PRIMITIVE_TOPOLOGY_POINT_LIST;
95  static constexpr const char* VertexShader = "Resources/Shaders/Particles/sand.vert.spv";
96  static constexpr const char* FragmentShader =
97  bl::rc::Config::ShaderIds::Fragment2DRotatedParticle;
98 };
99 
100 template<>
101 struct RenderConfigMap<Swirl> {
102  static constexpr std::uint32_t PipelineId = core::Properties::SandstormSwirlPipelineId;
103  static constexpr bool ContainsTransparency = true;
104 
105  static constexpr bool CreateRenderPipeline = true;
106 
107  static constexpr std::initializer_list<std::uint32_t> RenderPassIds =
108  bl::pcl::RenderConfigDefaults<Swirl>::RenderPassIds;
109 
112  bl::pcl::RenderConfigDescriptorList<bl::rc::ds::TexturePoolFactory,
113  bl::rc::ds::Scene2DFactory,
114  bl::pcl::DescriptorSetFactory<Swirl, GpuSwirl>>;
115 
116  static constexpr bool EnableDepthTesting = true;
117  static constexpr VkPrimitiveTopology Topology = VK_PRIMITIVE_TOPOLOGY_POINT_LIST;
118  static constexpr const char* VertexShader = "Resources/Shaders/Particles/sandSwirl.vert.spv";
119  static constexpr const char* FragmentShader =
120  bl::rc::Config::ShaderIds::Fragment2DRotatedParticle;
121 };
122 } // namespace pcl
123 } // namespace bl
124 
125 namespace core
126 {
127 namespace map
128 {
129 namespace weather
130 {
131 namespace
132 {
133 constexpr glm::vec2 SandVelocity(-1100.f * 0.8f, 345.f * 0.8f);
134 constexpr glm::vec2 SwirlVelocity(-680.f, 325.f);
135 constexpr float MaxAlpha = 230.f / 256.f;
136 constexpr float SwirlRatio = 0.5f;
137 constexpr float AlphaRate = 85.f / 256.f;
138 constexpr unsigned int SwirlCount = 40;
139 
140 float computeAlpha(float current, float target, float dt) {
141  const float rate = target > current ? AlphaRate : -AlphaRate;
142  const float na = current + rate * dt;
143  if (na < 0.f) return 0.f;
144  if (na > 1.f) return 1.f;
145  if (na > target && target > current) return target;
146  return na;
147 }
148 } // namespace
149 
150 namespace sandstorm
151 {
152 class SandSink : public bl::pcl::Sink<Sand> {
153 public:
155  : clear(false) {}
156 
157  virtual ~SandSink() = default;
158 
159  virtual void update(Proxy& proxy, std::span<Sand> particles, float, float) override {
160  if (clear) {
161  clear = false;
162  for (Sand& p : particles) { proxy.destroy(p); }
163  }
164  }
165 
166  void clearAll() { clear = true; }
167 
168 private:
169  bool clear;
170 };
171 
172 class SandUpdater : public bl::pcl::MetaUpdater<Sand> {
173 public:
174  SandUpdater(bl::rc::RenderTarget& observer, SandSink& sink)
175  : observer(observer)
176  , sink(sink)
177  , prevArea(1.f, 1.f, 1.f, 1.f) {}
178 
179  virtual ~SandUpdater() = default;
180 
181  virtual void update(Proxy& proxy, float, float) override {
182  bl::cam::Camera2D* cam = observer.getCurrentCamera<bl::cam::Camera2D>();
183  if (!cam) { return; }
184  const sf::FloatRect area = cam->getVisibleArea();
185 
186  if (proxy.getManager().getParticleCount() > 0) {
187  const float dx = area.width / prevArea.width;
188  const float dy = area.height / prevArea.height;
189  if (dx >= 1.25f || dy >= 1.25f) {
190  sink.clearAll();
191  prevArea = area;
192  }
193  }
194  else { prevArea = area; }
195  }
196 
197 private:
198  bl::rc::RenderTarget& observer;
199  SandSink& sink;
200  sf::FloatRect prevArea;
201 };
202 
203 float wrapWidth = 800.f;
204 float wrapHeight = 600.f;
205 
206 class SandAffector : public bl::pcl::Affector<Sand> {
207 public:
208  SandAffector(bl::rc::RenderTarget& observer)
209  : observer(observer) {}
210 
211  virtual ~SandAffector() = default;
212 
213  virtual void update(Proxy& proxy, float dt, float) override {
214  bl::cam::Camera2D* cam = observer.getCurrentCamera<bl::cam::Camera2D>();
215  if (!cam) { return; }
216  const sf::FloatRect area = cam->getVisibleArea();
217 
218  const float leftBound = area.left + area.width * 0.5f - wrapWidth * 0.5f;
219  const float rightBound = leftBound + wrapWidth;
220  const float topBound = area.top + area.height * 0.5f - wrapHeight * 0.5f;
221  const float bottomBound = topBound + wrapHeight;
222 
223  for (Sand& s : proxy.particles()) {
224  s.pos += SandVelocity * dt;
225  if (s.pos.x < leftBound) { s.pos.x += wrapWidth; }
226  else if (s.pos.x > rightBound) { s.pos.x -= wrapWidth; }
227  if (s.pos.y < topBound) { s.pos.y += wrapHeight; }
228  else if (s.pos.y > bottomBound) { s.pos.y -= wrapHeight; }
229  }
230  }
231 
232 private:
233  bl::rc::RenderTarget& observer;
234 };
235 
236 class SandEmitter : public bl::pcl::Emitter<Sand> {
237 public:
238  SandEmitter(bl::rc::RenderTarget& observer, glm::vec2 txtrSize)
239  : observer(observer)
240  , txtrHalfSize(txtrSize / 1.6f) {}
241 
242  virtual ~SandEmitter() = default;
243 
244  virtual void update(Proxy& proxy, float, float) override {
245  if (proxy.getManager().getParticleCount() == 0) {
246  bl::cam::Camera2D* cam = observer.getCurrentCamera<bl::cam::Camera2D>();
247  if (!cam) { return; }
248  const sf::FloatRect area = cam->getVisibleArea();
249 
250  const unsigned int width = std::ceil(area.width * 2.f / txtrHalfSize.x);
251  const unsigned int height = std::ceil(area.height * 2.f / txtrHalfSize.y);
252 
253  wrapWidth = static_cast<float>(width) * txtrHalfSize.x;
254  wrapHeight = static_cast<float>(height) * txtrHalfSize.y;
255  const glm::vec2 corner(area.left + area.width * 0.5f - wrapWidth * 0.5f,
256  area.top + area.height * 0.5f - wrapHeight * 0.5f);
257 
258  for (unsigned int x = 0; x < width; ++x) {
259  for (unsigned int y = 0; y < height; ++y) {
260  const glm::vec2 pos(x, y);
261  proxy.emit(corner + txtrHalfSize * pos);
262  }
263  }
264  }
265  }
266 
267 private:
268  bl::rc::RenderTarget& observer;
269  const glm::vec2 txtrHalfSize;
270 };
271 
272 class SwirlAffector : public bl::pcl::Affector<Swirl> {
273 public:
274  SwirlAffector(bl::rc::RenderTarget& observer)
275  : observer(observer) {}
276 
277  virtual ~SwirlAffector() = default;
278 
279  virtual void update(Proxy& proxy, float dt, float) override {
280  bl::cam::Camera2D* cam = observer.getCurrentCamera<bl::cam::Camera2D>();
281  if (!cam) { return; }
282  const sf::FloatRect area = cam->getVisibleArea();
283 
284  const float leftBound = area.left - area.width * 0.5f;
285  const float rightBound = leftBound + area.width * 2.f;
286  const float topBound = area.top - area.height * 0.5f;
287  const float bottomBound = topBound + area.height * 2.f;
288 
289  for (Swirl& s : proxy.particles()) {
290  s.pos += SwirlVelocity * dt;
291  s.angle += s.angularVelocity * dt;
292 
293  if (s.pos.x < leftBound || s.pos.y > bottomBound) {
294  s = Swirl(bl::util::Random::get<float>(rightBound - 100.f, rightBound),
295  bl::util::Random::get<float>(topBound, bottomBound - 100.f));
296  }
297  }
298  }
299 
300 private:
301  bl::rc::RenderTarget& observer;
302 };
303 
304 class SwirlEmitter : public bl::pcl::Emitter<Swirl> {
305 public:
306  SwirlEmitter(bl::rc::RenderTarget& observer, glm::vec2 txtrSize)
307  : observer(observer)
308  , txtrHalfSize(txtrSize / 1.6f) {}
309 
310  virtual ~SwirlEmitter() = default;
311 
312  virtual void update(Proxy& proxy, float, float) override {
313  if (proxy.getManager().getParticleCount() == 0) {
314  bl::cam::Camera2D* cam = observer.getCurrentCamera<bl::cam::Camera2D>();
315  if (!cam) { return; }
316  const sf::FloatRect area = cam->getVisibleArea();
317  const glm::vec2 corner(area.left - area.width * 0.5f, area.top - area.height * 0.5f);
318  const glm::vec2 otherCorner(corner + glm::vec2(area.width * 2.f, area.height * 2.f));
319 
320  for (unsigned int i = 0; i < SwirlCount; ++i) {
321  proxy.emit(bl::util::Random::get<float>(corner.x, otherCorner.x),
322  bl::util::Random::get<float>(corner.y, otherCorner.y));
323  }
324  }
325  }
326 
327 private:
328  bl::rc::RenderTarget& observer;
329  const glm::vec2 txtrHalfSize;
330 };
331 } // namespace sandstorm
332 
334 : targetAlpha(0.f)
335 , alpha(0.f) {}
336 
338  if (engine) {
339  engine->particleSystem().removeUniqueSystem<sandstorm::Sand>();
340  engine->particleSystem().removeUniqueSystem<sandstorm::Swirl>();
341  }
342 }
343 
345 
346 void Sandstorm::stop() { targetAlpha = 0; }
347 
348 bool Sandstorm::stopped() const { return sand && sand->getRenderer().getGlobals().alpha <= 0.f; }
349 
350 void Sandstorm::start(bl::engine::Engine& e, bl::rc::RenderTarget& renderTarget, Map& map) {
351  engine = &e;
352  targetAlpha = MaxAlpha;
353  alpha = 0.f;
354 
355  const auto sampler = e.renderer().vulkanState().samplerCache.noFilterBorderClamped();
356  sandTxtr = e.renderer().texturePool().getOrLoadTexture(Properties::SandPatchFile(), sampler);
357  swirlTxtr = e.renderer().texturePool().getOrLoadTexture(Properties::SandSwirlFile(), sampler);
358 
359  // sand
360  sand = &e.particleSystem().getUniqueSystem<sandstorm::Sand>();
361  sandstorm::SandSink* sink = sand->addSink<sandstorm::SandSink>();
362  sand->addUpdater<sandstorm::SandUpdater>(std::ref(renderTarget), std::ref(*sink));
363  sand->addAffector<sandstorm::SandAffector>(renderTarget);
364  sand->addEmitter<sandstorm::SandEmitter>(renderTarget, sandTxtr->size());
365 
366  sand->getRenderer().getGlobals().textureCenter =
367  sandTxtr->normalizeAndConvertCoord(sandTxtr->size() * 0.5f);
368  sand->getRenderer().getGlobals().textureId = sandTxtr.id();
369  sand->getRenderer().getGlobals().radius = glm::length(sandTxtr->size()) * 0.5f;
370 
371  sand->addToScene(renderTarget.getCurrentScene());
372  sand->getRenderer().getComponent()->vertexBuffer.vertices()[0].pos.z = map.getMinDepth() + 0.3f;
373 
374  // swirls
375  swirls = &e.particleSystem().getUniqueSystem<sandstorm::Swirl>();
376  swirls->addAffector<sandstorm::SwirlAffector>(renderTarget);
377  swirls->addEmitter<sandstorm::SwirlEmitter>(renderTarget, sandTxtr->size());
378 
379  swirls->getRenderer().getGlobals().textureCenter =
380  swirlTxtr->normalizeAndConvertCoord(swirlTxtr->size() * 0.5f);
381  swirls->getRenderer().getGlobals().textureId = swirlTxtr.id();
382  swirls->getRenderer().getGlobals().radius = glm::length(swirlTxtr->size()) * 0.5f;
383 
384  swirls->addToScene(renderTarget.getCurrentScene());
385  swirls->getRenderer().getComponent()->vertexBuffer.vertices()[0].pos.z = map.getMinDepth();
386 
387  setAlpha();
388 }
389 
390 void Sandstorm::update(float dt) {
391  if (alpha != targetAlpha) {
392  alpha = computeAlpha(alpha, targetAlpha, dt);
393  setAlpha();
394  }
395 }
396 
397 void Sandstorm::setAlpha() {
398  if (sand) {
399  sand->getRenderer().getGlobals().alpha = alpha;
400  swirls->getRenderer().getGlobals().alpha = alpha * SwirlRatio;
401  }
402 }
403 
404 } // namespace weather
405 } // namespace map
406 } // namespace core
Core classes and functionality for both the editor and game.
core::map::weather::sandstorm::GpuSwirl GpuSwirl
Definition: Sandstorm.cpp:74
core::map::weather::fog::GlobalShaderInfo GlobalShaderInfo
Definition: Fog.cpp:79
core::map::weather::sandstorm::Swirl Swirl
Definition: Sandstorm.cpp:73
core::map::weather::sandstorm::Sand Sand
Definition: Sandstorm.cpp:72
The primary map class that represents a usable map in the game.
Definition: Map.hpp:49
float getMinDepth() const
Returns the maximum depth possible for this map. Maximum is always 0.f. Minimum is negative,...
Definition: Map.cpp:775
Type
The type of weather.
Definition: Weather.hpp:38
@ SandStorm
A sandstorm ravages you.
Definition: Weather.hpp:79
static const std::string & SandSwirlFile()
Definition: Properties.cpp:419
static const std::string & SandPatchFile()
Definition: Properties.cpp:413
static constexpr std::uint32_t SandstormSandPipelineId
Definition: Properties.hpp:139
static constexpr std::uint32_t SandstormSwirlPipelineId
Definition: Properties.hpp:140
Sand(const glm::vec2 &pos)
Definition: Sandstorm.cpp:20
GpuSwirl & operator=(const Swirl &swirl)
Definition: Sandstorm.cpp:48
bl::pcl::RenderConfigDescriptorList< bl::rc::ds::TexturePoolFactory, bl::rc::ds::Scene2DFactory, bl::pcl::DescriptorSetFactory< Sand, Sand > > DescriptorSets
Definition: Sandstorm.cpp:91
bl::pcl::RenderConfigDescriptorList< bl::rc::ds::TexturePoolFactory, bl::rc::ds::Scene2DFactory, bl::pcl::DescriptorSetFactory< Swirl, GpuSwirl > > DescriptorSets
Definition: Sandstorm.cpp:114
virtual void update(Proxy &proxy, std::span< Sand > particles, float, float) override
Definition: Sandstorm.cpp:159
virtual void update(Proxy &proxy, float, float) override
Definition: Sandstorm.cpp:181
SandUpdater(bl::rc::RenderTarget &observer, SandSink &sink)
Definition: Sandstorm.cpp:174
virtual void update(Proxy &proxy, float dt, float) override
Definition: Sandstorm.cpp:213
SandAffector(bl::rc::RenderTarget &observer)
Definition: Sandstorm.cpp:208
virtual void update(Proxy &proxy, float, float) override
Definition: Sandstorm.cpp:244
SandEmitter(bl::rc::RenderTarget &observer, glm::vec2 txtrSize)
Definition: Sandstorm.cpp:238
virtual void update(Proxy &proxy, float dt, float) override
Definition: Sandstorm.cpp:279
SwirlAffector(bl::rc::RenderTarget &observer)
Definition: Sandstorm.cpp:274
virtual void update(Proxy &proxy, float, float) override
Definition: Sandstorm.cpp:312
SwirlEmitter(bl::rc::RenderTarget &observer, glm::vec2 txtrSize)
Definition: Sandstorm.cpp:306
virtual bool stopped() const override
Returns true if the sandstorm is fully stopped, false if stopping.
Definition: Sandstorm.cpp:348
virtual void update(float dt) override
Updates the sandstorm.
Definition: Sandstorm.cpp:390
virtual void start(bl::engine::Engine &engine, bl::rc::RenderTarget &renderTarget, Map &map) override
Starts the sandstorm.
Definition: Sandstorm.cpp:350
Sandstorm()
Creates the sandstorm.
Definition: Sandstorm.cpp:333
virtual void stop() override
Stops the sandstorm.
Definition: Sandstorm.cpp:346
virtual ~Sandstorm()
Destroy the Sandstorm object.
Definition: Sandstorm.cpp:337
virtual Weather::Type type() const override
Returns Sandstorm.
Definition: Sandstorm.cpp:344