From a93a723db62ba2ad445b0fff26be5c51aefcda78 Mon Sep 17 00:00:00 2001 From: Chuck Miller Date: Sun, 3 May 2009 17:11:25 -0400 Subject: Added rotational particles, and added code to show arrows when a player shoots them. --- src/CMakeLists.txt | 2 ++ src/Makefile.am | 2 ++ src/being.cpp | 17 ++++++++++- src/localplayer.h | 2 +- src/particle.cpp | 7 ++++- src/particle.h | 1 - src/particleemitter.cpp | 75 +++++++++++++++++++++++++++++++++++++++++++++ src/particleemitter.h | 1 + src/rotationalparticle.cpp | 76 ++++++++++++++++++++++++++++++++++++++++++++++ src/rotationalparticle.h | 48 +++++++++++++++++++++++++++++ src/simpleanimation.cpp | 15 +++++++++ src/simpleanimation.h | 4 +++ 12 files changed, 246 insertions(+), 4 deletions(-) create mode 100644 src/rotationalparticle.cpp create mode 100644 src/rotationalparticle.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 65ba4d98..299d75f8 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -384,6 +384,8 @@ SET(SRCS position.cpp position.h properties.h + rotationalparticle.cpp + rotationalparticle.h serverinfo.h shopitem.cpp shopitem.h diff --git a/src/Makefile.am b/src/Makefile.am index 21766f34..ad4a0a26 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -337,6 +337,8 @@ tmw_SOURCES = gui/widgets/avatar.cpp \ position.cpp \ position.h \ properties.h \ + rotationalparticle.cpp \ + rotationalparticle.h \ serverinfo.h \ shopitem.cpp \ shopitem.h \ diff --git a/src/being.cpp b/src/being.cpp index d719635b..fc61fbd9 100644 --- a/src/being.cpp +++ b/src/being.cpp @@ -470,8 +470,23 @@ void Being::handleAttack() void Being::handleAttack(Being *victim, int damage, AttackType type) #endif { - setAction(Being::ATTACK); + if (this != player_node) + setAction(Being::ATTACK); #ifdef EATHENA_SUPPORT + if (getType() == PLAYER) + { + if (mEquippedWeapon->getAttackType() == ACTION_ATTACK_BOW) + { + Particle *p = new Particle(NULL); + p->setLifetime(1000); + victim->controlParticle(p); + + Particle *p2 = particleEngine->addEffect("graphics/particles/arrow.particle.xml", mPx, mPy); + p2->setLifetime(900); + p2->setDestination(p, 7, 0); + p2->setDieDistance(8); + } + } mFrame = 0; mWalkTime = tick_time; #endif diff --git a/src/localplayer.h b/src/localplayer.h index 55e4e6f6..e67630b2 100644 --- a/src/localplayer.h +++ b/src/localplayer.h @@ -279,7 +279,7 @@ class LocalPlayer : public Player * @param damage the amount of damage dealt (0 means miss) * @param type the attack type */ - virtual void handleAttack(Being *victim, int damage, AttackType type) {} + //virtual void handleAttack(Being *victim, int damage, AttackType type) {} virtual void handleAttack() {} /** diff --git a/src/particle.cpp b/src/particle.cpp index 78db2a58..42ec84d7 100644 --- a/src/particle.cpp +++ b/src/particle.cpp @@ -31,6 +31,7 @@ #include "map.h" #include "particle.h" #include "particleemitter.h" +#include "rotationalparticle.h" #include "textparticle.h" #include "resources/resourcemanager.h" @@ -222,7 +223,6 @@ bool Particle::update() p = mChildParticles.erase(p); } } - if (!mAlive && mChildParticles.empty() && mAutoDelete) { return false; @@ -280,6 +280,11 @@ Particle *Particle::addEffect(const std::string &particleEffectFile, { newParticle = new AnimationParticle(mMap, node); } + // Rotational + else if ((node = XML::findFirstChildByName(effectChildNode, "rotation"))) + { + newParticle = new RotationalParticle(mMap, node); + } // Image else if ((node = XML::findFirstChildByName(effectChildNode, "image"))) { diff --git a/src/particle.h b/src/particle.h index f3f5571a..52b2dd3c 100644 --- a/src/particle.h +++ b/src/particle.h @@ -267,7 +267,6 @@ class Particle : public Sprite int mFadeIn; /**< Age in game ticks where fading in is finished*/ float mAlpha; /**< Opacity of the graphical representation of the particle */ - private: // generic properties bool mAutoDelete; /**< May the particle request its deletion by the parent particle? */ Map *mMap; /**< Map the particle is on. */ diff --git a/src/particleemitter.cpp b/src/particleemitter.cpp index 25e6ade5..d4a56bfd 100644 --- a/src/particleemitter.cpp +++ b/src/particleemitter.cpp @@ -26,6 +26,7 @@ #include "log.h" #include "particle.h" #include "particleemitter.h" +#include "rotationalparticle.h" #include "resources/image.h" #include "resources/imageset.h" @@ -184,6 +185,74 @@ ParticleEmitter::ParticleEmitter(xmlNodePtr emitterNode, Particle *target, Map * ParticleEmitter newEmitter(propertyNode, mParticleTarget, map); mParticleChildEmitters.push_back(newEmitter); } + else if (xmlStrEqual(propertyNode->name, BAD_CAST "rotation")) + { + ImageSet *imageset = ResourceManager::getInstance()->getImageSet( + XML::getProperty(propertyNode, "imageset", ""), + XML::getProperty(propertyNode, "width", 0), + XML::getProperty(propertyNode, "height", 0) + ); + + // Get animation frames + for_each_xml_child_node(frameNode, propertyNode) + { + int delay = XML::getProperty(frameNode, "delay", 0); + int offsetX = XML::getProperty(frameNode, "offsetX", 0); + int offsetY = XML::getProperty(frameNode, "offsetY", 0); + offsetY -= imageset->getHeight() - 32; + offsetX -= imageset->getWidth() / 2 - 16; + + if (xmlStrEqual(frameNode->name, BAD_CAST "frame")) + { + int index = XML::getProperty(frameNode, "index", -1); + + if (index < 0) + { + logger->log("No valid value for 'index'"); + continue; + } + + Image *img = imageset->get(index); + + if (!img) + { + logger->log("No image at index %d", index); + continue; + } + + mParticleRotation.addFrame(img, delay, offsetX, offsetY); + } + else if (xmlStrEqual(frameNode->name, BAD_CAST "sequence")) + { + int start = XML::getProperty(frameNode, "start", -1); + int end = XML::getProperty(frameNode, "end", -1); + + if (start < 0 || end < 0) + { + logger->log("No valid value for 'start' or 'end'"); + continue; + } + + while (end >= start) + { + Image *img = imageset->get(start); + + if (!img) + { + logger->log("No image at index %d", start); + continue; + } + + mParticleRotation.addFrame(img, delay, offsetX, offsetY); + start++; + } + } + else if (xmlStrEqual(frameNode->name, BAD_CAST "end")) + { + mParticleRotation.addTerminator(); + } + } // for frameNode + } else if (xmlStrEqual(propertyNode->name, BAD_CAST "animation")) { ImageSet *imageset = ResourceManager::getInstance()->getImageSet( @@ -285,6 +354,7 @@ ParticleEmitter & ParticleEmitter::operator=(const ParticleEmitter &o) mOutputPause = o.mOutputPause; mParticleImage = o.mParticleImage; mParticleAnimation = o.mParticleAnimation; + mParticleRotation = o.mParticleRotation; mParticleChildEmitters = o.mParticleChildEmitters; mOutputPauseLeft = 0; @@ -349,6 +419,11 @@ std::list ParticleEmitter::createParticles(int tick) { newParticle = new ImageParticle(mMap, mParticleImage); } + else if (mParticleRotation.getLength() > 0) + { + Animation *newAnimation = new Animation(mParticleRotation); + newParticle = new RotationalParticle(mMap, newAnimation); + } else if (mParticleAnimation.getLength() > 0) { Animation *newAnimation = new Animation(mParticleAnimation); diff --git a/src/particleemitter.h b/src/particleemitter.h index 67b35ae2..f58430b3 100644 --- a/src/particleemitter.h +++ b/src/particleemitter.h @@ -125,6 +125,7 @@ class ParticleEmitter */ Image *mParticleImage; /**< Particle image, if used */ Animation mParticleAnimation; /**< Filename of particle animation file */ + Animation mParticleRotation; /**< Filename of particle rotation file */ ParticleEmitterProp mParticleAlpha; /**< Opacity of the graphical representation of the particles */ /** List of emitters the spawned particles are equipped with */ diff --git a/src/rotationalparticle.cpp b/src/rotationalparticle.cpp new file mode 100644 index 00000000..2fd7f901 --- /dev/null +++ b/src/rotationalparticle.cpp @@ -0,0 +1,76 @@ +/* + * The Mana World + * Copyright (C) 2006 The Mana World Development Team + * + * This file is part of The Mana World. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "rotationalparticle.h" +#include "graphics.h" +#include "simpleanimation.h" + +#define PI 3.14159265 + +RotationalParticle::RotationalParticle(Map *map, Animation *animation): + ImageParticle(map, NULL), + mAnimation(new SimpleAnimation(animation)) +{ +} + +RotationalParticle::RotationalParticle(Map *map, xmlNodePtr animationNode): + ImageParticle(map, 0), + mAnimation(new SimpleAnimation(animationNode)) +{ +} + +RotationalParticle::~RotationalParticle() +{ + delete mAnimation; + mImage = NULL; +} + +bool RotationalParticle::update() +{ + // TODO: cache velocities to avoid spamming atan2() + + float rad = atan2(mVelocity.x, mVelocity.y); + if (rad < 0) + rad = PI + (PI + rad); + int size = mAnimation->getLength(); + float range = PI / size; + + // Determines which frame the particle should play + if (rad < range || rad > ((PI*2) - range)) + { + mAnimation->setFrame(0); + } + else + { + for (int c = 1; c < size; c++) + { + if (((c * (2 * range)) - range) < rad && rad < ((c * (2 * range)) + range)) + { + mAnimation->setFrame(c); + break; + } + } + } + + mImage = mAnimation->getCurrentImage(); + + return Particle::update(); +} diff --git a/src/rotationalparticle.h b/src/rotationalparticle.h new file mode 100644 index 00000000..07c95e9c --- /dev/null +++ b/src/rotationalparticle.h @@ -0,0 +1,48 @@ +/* + * The Mana World + * Copyright (C) 2006 The Mana World Development Team + * + * This file is part of The Mana World. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _ROTATIONAL_PARTICLE_H +#define _ROTATIONAL_PARTICLE_H + +#include + +#include "imageparticle.h" + +class Animation; +class Map; +class SimpleAnimation; + +class RotationalParticle : public ImageParticle +{ + public: + RotationalParticle(Map *map, Animation *animation); + + RotationalParticle(Map *map, xmlNodePtr animationNode); + + ~RotationalParticle(); + + virtual bool update(); + + private: + SimpleAnimation *mAnimation; /**< Used animation for this particle */ +}; + +#endif diff --git a/src/simpleanimation.cpp b/src/simpleanimation.cpp index 65d8e8e2..7038f446 100644 --- a/src/simpleanimation.cpp +++ b/src/simpleanimation.cpp @@ -129,6 +129,16 @@ void SimpleAnimation::reset() mAnimationPhase = 0; } +void SimpleAnimation::setFrame(int frame) +{ + if (frame < 0) + frame = 0; + if (frame >= mAnimation->getLength()) + frame = mAnimation->getLength() - 1; + mAnimationPhase = frame; + mCurrentFrame = mAnimation->getFrame(mAnimationPhase); +} + void SimpleAnimation::update(unsigned int timePassed) { mAnimationTime += timePassed; @@ -145,6 +155,11 @@ void SimpleAnimation::update(unsigned int timePassed) } } +int SimpleAnimation::getLength() +{ + return mAnimation->getLength(); +} + Image *SimpleAnimation::getCurrentImage() const { return mCurrentFrame->image; diff --git a/src/simpleanimation.h b/src/simpleanimation.h index e48644d4..508810b1 100644 --- a/src/simpleanimation.h +++ b/src/simpleanimation.h @@ -48,6 +48,10 @@ class SimpleAnimation ~SimpleAnimation(); + void setFrame(int frame); + + int getLength(); + void update(unsigned int timePassed); bool draw(Graphics* graphics, int posX, int posY) const; -- cgit v1.2.3-60-g2f50