Peoplemon  0.1.0
Peoplemon 3 game source documentation
Rain.cpp
Go to the documentation of this file.
1 #include "Rain.hpp"
2 
3 #include <BLIB/Cameras/2D/Camera2D.hpp>
4 #include <BLIB/Particles.hpp>
5 #include <Core/Maps/Map.hpp>
6 #include <Core/Properties.hpp>
7 #include <Core/Resources.hpp>
8 
9 namespace
10 {
11 constexpr float SpawnRate = 250.f;
12 constexpr float SplashTime = -0.15f;
13 constexpr float TransTime = -0.3f;
14 constexpr float DeadTime = -0.4f;
15 constexpr float StopTime = 4.f;
16 constexpr float StopSpeed = 1.f / StopTime;
17 constexpr float RespawnDelay = 2.f;
18 
19 std::size_t deadCount = 0;
20 } // namespace
21 
22 namespace core
23 {
24 namespace map
25 {
26 namespace weather
27 {
28 namespace rain
29 {
30 struct Raindrop {
31  glm::vec2 pos;
32  float height;
33 
34  Raindrop() = default;
35 
36  Raindrop(const sf::FloatRect& area) {
37  pos.x = bl::util::Random::get<float>(area.left - 300.f, area.left + area.width + 300.f);
38  pos.y = bl::util::Random::get<float>(area.top - 300.f, area.top + area.height + 300.f);
39  height = bl::util::Random::get<float>(120.f, 180.f);
40  }
41 };
42 
43 struct GpuRaindrop {
44  glm::vec2 pos;
45  std::uint32_t state; // 0 = air, 1 = splash1, 2 = splash2
46  float height;
47 
48  GpuRaindrop() = default;
49 
50  GpuRaindrop& operator=(const Raindrop& drop) {
51  pos = drop.pos;
52  state = drop.height >= 0.f ? 0 : (drop.height >= SplashTime ? 1 : 2);
53  height = drop.height;
54  return *this;
55  }
56 };
57 
58 struct alignas(8) GlobalShaderInfo {
59  struct alignas(8) ModeInfo {
60  glm::vec2 textureCenter;
61  std::uint32_t textureId;
62  float radius;
63  };
64 
65  alignas(8) ModeInfo info[3];
66  float rotation;
67 };
68 } // namespace rain
69 } // namespace weather
70 } // namespace map
71 } // namespace core
72 
73 namespace bl
74 {
75 namespace pcl
76 {
80 
81 template<>
82 struct RenderConfigMap<Raindrop> {
83  static constexpr std::uint32_t PipelineId = core::Properties::RaindropPipelineId;
84  static constexpr bool ContainsTransparency = true;
85 
86  static constexpr bool CreateRenderPipeline = true;
87 
88  static constexpr std::initializer_list<std::uint32_t> RenderPassIds =
89  bl::pcl::RenderConfigDefaults<Raindrop>::RenderPassIds;
90 
93  bl::pcl::RenderConfigDescriptorList<bl::rc::ds::TexturePoolFactory,
94  bl::rc::ds::Scene2DFactory,
95  bl::pcl::DescriptorSetFactory<Raindrop, GpuRaindrop>>;
96 
97  static constexpr bool EnableDepthTesting = true;
98  static constexpr VkPrimitiveTopology Topology = VK_PRIMITIVE_TOPOLOGY_POINT_LIST;
99  static constexpr const char* VertexShader = "Resources/Shaders/Particles/raindrop.vert.spv";
100  static constexpr const char* FragmentShader =
101  bl::rc::Config::ShaderIds::Fragment2DRotatedParticle;
102 };
103 } // namespace pcl
104 } // namespace bl
105 
106 namespace core
107 {
108 namespace map
109 {
110 namespace weather
111 {
112 namespace rain
113 {
114 class GravityAffector : public bl::pcl::Affector<Raindrop> {
115 public:
116  GravityAffector(const glm::vec2& vel, float fallVel)
117  : vel(vel)
118  , fallVel(fallVel) {}
119 
120  virtual ~GravityAffector() = default;
121 
122  virtual void update(Proxy& proxy, float dt, float) override {
123  for (Raindrop& drop : proxy.particles()) {
124  if (drop.height > 0.f) {
125  drop.pos += vel * dt;
126  drop.height -= fallVel * dt;
127  if (drop.height < 0.f) { drop.height = 0.f; }
128  }
129  else { drop.height -= dt; }
130  }
131  }
132 
133 private:
134  const glm::vec2 vel;
135  const float fallVel;
136 };
137 
138 class TimeSink : public bl::pcl::Sink<Raindrop> {
139 public:
141  : time(0.f) {}
142 
143  virtual ~TimeSink() = default;
144 
145  virtual void update(Proxy& proxy, std::span<Raindrop> particles, float dt, float) override {
146  time += dt;
147  for (Raindrop& drop : particles) {
148  if (drop.height <= DeadTime) {
149  proxy.destroy(drop);
150  if (time >= RespawnDelay) { ++deadCount; }
151  }
152  }
153  }
154 
155 private:
156  float time;
157 };
158 
159 class TimeEmitter : public bl::pcl::Emitter<Raindrop> {
160 public:
161  TimeEmitter(bl::rc::RenderTarget& observer, std::size_t target)
162  : observer(observer)
163  , target(target)
164  , residual(0.f) {}
165 
166  virtual ~TimeEmitter() = default;
167 
168  void setTarget(std::size_t t) { target = t; }
169 
170  virtual void update(Proxy& proxy, float dt, float) override {
171  const std::size_t current = proxy.getManager().getParticleCount();
172  if (current < target) {
173  residual += SpawnRate * dt;
174  if (residual >= 1.f || deadCount > 0) {
175  const std::size_t maxSpawn = target - current;
176  const std::size_t toSpawn =
177  std::min(static_cast<std::size_t>(std::floor(residual)) + deadCount, maxSpawn);
178  residual -= static_cast<float>(toSpawn);
179 
180  bl::cam::Camera2D* cam = observer.getCurrentCamera<bl::cam::Camera2D>();
181  if (!cam) { return; }
182  const sf::FloatRect area = cam->getVisibleArea();
183  for (std::size_t i = 0; i < toSpawn; ++i) { proxy.emit(area); }
184  }
185  }
186  }
187 
188 private:
189  bl::rc::RenderTarget& observer;
190  std::size_t target;
191  float residual;
192 };
193 
194 } // namespace rain
195 
196 Rain::Rain(bool hard, bool canThunder)
197 : engine(nullptr)
198 , particles(nullptr)
199 , _type(hard ? (canThunder ? Weather::HardRainThunder : Weather::HardRain) :
200  (canThunder ? Weather::LightRainThunder : Weather::LightRain))
201 , targetParticleCount(hard ? Properties::HardRainParticleCount() :
202  Properties::LightRainParticleCount())
203 , velocity(hard ? glm::vec2{-90.f, 30.f} : glm::vec2{0.f, 0.f})
204 , fallSpeed(hard ? 740.f : 500.f)
205 , rotation(bl::math::degreesToRadians(hard ? 45.f : 15.f))
206 , stopFactor(-1.f)
207 , thunder(canThunder, hard) {
208  rainSoundHandle = bl::audio::AudioSystem::getOrLoadSound(
210 }
211 
213  stop();
214  if (engine) { engine->particleSystem().removeUniqueSystem<rain::Raindrop>(); }
215  deadCount = 0;
216 }
217 
218 Weather::Type Rain::type() const { return _type; }
219 
220 void Rain::start(bl::engine::Engine& e, bl::rc::RenderTarget& renderTarget, Map& map) {
221  engine = &e;
222 
223  particles = &e.particleSystem().getUniqueSystem<rain::Raindrop>();
224 
225  const auto sampler = e.renderer().vulkanState().samplerCache.noFilterBorderClamped();
226  auto& tpool = e.renderer().texturePool();
227  dropTxtr = tpool.getOrLoadTexture(Properties::RainDropFile(), sampler);
228  splash1Txtr = tpool.getOrLoadTexture(Properties::RainSplash1File(), sampler);
229  splash2Txtr = tpool.getOrLoadTexture(Properties::RainSplash2File(), sampler);
230 
231  const bl::rc::res::TextureRef* textures[] = {&dropTxtr, &splash1Txtr, &splash2Txtr};
232  for (unsigned int i = 0; i < 3; ++i) {
233  auto& tex = *textures[i];
234  auto& info = particles->getRenderer().getGlobals().info[i];
235 
236  sf::FloatRect bounds(0.f, 0.f, tex->size().x, tex->size().y);
237  sf::Transform transform;
238  transform.rotate(bl::math::radiansToDegrees(rotation));
239  bounds = transform.transformRect(bounds);
240  const glm::vec2 rotSize(bounds.width, bounds.height);
241 
242  info.textureId = tex.id();
243  info.textureCenter = tex->normalizeAndConvertCoord(tex->size() * 0.5f);
244  info.radius = glm::length(glm::vec2(bounds.width, bounds.height)) * 0.5f;
245  }
246  particles->getRenderer().getGlobals().rotation = rotation;
247 
248  emitter = particles->addEmitter<rain::TimeEmitter>(renderTarget, targetParticleCount);
249  particles->addAffector<rain::GravityAffector>(velocity, fallSpeed);
250  particles->addSink<rain::TimeSink>();
251  particles->addToScene(renderTarget.getCurrentScene());
252  particles->getRenderer().getComponent()->vertexBuffer.vertices()[0].pos.z = map.getMinDepth();
253 
254  bl::audio::AudioSystem::playSound(rainSoundHandle, 1.5f, true);
255 }
256 
257 void Rain::stop() {
258  stopFactor = 0.f;
259  bl::audio::AudioSystem::stopSound(rainSoundHandle, StopTime + 0.5f);
260  thunder.stop();
261 }
262 
263 bool Rain::stopped() const { return particles && particles->getParticleCount() == 0; }
264 
265 void Rain::update(float dt) {
266  thunder.update(dt);
267 
268  if (stopFactor >= 0.f) {
269  stopFactor = std::min(stopFactor + StopSpeed * dt, 1.f);
270  emitter->setTarget(
271  targetParticleCount -
272  static_cast<std::size_t>(static_cast<float>(targetParticleCount) * stopFactor));
273  if (stopFactor >= 1.f) {
274  stopFactor = -1.f;
275  particles->removeAllEmitters();
276  }
277  }
278 }
279 
280 } // namespace weather
281 } // namespace map
282 } // namespace core
Core classes and functionality for both the editor and game.
core::map::weather::rain::GpuRaindrop GpuRaindrop
Definition: Rain.cpp:78
core::map::weather::fog::GlobalShaderInfo GlobalShaderInfo
Definition: Fog.cpp:79
core::map::weather::rain::Raindrop Raindrop
Definition: Rain.cpp:77
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
Parent weather system for maps. Manages active weather.
Definition: Weather.hpp:32
Type
The type of weather.
Definition: Weather.hpp:38
Wrapper around bl::engine::Configuration. Provides application configuration in variables that may be...
Definition: Properties.hpp:28
static const std::string & RainSplash2File()
Definition: Properties.cpp:395
static constexpr std::uint32_t RaindropPipelineId
Definition: Properties.hpp:136
static const std::string & LightRainSoundFile()
Definition: Properties.cpp:371
static const std::string & HardRainSoundFile()
Definition: Properties.cpp:377
static const std::string & RainSplash1File()
Definition: Properties.cpp:389
static const std::string & RainDropFile()
Definition: Properties.cpp:383
Raindrop(const sf::FloatRect &area)
Definition: Rain.cpp:36
GpuRaindrop & operator=(const Raindrop &drop)
Definition: Rain.cpp:50
bl::pcl::RenderConfigDescriptorList< bl::rc::ds::TexturePoolFactory, bl::rc::ds::Scene2DFactory, bl::pcl::DescriptorSetFactory< Raindrop, GpuRaindrop > > DescriptorSets
Definition: Rain.cpp:95
GravityAffector(const glm::vec2 &vel, float fallVel)
Definition: Rain.cpp:116
virtual void update(Proxy &proxy, float dt, float) override
Definition: Rain.cpp:122
virtual void update(Proxy &proxy, std::span< Raindrop > particles, float dt, float) override
Definition: Rain.cpp:145
void setTarget(std::size_t t)
Definition: Rain.cpp:168
TimeEmitter(bl::rc::RenderTarget &observer, std::size_t target)
Definition: Rain.cpp:161
virtual void update(Proxy &proxy, float dt, float) override
Definition: Rain.cpp:170
virtual void stop() override
Stop the rain.
Definition: Rain.cpp:257
virtual bool stopped() const override
Returns true when all rain is fallen after stop() is called.
Definition: Rain.cpp:263
virtual void start(bl::engine::Engine &engine, bl::rc::RenderTarget &renderTarget, Map &map) override
Start the rain.
Definition: Rain.cpp:220
virtual Weather::Type type() const override
One of LightRain, LightRainThunder, HardRain, or HardRainThunder.
Definition: Rain.cpp:218
Rain(bool hard, bool thunder)
Construct a new Rain system.
Definition: Rain.cpp:196
virtual ~Rain()
Destroy the Rain.
Definition: Rain.cpp:212
virtual void update(float dt) override
Updates the rain.
Definition: Rain.cpp:265
void stop()
Prevents further thunder and fades out current strike if present.
Definition: Thunder.cpp:42
void update(float dt)
Update the thunder.
Definition: Thunder.cpp:44