diff --git a/src/framework/CMakeLists.txt b/src/framework/CMakeLists.txt index 193fdbb8..6ab577ee 100644 --- a/src/framework/CMakeLists.txt +++ b/src/framework/CMakeLists.txt @@ -143,8 +143,9 @@ SET(framework_SOURCES ${framework_SOURCES} ${CMAKE_CURRENT_LIST_DIR}/graphics/texturemanager.cpp ${CMAKE_CURRENT_LIST_DIR}/graphics/borderimage.cpp ${CMAKE_CURRENT_LIST_DIR}/graphics/image.cpp - ${CMAKE_CURRENT_LIST_DIR}/graphics/particlesmanager.cpp - ${CMAKE_CURRENT_LIST_DIR}/graphics/particlessystem.cpp + ${CMAKE_CURRENT_LIST_DIR}/graphics/particlemanager.cpp + ${CMAKE_CURRENT_LIST_DIR}/graphics/particlesystem.cpp + ${CMAKE_CURRENT_LIST_DIR}/graphics/particleemitter.cpp ${CMAKE_CURRENT_LIST_DIR}/graphics/shader.cpp ${CMAKE_CURRENT_LIST_DIR}/graphics/shaderprogram.cpp ${CMAKE_CURRENT_LIST_DIR}/graphics/paintershaderprogram.cpp @@ -180,4 +181,4 @@ SET(framework_SOURCES ${framework_SOURCES} # framework third party ${CMAKE_CURRENT_LIST_DIR}/thirdparty/apngloader.cpp -) \ No newline at end of file +) diff --git a/src/framework/application.cpp b/src/framework/application.cpp index f0adacd9..7afa00f4 100644 --- a/src/framework/application.cpp +++ b/src/framework/application.cpp @@ -31,7 +31,7 @@ #include #include #include -#include +#include #include #include @@ -209,7 +209,7 @@ void Application::poll() // poll application genareted events g_dispatcher.poll(); - g_particlesManager.update(); + g_particleManager.update(); } void Application::render() @@ -217,7 +217,7 @@ void Application::render() // everything is rendered by UI components g_ui.render(); - g_particlesManager.render(); + g_particleManager.render(); } void Application::resize(const Size& size) diff --git a/src/framework/graphics/particlemanager.cpp b/src/framework/graphics/particlemanager.cpp new file mode 100644 index 00000000..0dd1d1ff --- /dev/null +++ b/src/framework/graphics/particlemanager.cpp @@ -0,0 +1,38 @@ +#include "particlemanager.h" +#include +#include + +ParticleManager g_particleManager; + +bool ParticleManager::load(const std::string& filename) +{ + if(!g_resources.fileExists(filename)) + return false; + + try { + OTMLDocumentPtr doc = OTMLDocument::parse(filename); + for(const OTMLNodePtr& node : doc->children()) { + if(node->tag() == "ParticleSystem") { + ParticleSystemPtr particleSystem = ParticleSystemPtr(new ParticleSystem); + particleSystem->load(node); + m_particlesSystems.push_back(particleSystem); + } + } + return true; + } catch(Exception& e) { + logError("could not load particles: ", e.what()); + return false; + } +} + +void ParticleManager::render() +{ + for(auto it = m_particlesSystems.begin(), end = m_particlesSystems.end(); it != end; ++it) + (*it)->render(); +} + +void ParticleManager::update() +{ + for(auto it = m_particlesSystems.begin(), end = m_particlesSystems.end(); it != end; ++it) + (*it)->update(); +} diff --git a/src/framework/graphics/particlemanager.h b/src/framework/graphics/particlemanager.h new file mode 100644 index 00000000..6b22a03b --- /dev/null +++ b/src/framework/graphics/particlemanager.h @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2010-2011 OTClient + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef PARTICLEMANAGER_H +#define PARTICLEMANAGER_H + +#include "particlesystem.h" + +class ParticleManager { +public: + bool load(const std::string& filename); + + void render(); + void update(); + +private: + std::list m_particlesSystems; +}; + +extern ParticleManager g_particleManager; + +#endif diff --git a/src/framework/graphics/particlesmanager.cpp b/src/framework/graphics/particlesmanager.cpp deleted file mode 100644 index b1af75dc..00000000 --- a/src/framework/graphics/particlesmanager.cpp +++ /dev/null @@ -1,39 +0,0 @@ -#include "particlesmanager.h" -#include -#include - -ParticlesManager g_particlesManager; - -bool ParticlesManager::load(const std::string& filename) -{ - if(!g_resources.fileExists(filename)) - return false; - - try { - OTMLDocumentPtr doc = OTMLDocument::parse(filename); - //for(const OTMLNodePtr& child : doc->children()) - //m_confsMap[child->tag()] = child->value(); - return true; - } catch(Exception& e) { - logError("could not load configurations: ", e.what()); - return false; - } -} - -void ParticlesManager::add(ParticlesSystem particleSystem) -{ - // check it has emitters - m_particlesSystems.push_back(particleSystem); -} - -void ParticlesManager::render() -{ - for(auto it = m_particlesSystems.begin(), end = m_particlesSystems.end(); it != end; ++it) - (*it).render(); -} - -void ParticlesManager::update() -{ - for(auto it = m_particlesSystems.begin(), end = m_particlesSystems.end(); it != end; ++it) - (*it).update(); -} diff --git a/src/framework/graphics/particlesmanager.h b/src/framework/graphics/particlesmanager.h deleted file mode 100644 index e057b4e4..00000000 --- a/src/framework/graphics/particlesmanager.h +++ /dev/null @@ -1,16 +0,0 @@ -#include "particlessystem.h" - -class ParticlesManager { -public: - bool load(const std::string& filename); - - void add(ParticlesSystem particleSystem); - - void render(); - void update(); - -private: - std::list m_particlesSystems; -}; - -extern ParticlesManager g_particlesManager; diff --git a/src/framework/graphics/particlessystem.cpp b/src/framework/graphics/particlessystem.cpp deleted file mode 100644 index 2a60aa1a..00000000 --- a/src/framework/graphics/particlessystem.cpp +++ /dev/null @@ -1,161 +0,0 @@ -#include "particlessystem.h" -#include "graphics.h" -#include -#include -#include - -Particle::Particle(const Rect& rect, float vx, float vy, float ax, float ay, float duration, const Color& color, TexturePtr texture) -{ - m_rect = rect; - m_ix = rect.x(); m_iy = rect.y(); - m_vx = vx; m_vy = vy; - m_ax = ax; m_ay = ay; - m_color = color; - m_texture = texture; - m_duration = duration; - m_startTicks = g_clock.ticks(); - m_finished = false; -} - -Particle::~Particle() -{ - //dump << "deleted"; -} - -void Particle::render() -{ - g_painter.setColor(m_color); - - if(!m_texture) - g_painter.drawFilledRect(m_rect); - else { - //g_painter.setCompositionMode(Painter::CompositionMode_AdditiveSource); - g_painter.drawTexturedRect(m_rect, m_texture); - //g_painter.setCompositionMode(Painter::CompositionMode_SourceOver); - } -} - -void Particle::update() -{ - ticks_t t = g_clock.ticks() - m_startTicks; - - // check if finished - if(m_duration >= 0 && t > m_duration * 1000) { - m_finished = true; - return; - } - - //update position - m_rect.moveTo(m_ix + (m_vx * t / 1000.0) + (m_ax * t*t / (2.0 * 1000 * 1000)), - m_iy + (m_vy * t / 1000.0) + (m_ay * t*t / (2.0 * 1000 * 1000))); -} - -ParticleEmitter::ParticleEmitter(const Point& position, float duration, float burstRate, float burstCount) -{ - m_position = position; - m_duration = duration; - m_burstRate = burstRate; m_burstCount = burstCount; - m_currentBurst = 0; - m_startTicks = g_clock.ticks(); - m_finished = false; - - // particles default configuration. (make them reasonable for user detect missing properties on scripts) - m_pPositionMinRadius = 0; m_pPositionMaxRadius = 3; - m_pPositionMinAngle = -Fw::pi; m_pPositionMaxAngle = Fw::pi; - m_pMinSize = Size(32, 32); m_pMaxSize = Size(32, 32); - m_pMinDuration = 0; m_pMaxDuration = 10; - - m_pMinVelocity = 32; m_pMaxVelocity = 64; - m_pMinVelocityAngle = -Fw::pi; m_pMaxVelocityAngle = Fw::pi; - - m_pMinAcceleration = 32; m_pMaxAcceleration = 64; - m_pMinAccelerationAngle = -Fw::pi; m_pMaxAccelerationAngle = Fw::pi; - - m_pColor = Color(255, 0, 0, 128); - m_pTexture = nullptr; -} - -void ParticleEmitter::render() -{ - for(auto it = m_particles.begin(), end = m_particles.end(); it != end; ++it) - (*it)->render(); -} - -void ParticleEmitter::update() -{ - ticks_t elapsedTicks = g_clock.ticks() - m_startTicks; - - // check if finished - if(m_duration >= 0 && elapsedTicks > m_duration * 1000) { - m_finished = true; - return; - } - - // update particles - for(auto it = m_particles.begin(), end = m_particles.end(); it != end;) { - const ParticlePtr& particle = *it; - if(particle->hasFinished()) { - it = m_particles.erase(it); - continue; - } - particle->update(); - ++it; - } - - // create some particles - m_pTexture = g_textures.getTexture("circle2.png"); // remove this, 'll be parsed on loader - - int currentBurst = elapsedTicks / 1000.0 / m_burstRate + 1; - for(int b = m_currentBurst; b < currentBurst; ++b) { - - // every burst created at same position. - float pRadius = Fw::randomRange(m_pPositionMinRadius, m_pPositionMaxRadius); - float pAngle = Fw::randomRange(m_pPositionMinAngle, m_pPositionMaxAngle); - Point pPosition = Point(pRadius * cos(pAngle), pRadius * sin(pAngle)); - - for(int p = 0; p < m_burstCount; ++p) { - - Size pSize = Size(Fw::randomRange(m_pMinSize.width(), m_pMaxSize.width()), Fw::randomRange(m_pMinSize.height(), m_pMaxSize.height())); - float pDuration = Fw::randomRange(m_pMinDuration, m_pMaxDuration); - - // particles initial velocity - float pVelocity = Fw::randomRange(m_pMinVelocity, m_pMaxVelocity); - float pVelocityAngle = Fw::randomRange(m_pMinVelocityAngle, m_pMaxVelocityAngle); - - // particles initial acceleration - float pAcceleration = Fw::randomRange(m_pMinAcceleration, m_pMaxAcceleration); - float pAccelerationAngle = Fw::randomRange(m_pMinAccelerationAngle, m_pMaxAccelerationAngle); - - m_particles.push_back(ParticlePtr(new Particle(Rect(m_position + pPosition, pSize), - pVelocity * cos(pVelocityAngle), pVelocity * sin(pVelocityAngle), - pAcceleration * cos(pAccelerationAngle), pAcceleration * sin(pAccelerationAngle), - pDuration, m_pColor, m_pTexture))); - } - } - - m_currentBurst = currentBurst; -} - -void ParticlesSystem::add(const ParticleEmitterPtr& emitter) -{ - m_emitters.push_back(emitter); -} - -void ParticlesSystem::render() -{ - for(auto it = m_emitters.begin(), end = m_emitters.end(); it != end; ++it) - (*it)->render(); -} - -void ParticlesSystem::update() -{ - for(auto it = m_emitters.begin(), end = m_emitters.end(); it != end;) { - const ParticleEmitterPtr& emitter = *it; - if(emitter->hasFinished()) { - it = m_emitters.erase(it); - continue; - } - emitter->update(); - ++it; - } -} diff --git a/src/framework/graphics/particlessystem.h b/src/framework/graphics/particlessystem.h deleted file mode 100644 index c3b460c6..00000000 --- a/src/framework/graphics/particlessystem.h +++ /dev/null @@ -1,97 +0,0 @@ -#include -#include - -class Particle { -public: - - Particle(const Rect& rect, float vx, float vy, float ax, float ay, float duration, const Color& color = Color(255, 255, 255), TexturePtr texture = nullptr); - ~Particle(); - - void render(); - void update(); - - bool hasFinished() { return m_finished; } - -private: - Rect m_rect; - Color m_color; - TexturePtr m_texture; - - int m_ix, m_iy; - PointF m_s0, m_v, m_a; - float m_vx, m_vy; - float m_ax, m_ay; - - float m_duration; - ticks_t m_startTicks; - bool m_finished; -}; -typedef std::shared_ptr ParticlePtr; - -class ParticleEmitter { -public: - - ParticleEmitter(const Point& position, float duration, float burstRate, float burstCount); - - void render(); - void update(); - - bool hasFinished() { return m_finished; } - -private: - // self related - Point m_position; - int m_duration; - ticks_t m_startTicks; - bool m_finished; - float m_burstRate, m_burstCount; - int m_currentBurst; - std::list m_particles; - - // particles size - Size m_pMinSize, m_pMaxSize; - - // particles initial position related to emitter position - float m_pPositionMinRadius, m_pPositionMaxRadius; - float m_pPositionMinAngle, m_pPositionMaxAngle; - - // particles initial velocity - float m_pMinVelocity, m_pMaxVelocity; - float m_pMinVelocityAngle, m_pMaxVelocityAngle; - - // particles initial acceleration - float m_pMinAcceleration, m_pMaxAcceleration; - float m_pMinAccelerationAngle, m_pMaxAccelerationAngle; - - // particles duration - float m_pMinDuration, m_pMaxDuration; - - // visual ralated - Color m_pColor; - TexturePtr m_pTexture; -}; -typedef std::shared_ptr ParticleEmitterPtr; - -class Affector { -public: - virtual void update() {} -}; - -class Gravity270Affector : public Affector { -public: - void update() { - // earth gravity is 9.8 m/s². -> in tibia, 32 pixels are equal to 1 meter -> 32 pixels/m -> 9.8 * 32 is gravity constant - } -}; - -class ParticlesSystem { -public: - void add(const ParticleEmitterPtr& emitter); - - void render(); - void update(); - -private: - std::list m_emitters; - std::list m_affectors; -}; diff --git a/src/framework/graphics/particlesystem.cpp b/src/framework/graphics/particlesystem.cpp new file mode 100644 index 00000000..249ce451 --- /dev/null +++ b/src/framework/graphics/particlesystem.cpp @@ -0,0 +1,32 @@ +#include "particlesystem.h" + +bool ParticleSystem::load(const OTMLNodePtr& node) +{ + for(const OTMLNodePtr& childNode : node->children()) { + if(childNode->tag() == "Emitter") { + ParticleEmitterPtr emitter = ParticleEmitterPtr(new ParticleEmitter); + emitter->load(childNode); + m_emitters.push_back(emitter); + } + } + return true; +} + +void ParticleSystem::render() +{ + for(auto it = m_emitters.begin(), end = m_emitters.end(); it != end; ++it) + (*it)->render(); +} + +void ParticleSystem::update() +{ + for(auto it = m_emitters.begin(), end = m_emitters.end(); it != end;) { + const ParticleEmitterPtr& emitter = *it; + if(emitter->hasFinished()) { + it = m_emitters.erase(it); + continue; + } + emitter->update(); + ++it; + } +} diff --git a/src/framework/graphics/particlesystem.h b/src/framework/graphics/particlesystem.h new file mode 100644 index 00000000..e4add03e --- /dev/null +++ b/src/framework/graphics/particlesystem.h @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2010-2011 OTClient + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef PARTICLESYSTEM_H +#define PARTICLESYSTEM_H + +#include "particleemitter.h" + +class Affector { +public: + virtual void update() {} +}; + +class Gravity270Affector : public Affector { +public: + void update() { + // earth gravity is 9.8 m/s². -> in tibia, 32 pixels are equal to 1 meter -> 32 pixels/m -> 9.8 * 32 is gravity constant + } +}; + +class ParticleSystem { +public: + bool load(const OTMLNodePtr& node); + + void render(); + void update(); + +private: + std::list m_emitters; + std::list m_affectors; +}; +typedef std::shared_ptr ParticleSystemPtr; + +#endif diff --git a/src/otclient/net/protocolgameparse.cpp b/src/otclient/net/protocolgameparse.cpp index 5e31fcc6..aac6a603 100644 --- a/src/otclient/net/protocolgameparse.cpp +++ b/src/otclient/net/protocolgameparse.cpp @@ -32,7 +32,7 @@ #include #include #include -#include +#include void ProtocolGame::parseMessage(InputMessage& msg) { @@ -529,12 +529,8 @@ void ProtocolGame::parseMagicEffect(InputMessage& msg) TilePtr tile = g_map.getTile(pos); tile->addEffect(effect); - // test particles - ParticlesSystem particlesSystem; - - particlesSystem.add(ParticleEmitterPtr(new ParticleEmitter(Point(100, 100), -1, 2, 10))); - - g_particlesManager.add(particlesSystem); + // TODO: check if particles effect exists, if not, play standard sprite effect. + g_particleManager.load("particle.otpa"); } void ProtocolGame::parseAnimatedText(InputMessage& msg)