A small domain-specific language for scripting bullet behaviors for shooting games, inspired by BulletML.
The following is hypothesis, more of a desired end goal if you will.
- A declarative language defining bullet types and a sequence of events taking place across their lifespan.
- A particle system wrapper that carries out the events described.
Triggering a Barrage invokes its "initial event", and from there on the game engine must relinquish control of the particle system to the Barrage as it carries out its logic. For this reason, particle systems intended to be used with Barrage must implement some interface to facilitate this.
Barrage scripts can be parsed at runtime from loaded files or (eventually) at compile-time using Haxe macros. The latter approach means any used barrage script would be checked for errors during build and there would be no overhead from interpretation.
The following describes a bullet system where the initial action fires a slow bullet towards the player that "bursts" 6 times into a circular spread of more bullets before disappearing. The spawned bullets first spread, then gradually form into "waves" that flow towards the player.
# Comments are prefixed with pound sign
# A Barrage has a starting Action that results in bullets being created
# Actions can have sub-actions
# Bullets can trigger actions
# Actions triggered by bullets use the bullet's position as origin
# Barrage root declaration
barrage called waveburst
# Define and name a bullet.
# This bullet initially moves backwards, but accelerates towards a positive velocity
bullet called offspring
speed is -100
acceleration is 150
# This bullet action waits a second before turning towards the player
do action
wait 1 seconds
set direction to aimed over 1 seconds
# This is our base bullet
bullet called source
speed is 100
do action
# This action immediately triggers a sub-action
do action
# fires 6 360 degree spreads of 11 bullets, one every quarter second
wait 0.25 seconds
# Math expressions in parentheses are evaluated to constants at build time
fire offspring in aimed direction (360/10*0.5)
do action
fire offspring in incremental direction (360/10)
repeat 10 times
repeat 6 times
# wait for the sub-action to complete..
wait (6*0.25) seconds
# then die
die
# Barrage entry point. Every barrage must have a start action
action called start
# Fire a source bullet directly towards the player
fire source in aimed direction 0
Barrage as an engine can be considered a "particle governor" in that it needs access to emission and removal functions as well as the properties of each bullet created. Thus, it needs to be mapped against an emitter that implements the IEmitter interface, which needs to return bullets implementing the IBullet interface. When a Barrage is "run", a RunningBarrage instance is created which needs to be updated with an identical delta (in seconds) to the particle system.
The following example code demonstrates this relationship.
//Init
var b = Barrage.fromString(sourceCode);
var runningBarrage = b.run(emitter);
runningBarrage.onComplete.add(onBarrageComplete);
runningBarrage.start();
//Update
runningBarrage.update(deltaSeconds);
emitter.update(deltaSeconds);
This implementation is still in development. It's necessary for the emitter to be updated separately from the barrage, since an emitter typically won't be exclusive to barrage use.