HW

a blog about code.

about

projects

contact

Implementing a simple Particle System in Python using libtcod

Particle systems can be used to simulate "fuzzy" phenomena --- fire, water, explosions, stars etc.

I knew that I wanted to explosions in the game that I am developing so I began by developing the following simple particle system.

Setup Virtual Environment and Install libtcod

mkdir particle_system

cd ./particle_system

Create and activate virtual environment

python3 -m venv venv

source ./venv/bin/activate

Install tcod

pip3 install tcod

Download the console font.

wget https://raw.githubusercontent.com/TStand90/roguelike_tutorial_revised/master/arial10x10.png

A Simple Particle System in Python

Create a file called particle_system.py.

Put the following code into particle systems.py:

import tcod as libtcod
import random
import time

screen_width = 80
screen_height = 50
window_title = "A Particle System"
max_particle_moves = 100
particles_per_update = 2

red_lt = libtcod.Color(251,73,52) #gruvbox lt red

class Particle:
    def __init__(self, x, y, vx, vy, colour):
        self.x = x
        self.y = y
        self.vx = vx
        self.vy = vy
        self.colour = colour
        self.moves = 0

    def is_dead(self):
        if self.moves > max_particle_moves:
            return True
        else:
            return False

    def move(self):
        self.x += self.vx
        self.y += self.vy
        self.moves += 1

    def draw(self):
        libtcod.console_set_char_background(
            0,
            self.x,
            self.y,
            self.colour,
            libtcod.BKGND_SET
        )


class ParticleSystem:
    def __init__(self, x, y):
        self.origin = x, y
        self.particles = []

    def update(self):
        x, y = self.origin

        for p in self.particles:
            p.move()
            if p.is_dead():
                self.particles.remove(p)

    def add_particles(self, number):
        for i in range(0, number):
            vx = random.randint(-2, 2)
            vy = random.randint(-2, 2)
            p = Particle(self.origin[0], self.origin[1], vx, vy, red_lt)
            self.particles.append(p)


    def draw(self):
        for p in self.particles:
            p.draw()


def main():

    libtcod.console_set_custom_font(
        "arial10x10.png", libtcod.FONT_TYPE_GREYSCALE | libtcod.FONT_LAYOUT_TCOD
    )

    libtcod.console_init_root(
        screen_width,
        screen_height,
        window_title,
        False,
    )

    ps = ParticleSystem(20, 20)

    while not libtcod.console_is_window_closed():
        libtcod.console_clear(0)
        ps.draw()
        ps.update()
        ps.add_particles(particles_per_update)
        time.sleep(.1)
        libtcod.console_flush()
        key = libtcod.console_check_for_keypress()
        if key.vk == libtcod.KEY_ESCAPE: break


if __name__ == "__main__":
    main()

Run it

python ./particle_system.py

It is not very exciting right now but it is a base from which a more rich system might be built.