Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
SFML Game Development.pdf
Скачиваний:
194
Добавлен:
28.03.2016
Размер:
4.19 Mб
Скачать

Chapter 8

float ratio = particle.lifetime.asSeconds()

/ Table[mType].lifetime.asSeconds();

c.a = static_cast<sf::Uint8>(255 * std::max(ratio, 0.f));

Now the interesting part: we add four vertices for each particle, one in every corner of our rectangle. The first two arguments denote the target coordinates; the next two denote the texture coordinates. The fifth argument is the vertex color. Since we need no gradient inside a particle, the color is uniform for all four vertices.

addVertex(pos.x - half.x, pos.y - half.y, 0.f,

0.f,

c);

addVertex(pos.x + half.x, pos.y - half.y, size.x,

0.f,

c);

addVertex(pos.x +

half.x, pos.y +

half.y, size.x,

size.y, c);

addVertex(pos.x -

half.x, pos.y +

half.y, 0.f,

size.y, c);

}

The function to add vertices itself is not very interesting—it builds sf::Vertex and adds it to sf::VertexArray:

void ParticleNode::addVertex(float worldX, float worldY, float texCoordX, float texCoordY, const sf::Color& color) const

{

sf::Vertex vertex;

vertex.position = sf::Vector2f(worldX, worldY); vertex.texCoords = sf::Vector2f(texCoordX, texCoordY); vertex.color = color;

mVertexArray.append(vertex);

}

Emitter nodes

Because particles should be emitted in the places where the missiles are located, it stands to reason that emitters should be attached to missiles. Once more, our scene graph comes in very handy: we can create a new scene node EmitterNode for emitters and attach it to the Projectile node of the missile.

EmitterNode is rather simple, its class definition is shown in the following code snippet:

class EmitterNode : public SceneNode

{

public:

 

 

 

explicit

EmitterNode(Particle::Type type);

...

 

 

 

 

 

 

 

 

 

[ 197 ]

 

 

 

 

www.it-ebooks.info

Every Pixel Counts – Adding Visual Effects

private:

sf::Time mAccumulatedTime; Particle::Type mType; ParticleNode* mParticleSystem;

};

The pointer mParticleSystem points to the ParticleNode into which the EmitterNode emits particles. Initially, it is nullptr. In the update function, we emit particles if the particle system has already been initialized. Otherwise, we need to find the system corresponding to the emitter. "Corresponding" means both use the same particle type, for example, Particle::Smoke. We send a command through the scene graph to find the right particle system. It sets the member variable

mParticleSystem to the found ParticleNode:

void EmitterNode::updateCurrent(sf::Time dt, CommandQueue& commands)

{

if (mParticleSystem)

{

emitParticles(dt);

}

else

{

auto finder = [this] (ParticleNode& container, sf::Time)

{

if (container.getParticleType() == mType) mParticleSystem = &container;

};

Command command;

command.category = Category::ParticleSystem; command.action = derivedAction<ParticleNode>(finder);

commands.push(command);

}

}

After the emitter has been linked to a particle system, the method to emit particles becomes interesting. We set an emission rate and try to achieve it as closely as possible. Since this is not usually equal to our logic frame rate, the amount of emitted particles per frame differs. To cope with that problem, we again use accumulators, as we did for the logic game loop in Chapter 1, Making a Game Tick. We emit particles as long as the emission interval still fits into the current frame. The remaining time is stored in mAccumulatedTime and is carried over to the next frame.

[ 198 ]

www.it-ebooks.info

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]