BulletMLLib 5.1.4
dotnet add package BulletMLLib --version 5.1.4
NuGet\Install-Package BulletMLLib -Version 5.1.4
<PackageReference Include="BulletMLLib" Version="5.1.4" />
<PackageVersion Include="BulletMLLib" Version="5.1.4" />
<PackageReference Include="BulletMLLib" />
paket add BulletMLLib --version 5.1.4
#r "nuget: BulletMLLib, 5.1.4"
#:package BulletMLLib@5.1.4
#addin nuget:?package=BulletMLLib&version=5.1.4
#tool nuget:?package=BulletMLLib&version=5.1.4
BulletMLLib
A C# library for parsing and executing BulletML XML files. Define complex bullet patterns declaratively in XML and run them in your shmup (shoot-em-up) game.
Based on the implementation by Keiichi Kashihara of Bandle Games.
Features
- Parse BulletML XML documents into executable pattern trees
- All BulletML elements supported: fire, direction, speed, acceleration, repeat, vanish, change direction/speed, and more
- Parameterized references for reusable bullet definitions
- Expression evaluation in node values (
$rank,$rand, custom callbacks) - Configurable time speed (slow-motion) and scale (resize patterns)
- Async update support
Installation
dotnet add package BulletMLLib
Requirements: .NET 8.0+, MonoGame.Framework.DesktopGL 3.8+
Quick Start
1. Implement IBulletManager to handle bullet lifecycle and provide game state:
public class MyBulletManager : IBulletManager
{
public Random Rand { get; } = new Random();
public Dictionary<string, FunctionDelegate> CallbackFunctions { get; } = new();
public FunctionDelegate GameDifficulty { get; set; } = () => 0.5f;
public Vector2 PlayerPosition(IBullet bullet) => _playerPos;
public IBullet CreateBullet() => new MyBullet(this);
public IBullet CreateTopBullet() => new MyBullet(this);
public void RemoveBullet(IBullet bullet) { /* mark inactive */ }
}
2. Inherit from Bullet to provide position storage and bounds checking:
public class MyBullet : Bullet
{
private Vector2 _position;
public override float X { get => _position.X; set => _position.X = value; }
public override float Y { get => _position.Y; set => _position.Y = value; }
public MyBullet(IBulletManager manager) : base(manager) { }
public override void PostUpdate() { /* check bounds, collisions, etc. */ }
}
3. Load a pattern and fire it:
var manager = new MyBulletManager();
var pattern = new BulletPattern(manager);
pattern.ParseXML("patterns/spiral.xml");
var topBullet = manager.CreateTopBullet();
topBullet.X = 400;
topBullet.Y = 100;
topBullet.InitTopNode(pattern.RootNode);
// Each frame:
topBullet.Update();
For a complete working example, see the QuickStart project.
Example BulletML Pattern
A spiral pattern that continuously fires rotating bullets:
<?xml version="1.0"?>
<bulletml type="vertical">
<action label="top">
<repeat>
<times>999</times>
<action>
<fire>
<direction type="sequence">13</direction>
<speed>2</speed>
<bullet />
</fire>
<wait>2</wait>
</action>
</repeat>
</action>
</bulletml>
Documentation
Full documentation is available in the docs folder:
- Getting Started -- step-by-step integration guide
- API Reference -- classes, interfaces, enums, and properties
- BulletML Pattern Guide -- writing BulletML XML scripts
- Architecture -- library internals and design
The wiki is also a useful reference for writing BulletML scripts.
Resources
- BulletML Specification -- original language spec by ABA Games
- BulletML Examples -- collection of open-source BulletML patterns
- QuickStart Project -- minimal working example
License
MIT
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 was computed. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net8.0
- Equationator (>= 5.0.0)
- Vector2Extensions (>= 5.0.0)
NuGet packages (1)
Showing the top 1 NuGet packages that depend on BulletMLLib:
| Package | Downloads |
|---|---|
|
BulletCircus
MonoGame library game that mixes BulletML with flocking and collision detection |
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 5.1.4 | 97 | 10/2/2026 |
| 5.1.3 | 111 | 9/28/2026 |
| 5.1.2 | 91 | 9/28/2026 |
| 5.1.1 | 94 | 9/28/2026 |
| 5.1.0 | 92 | 9/28/2026 |
| 5.0.0 | 197 | 1/27/2026 |
| 2.0.5 | 1,372 | 7/7/2021 |
| 2.0.4 | 1,214 | 7/1/2021 |
| 2.0.2 | 1,189 | 4/27/2021 |
| 2.0.1 | 1,509 | 3/5/2020 |
| 2.0.0 | 1,607 | 5/6/2019 |
| 1.0.8 | 2,294 | 2/20/2018 |
| 1.0.7 | 2,118 | 12/3/2017 |
| 1.0.5 | 1,977 | 11/30/2017 |
| 1.0.4 | 2,178 | 12/24/2016 |
| 1.0.3 | 2,129 | 9/5/2016 |
| 1.0.2 | 2,089 | 9/4/2016 |
5.1.3
Recursive actions work. An action can now reference itself, directly or through other actions, as long as it reaches a wait before it recurses. 5.1 rejected every such pattern as a "circular actionRef".
- When the recursive actionRef is the last thing left to run, the action restarts with the new params instead of nesting another copy of itself, so a pattern can recurse for as long as the game runs without using more memory or stack.
- A cycle with no wait would loop forever in one frame, so it still fails to load: The action node "loop" has a circular actionRef with no wait before it
- If a recursive action's waits come out as 0 at runtime (for example $rand*2), it runs once per frame instead of hanging.
Upgrading from 5.0? 5.1.0 made pattern validation much stricter. See the full release notes before upgrading.
Full release notes: https://github.com/dmanning23/BulletMLLib/blob/master/CHANGELOG.md