Веб-сайт самохостера Lotigara

summaryrefslogtreecommitdiff
path: root/source/game/StarParticleManager.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'source/game/StarParticleManager.cpp')
-rw-r--r--source/game/StarParticleManager.cpp115
1 files changed, 115 insertions, 0 deletions
diff --git a/source/game/StarParticleManager.cpp b/source/game/StarParticleManager.cpp
new file mode 100644
index 0000000..c19eab6
--- /dev/null
+++ b/source/game/StarParticleManager.cpp
@@ -0,0 +1,115 @@
+#include "StarParticleManager.hpp"
+#include "StarIterator.hpp"
+#include "StarLogging.hpp"
+
+namespace Star {
+
+ParticleManager::ParticleManager(WorldGeometry const& worldGeometry, ClientTileSectorArrayPtr const& tileSectorArray)
+ : m_worldGeometry(worldGeometry), m_undergroundLevel(0.0f), m_tileSectorArray(tileSectorArray) {}
+
+void ParticleManager::add(Particle particle) {
+ m_particles.push_back(move(particle));
+}
+
+void ParticleManager::addParticles(List<Particle> particles) {
+ m_particles.appendAll(move(particles));
+}
+
+size_t ParticleManager::count() const {
+ return m_particles.size();
+}
+
+void ParticleManager::clear() {
+ m_particles.clear();
+}
+
+void ParticleManager::setUndergroundLevel(float undergroundLevel) {
+ m_undergroundLevel = undergroundLevel;
+}
+
+void ParticleManager::update(float dt, RectF const& cullRegion, float wind) {
+ if (!m_tileSectorArray)
+ return;
+
+ auto cullRects = m_worldGeometry.splitRect(cullRegion);
+
+ for (auto& particle : m_particles) {
+ bool inRegion = false;
+ Vec2F worldPos = m_worldGeometry.xwrap(particle.position);
+ for (auto cullRect : cullRects) {
+ if (cullRect.contains(worldPos)) {
+ inRegion = true;
+ break;
+ }
+ }
+ if (!inRegion)
+ continue;
+
+ particle.update(dt, Vec2F(wind, 0));
+ Vec2I pos(particle.position.floor());
+ TileType tiletype;
+ auto const& tile = m_tileSectorArray->tile(pos);
+ if (isSolidColliding(tile.collision))
+ tiletype = TileType::Colliding;
+ else if (tile.liquid.level > 0.5f)
+ tiletype = TileType::Water;
+ else
+ tiletype = TileType::Empty;
+
+ if (particle.collidesForeground && tiletype == TileType::Colliding) {
+ RectF colRect;
+ colRect.setXMax(std::ceil(particle.position[0]));
+ colRect.setXMin(std::floor(particle.position[0]));
+ colRect.setYMax(std::ceil(particle.position[1]));
+ colRect.setYMin(std::floor(particle.position[1]));
+ Line2F colLine(particle.position, particle.position - particle.velocity);
+
+ auto collisionPosition = colRect.edgeIntersection(colLine).point;
+ if (particle.position[0] > colRect.center()[0])
+ collisionPosition[0] += 0.1f;
+ else if (particle.position[0] < colRect.center()[0])
+ collisionPosition[0] -= 0.1f;
+ if (particle.position[1] > colRect.center()[1])
+ collisionPosition[1] += 0.1f;
+ else if (particle.position[1] < colRect.center()[1])
+ collisionPosition[1] -= 0.1f;
+
+ particle.collide(collisionPosition);
+ }
+
+ if (particle.underwaterOnly && tiletype == TileType::Empty)
+ particle.destroy(false);
+
+ if (particle.collidesLiquid && tiletype == TileType::Water)
+ particle.destroy(false);
+
+ if (particle.trail && particle.timeToLive >= 0.0f) {
+ auto trail = particle;
+ trail.trail = false;
+ trail.timeToLive = 0;
+ trail.velocity = {};
+ m_nextParticles.append(move(trail));
+ }
+
+ if (!particle.dead())
+ m_nextParticles.append(move(particle));
+ }
+
+ m_particles.clear();
+ swap(m_particles, m_nextParticles);
+}
+
+List<Particle> const& ParticleManager::particles() const {
+ return m_particles;
+}
+
+List<pair<Vec2F, Vec3B>> ParticleManager::lightSources() const {
+ List<pair<Vec2F, Vec3B>> lsources;
+ for (auto const& particle : m_particles) {
+ if (particle.light != Color::Clear)
+ lsources.append({particle.position, particle.light.toRgb()});
+ }
+ return lsources;
+}
+
+}