Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add particle systems and supporting example scripts #333 #334

Merged
merged 1 commit into from Mar 23, 2019

Conversation

Projects
None yet
3 participants
@SirGnip
Copy link
Contributor

commented Mar 23, 2019

As I was watching @pvcraven 's Arcade talk from PyCon 2018, I noticed that particles where mentioned in the "What's Next" portion of the talk. I thought I'd take a stab at an initial implementation of particle systems to get things rolling.

I focused on providing the user flexibility (the "what will the particle systems be able to do") and very little effort on the underlying implementation details (the "how") at this point (simply using Sprite and SpriteList).

I have something functional, so, I'd love it if the community could grab this PR, run examples/particle_systems.py and examples/particle_fireworks.py from the examples/ directory to get a sense of what it can do and post feedback here on the PR or on the Issue: #333.

Now, for the TL;DR...

Goals:

  • Declarative syntax - Users are able to assemble relatively complex Emitters with somewhat declarative-ish looking code (see examples/particle_systems.py)
  • Flexible
    • When creating an Emitter, it is passed a callback (see Emitter.particle_factory) that allows a user to define the initial state of the Particles that will be emitted. This allows for a lot of flexibility in controlling a Particle. A number of utility functions were created to make assembling this particle_factory callback easier (see utils.py).
    • Initial implementation allows any image file on disk or Texture object to be used as a particle
  • Extensible - User can easily add new behavior to their particle systems by simply writing arbitrary functions and calling them to the particle_factory callback function. Can also subclass the existing Particle and EmitController classes for more flexibility and reuse.
  • Minimal - Tried to create foundational features while keeping implementation small and simple, avoiding the temptation to try to do everything at the outset. Also tried to keep the impact to the existing arcade library code minimal.

Implementation Details

  • Current implementation is based on Sprite and SpriteList. May be a bit heavyweight when compared with traditional particle systems, but it allowed me to get something functional quickly.
  • Two client API's
    • A flexible core API - Constructing an Emitter requires that the user understand a couple intermediate Python language features such as callbacks and lambdas, but is rewarded with a lot of flexibility.
    • A simplified API for beginners that allows them to create Emitter objects with a simple function call. These functions give up some flexibility found in the core API to make the interface much simpler (see emitter_simple.py).
  • Plenty of working examples:
  • Can maintain 60 fps performance from one emitter that instantaneously emits 500 particles on a Windows 7 laptop with i7 CPU and integrated graphics card. The current performance bottleneck is creating and deleting multiple Sprites, not the animating of large numbers of Sprites. I have some simple optimizations that help with this (in a forthcoming PR).
  • Used pymunk's Vec2d for points and velocity vectors in function signatures
  • FrametimePlotter - Simple utility class that plots the length of each frame using matplotlib and dumps out basic stats (min, max, avg). Useful for identifying spikes in the length of each frame.

Possible next steps:

  • Optimization - Creating and reaping Sprites causes a spike in the length of a frame, meaning the user sees slight visual hitches when spawning or reaping large numbers of particles at the same time. (Some initial optimizations will be in another PR).
  • Forces - Provide better support for common "forces" (gravity, wind, drag, turbulence, attract, repel, etc.). The Emitter does currently support hand-built forces (see the use of Emitter.mutation_callback in examples/particle_fireworks.py) but some work can be done to make this easier on the user.
  • Collision - have particle respond (ex: disappear, bounce) when they collide with other things.
  • Refactor - Particles currently must be Sprites. Rework the particle system API and possibly some other arcade classes so that other objects (ex: pixels, polygons, Shape, ShapeElementList?) can be used as Particles.
  • Emitters must be drawn and updated, just like Sprites, so it usually makes sense to put them in a list (see self.emitters in examples/particle_fireworks.py). But, then the functionality here starts to look and feel somewhat like parts of SpriteList. There may be an opportunity to extract the "enables lists of things to be updated and drawn" logic from SpriteList and be able to use it in a more generic fashion (with Sprites, Emitters, Particles, even Shapes?) . More ideas on this later.

Known issues:

  • can't animate a Sprite's scale when it has a dynamically generated texture (probably bug #331)

@SirGnip SirGnip force-pushed the SirGnip:particle branch from 1874f55 to 1cca3a4 Mar 23, 2019

@pvcraven pvcraven merged commit 1f2981c into pvcraven:master Mar 23, 2019

1 check failed

continuous-integration/appveyor/pr AppVeyor build failed
Details
@pvcraven

This comment has been minimized.

Copy link
Owner

commented Mar 23, 2019

If you use discord: https://discord.gg/bDykUD

@pvcraven

This comment has been minimized.

Copy link
Owner

commented Mar 23, 2019

This is seriously cool!!!!!

@pauleveritt

This comment has been minimized.

Copy link
Collaborator

commented Mar 23, 2019

As a note, though...something like this could use some tests. Can I help?

@pvcraven

This comment has been minimized.

@pvcraven

This comment has been minimized.

Copy link
Owner

commented Mar 24, 2019

@SirGnip

This comment has been minimized.

Copy link
Contributor Author

commented Mar 24, 2019

Thanks! I had fun writing it...

Regarding tests, I intended particle_systems.py and particle_fireworks.py to serve as tests. But, yes, it could always use unit tests.

A question first, though. I honestly wasn't expecting this to get merged right away (but I'm excited that it has been!). I wanted to discuss a refactoring that could bring a lot more flexibility to both the particle system and arcade as a whole. But, I'd hate for a release to go out, people start to use the particle systems, and then we can't change the interface without breaking backward compatibility. I'm trying to put my refactoring thoughts into very concise words before posting it.

So, I don't want people to spend a ton of time building out tests for something that might change (maybe not, we'll see)

@SirGnip SirGnip deleted the SirGnip:particle branch Mar 27, 2019

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.