Skip to content
Modar Nasser edited this page Feb 8, 2020 · 1 revision

Overview

A simple particles system that can be improved in many ways.

Inspired by the C++ example from SFML website.

Code

The needed imports are sfml, random and math

Here is the base class which inherits from sf.Drawable

class ParticlesSytem(sf.Drawable):
    def __init__(self, count):
        super().__init__()
        self.vertices = sf.VertexArray(sf.PrimitiveType.POINTS, count)
        self.particles = [{}]*count
        self.emitter_pos = sf.Vector2(0, 0)
        self.max_lifetime = sf.seconds(3)

    def reset_particle(self, index):
        angle = random.randrange(0, 360) * 3.14 / 180.0
        speed = (random.randrange(0, 150) + 150.0) / 300.0
        lifetime = random.randrange(0, 1500)+ 750
        self.particles[index] = {
            "velocity": sf.Vector2(math.cos(angle) * speed, math.sin(angle) * speed),
            "lifetime": sf.milliseconds(lifetime)
        }
        self.vertices[index].position = self.emitter_pos
        self.vertices[index].color = sf.Color.WHITE

    def update(self, elapsed_time):
        for i, particle in enumerate(self.particles):
            if particle != {}:
                particle["lifetime"] -= elapsed_time
                if particle["lifetime"] <= sf.Time.ZERO:
                    self.reset_particle(i)
                    continue

                ratio = particle["lifetime"] / self.max_lifetime
                self.vertices[i].color = sf.Color(255, 255, 255, int(ratio*255))
                self.vertices[i].position += particle["velocity"]

            else:
                # initialisation
                self.reset_particle(i)
                self.particles[i]["lifetime"] = sf.milliseconds(random.randrange(0, 1000))

    def draw(self, target, states):
        target.draw(self.vertices, states)

You can simply use it like this :

window = sf.RenderWindow(sf.VideoMode(750, 750), "Particles")
window.framerate_limit = 60
particles = ParticlesSytem(1000)
clock = sf.Clock()
while window.is_open:
    for event in window.events:
        if event == sf.Event.CLOSED:
            window.close()
        if event == sf.Event.KEY_PRESSED:
            if event["code"] == sf.Keyboard.ESCAPE:
                window.close()
    
    mouse = sf.Mouse.get_position(window)
    particles.emitter_pos = window.map_pixel_to_coords(mouse)
    
    particles.update(clock.elapsed_time)
    clock.restart()
    
    window.clear()
    window.draw(particles)
    window.display()
Clone this wiki locally