3 #include <BLIB/Cameras/2D/Camera2D.hpp>
4 #include <BLIB/Particles.hpp>
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;
19 std::size_t deadCount = 0;
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);
84 static constexpr
bool ContainsTransparency =
true;
86 static constexpr
bool CreateRenderPipeline =
true;
88 static constexpr std::initializer_list<std::uint32_t> RenderPassIds =
89 bl::pcl::RenderConfigDefaults<Raindrop>::RenderPassIds;
93 bl::pcl::RenderConfigDescriptorList<bl::rc::ds::TexturePoolFactory,
94 bl::rc::ds::Scene2DFactory,
95 bl::pcl::DescriptorSetFactory<Raindrop, GpuRaindrop>>;
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;
118 , fallVel(fallVel) {}
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; }
129 else { drop.height -= dt; }
145 virtual void update(Proxy& proxy, std::span<Raindrop> particles,
float dt,
float)
override {
148 if (drop.height <= DeadTime) {
150 if (time >= RespawnDelay) { ++deadCount; }
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);
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); }
189 bl::rc::RenderTarget& observer;
199 , _type(hard ? (canThunder ?
Weather::HardRainThunder :
Weather::HardRain) :
201 , targetParticleCount(hard ?
Properties::HardRainParticleCount() :
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))
207 , thunder(canThunder, hard) {
208 rainSoundHandle = bl::audio::AudioSystem::getOrLoadSound(
214 if (engine) { engine->particleSystem().removeUniqueSystem<
rain::Raindrop>(); }
220 void Rain::start(bl::engine::Engine& e, bl::rc::RenderTarget& renderTarget,
Map& map) {
223 particles = &e.particleSystem().getUniqueSystem<
rain::Raindrop>();
225 const auto sampler = e.renderer().vulkanState().samplerCache.noFilterBorderClamped();
226 auto& tpool = e.renderer().texturePool();
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];
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);
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;
246 particles->getRenderer().getGlobals().rotation = rotation;
248 emitter = particles->addEmitter<
rain::TimeEmitter>(renderTarget, targetParticleCount);
251 particles->addToScene(renderTarget.getCurrentScene());
252 particles->getRenderer().getComponent()->vertexBuffer.vertices()[0].pos.z = map.
getMinDepth();
254 bl::audio::AudioSystem::playSound(rainSoundHandle, 1.5f,
true);
259 bl::audio::AudioSystem::stopSound(rainSoundHandle, StopTime + 0.5f);
263 bool Rain::stopped()
const {
return particles && particles->getParticleCount() == 0; }
268 if (stopFactor >= 0.f) {
269 stopFactor = std::min(stopFactor + StopSpeed * dt, 1.f);
271 targetParticleCount -
272 static_cast<std::size_t
>(
static_cast<float>(targetParticleCount) * stopFactor));
273 if (stopFactor >= 1.f) {
275 particles->removeAllEmitters();
Core classes and functionality for both the editor and game.
core::map::weather::rain::GpuRaindrop GpuRaindrop
core::map::weather::fog::GlobalShaderInfo GlobalShaderInfo
core::map::weather::rain::Raindrop Raindrop
The primary map class that represents a usable map in the game.
float getMinDepth() const
Returns the maximum depth possible for this map. Maximum is always 0.f. Minimum is negative,...
Parent weather system for maps. Manages active weather.
Wrapper around bl::engine::Configuration. Provides application configuration in variables that may be...
static const std::string & RainSplash2File()
static constexpr std::uint32_t RaindropPipelineId
static const std::string & LightRainSoundFile()
static const std::string & HardRainSoundFile()
static const std::string & RainSplash1File()
static const std::string & RainDropFile()
Raindrop(const sf::FloatRect &area)
GpuRaindrop & operator=(const Raindrop &drop)
bl::pcl::RenderConfigDescriptorList< bl::rc::ds::TexturePoolFactory, bl::rc::ds::Scene2DFactory, bl::pcl::DescriptorSetFactory< Raindrop, GpuRaindrop > > DescriptorSets
GravityAffector(const glm::vec2 &vel, float fallVel)
virtual void update(Proxy &proxy, float dt, float) override
virtual ~GravityAffector()=default
virtual ~TimeSink()=default
virtual void update(Proxy &proxy, std::span< Raindrop > particles, float dt, float) override
void setTarget(std::size_t t)
TimeEmitter(bl::rc::RenderTarget &observer, std::size_t target)
virtual ~TimeEmitter()=default
virtual void update(Proxy &proxy, float dt, float) override
virtual void stop() override
Stop the rain.
virtual bool stopped() const override
Returns true when all rain is fallen after stop() is called.
virtual void start(bl::engine::Engine &engine, bl::rc::RenderTarget &renderTarget, Map &map) override
Start the rain.
virtual Weather::Type type() const override
One of LightRain, LightRainThunder, HardRain, or HardRainThunder.
Rain(bool hard, bool thunder)
Construct a new Rain system.
virtual ~Rain()
Destroy the Rain.
virtual void update(float dt) override
Updates the rain.
void stop()
Prevents further thunder and fades out current strike if present.
void update(float dt)
Update the thunder.