Particles version 0.1.0 Get Latest Release
particles.scm (https://github.com/ericoporto/particles/releases/download/v0.1.0/particles.scm) | GitHub Repo (https://github.com/ericoporto/particles) | Project with Demo! (https://github.com/ericoporto/particles/releases/download/v0.1.0/particles_demo_windows.zip)
(https://github.com/ericoporto/particles/actions/workflows/main.yml/badge.svg) (https://github.com/ericoporto/particles/actions)
Particle Script Module for AGS
OverviewThis module is meant to help you manage particles on screen, which can be used for visual effects or even for game related actions.
It has two base concepts, the emitter, which is the source and owner of the effect you want to devise, and the particles, which run a small piece of logic repeatedly and syncs itself to a visual representation as AGS Overlays.
There is an additional concept which this module uses called the particle definition, which is a simple object that has no logic, but it has a series of properties, which represents the initial configuration and instructions a particle will receive, including characteristics it should have, how it should behave (using physics concepts) and how it should look.
An emitter owns a collection of particle definitions (an array), and when it emits each particle it selects a particle definition from its collection at random, and assigns it to a particle, which is then emitted.
Because this collection of definitions can be big, you can use any random process you want (with your own probability distributions) to create this collection. Because the emitter samples this collection at random, the produced particles will have matching distribution (at least visually) to the one used to generate the array of definitions.
UsageHere is a simple example, to quickstart using this module and give an idea of how it works
// ... in room script
// encapsulate definition in a function to be able to apply randomnes
ParticleDefinition* GetSparkleParticle()
{
ParticleDefinition* sparkleParticle = new ParticleDefinition;
sparkleParticle.LifeTotal = 50;
sparkleParticle.VelX = Random(3000) - 1000;
sparkleParticle.VelY = Random(3000) - 1000;
sparkleParticle.TransparencyBegin = 0;
sparkleParticle.TransparencyEnd = 100;
sparkleParticle.WidthBegin = 3;
sparkleParticle.WidthEnd = 8;
sparkleParticle.HeightBegin = 3;
sparkleParticle.HeightEnd = 8;
sparkleParticle.Gravity = 100;
sparkleParticle.GroundY = 154;
sparkleParticle.Bounces = true;
return sparkleParticle;
}
Emitter emt;
void room_AfterFadeIn()
{
// Create array of particle definitions
int defs_count = 2048;
ParticleDefinition *defs[] = new ParticleDefinition[defs_count];
for(i=0; i<defs_count; i++)
{
defs[i] = GetSparkleParticle();
}
// Emitter at (150, 90) emitting 10 particles, max 256 at a time
emt.Init(150, 90, defs, defs_count, 10, 256);
}
void on_mouse_click(MouseButton button)
{
// Emit particles on click
emt.SetPosition(mouse.x, mouse.y);
emt.Emit();
}
function repeatedly_execute_always()
{
emt.Update();
}
Script APISpoiler
Emitter
This struct is the main way we will manage particles in this module.
Emitter.Init
void Emitter.Init(int x, int y, ParticleDefinition * defs[], int defCount, int emitAmount, int maxParticles);
Initializes the emitter, has to be run once, before invoking any other method from the emitter.
You will pass the following parameters
- a position (x, y) to place the emitter (it can be set later to other using SetPosition method)
- an array of Particle Definitions, along with the size of this array
- the amount of particles that should be emitted when calling Emit()
- the maximum number of particles that should exist at the same time
Emitter.Update
void Emitter.Update();
This method will both run one step in the particle simulation and update their rendering on the screen using overlays.
You normally run this once in repeatedly_execute_always, room_RepExec or some other method you use to run once per frame.
Emitter.Emit
void Emitter.Emit();
Emits particles. The amount of particles emitted is the emitAmount set when you init the emitter.
A random particle definition is selected from the set definitions arrays, and used to initialize each particle emitted individually.
Emitter.SetPosition
void Emitter.SetPosition(int x, int y);
Sets the position of the emitter on screen.
Emitter.SetDefinitions
void Emitter.SetDefinitions(ParticleDefinition * defs[], int defCount);
Sets the definitions hold by the emitter.
Emitter.ParticlesHitPoint
Particle * [] Emitter.ParticlesHitPoint(int x, int y);
Get null terminated array of particles that overlaps with the given point.
Emitter.ParticlesHitRect
Particle * [] Emitter.ParticlesHitRect(int x, int y, int width, int height);
Get null terminated array of particles that overlaps with the given rectangle.
Particle
This struct represents a single particle in the particle system. It is used to simulate the movement, appearance, and behavior of each particle.
It's managed by the emitter and they can be retrieved through specific methods in the emitter (for now only hit tests), and then you can get some information from each directly.
Particle.Life
int attribute Particle.Life;
The remaining life of the particle. It decrements on each update and the particle dies when its life is equal to or below zero.
Particle.IsAlive
bool Particle.IsAlive();
Returns true if the particle is still alive (i.e., its life is greater than zero), and false otherwise.
Particle.HitsPoint
bool Particle.HitsPoint(int x, int y);
Returns true if the particle overlaps the given point (x, y). The particle is assumed to be a rectangle for the purpose of hit detection.
Particle.HitsRect
bool Particle.HitsRect(int x, int y, int width, int height);
Returns true if the particle overlaps the given rectangle (x, y, width, height). The particle is assumed to be a rectangle for the purpose of hit detection.
ParticleDefinition
This struct defines the behavior and visual properties of particles. It is used by the emitter to generate new particles with specific characteristics.
When you set the value of them, it's usually a good idea to create a function to encapsulate this setting, so you can produce many different values with random settings on each definition.
ParticleDefinition.Sprite
int ParticleDefinition.Sprite;
The sprite used for the particle. If SpriteBegin and SpriteEnd are set, this defines the initial frame of the particle animation.
ParticleDefinition.OffsetX
int ParticleDefinition.OffsetX;
The horizontal offset from the emitter's position when the particle is emitted.
ParticleDefinition.OffsetY
int ParticleDefinition.OffsetY;
The vertical offset from the emitter's position when the particle is emitted.
ParticleDefinition.LifeTotal
int ParticleDefinition.LifeTotal;
The total lifetime of the particle, in update loops. This value is used to initialize the particle's life when it is emitted.
ParticleDefinition.VelX
int ParticleDefinition.VelX;
The initial horizontal velocity of the particle, in thousandths of a pixel per update loop. It's in X direction, so positive numbers moves particle to right.
ParticleDefinition.VelY
int ParticleDefinition.VelY;
The initial vertical velocity of the particle, in thousandths of a pixel per update loop. It's in Y direction, so positive numbers moves particle upwards.
ParticleDefinition.Gravity
int ParticleDefinition.Gravity;
The vertical acceleration applied to the particle over time (gravity), in thousandths of a pixel per update loop.
ParticleDefinition.SpriteBegin
int ParticleDefinition.SpriteBegin;
The initial sprite frame of a sequential sprite range.
ParticleDefinition.SpriteEnd
int ParticleDefinition.SpriteEnd;
The final sprite frame of a sequential sprite range.
ParticleDefinition.TransparencyBegin
int ParticleDefinition.TransparencyBegin;
The transparency level when the particle is emitted. A value of 0 is fully opaque, and 100 is fully transparent.
ParticleDefinition.TransparencyEnd
int ParticleDefinition.TransparencyEnd;
The transparency level when the particle reaches the end of its life.
ParticleDefinition.WidthBegin
int ParticleDefinition.WidthBegin;
The width of the particle when it is emitted.
ParticleDefinition.WidthEnd
int ParticleDefinition.WidthEnd;
The width of the particle when it reaches the end of its life.
ParticleDefinition.HeightBegin
int ParticleDefinition.HeightBegin;
The height of the particle when it is emitted.
ParticleDefinition.HeightEnd
int ParticleDefinition.HeightEnd;
The height of the particle when it reaches the end of its life.
ParticleDefinition.Bounces
bool ParticleDefinition.Bounces;
Determines whether the particle should bounce when it hits the ground.
ParticleDefinition.GroundY
int ParticleDefinition.GroundY;
The vertical position that the particle will treat as the ground for bounce detection. If this is not set, the particle will not recognize any ground.
ParticleDefinition.BlendMode
BlendMode ParticleDefinition.BlendMode;
The blend mode to use when rendering the particle.
Compatibility: This is only available in AGS 4.0 and above.
ParticleDefinition.Angle
float ParticleDefinition.Angle;
The initial rotation angle of the particle, in degrees (0 to 360).
Compatibility: This is only available in AGS 4.0 and above.
ParticleDefinition.RotationSpeed
float ParticleDefinition.RotationSpeed;
The speed at which the particle rotates, in degrees per update loop.
Compatibility: This is only available in AGS 4.0 and above.
LicenseThis module is created by eri0o is provided with MIT License, see LICENSE (https://github.com/ericoporto/particles/blob/main/LICENSE) for more details.
NoteThis module is considered in beta stage, and there is probably a lot missing in it, as an example it can't yet produce room overlays (I haven't figured how I should manage them in the pool that is used behind the scenes).
Please play with it and give me feedback and ideas you have. Still, there is a lot that can be done with it already!
Hi Lorenzo! Thanks!! In theory the performance shouldn't be much different because it's based on Overlays and not on rawpixel drawing. I wanted to make the demo high res to be more interesting but I couldn't find fun pre-made assets that were high res so I kept at the default stuff for now. I will see if I can find something again for background and character that still looks interesting.