A type-safe ECS library in MoonBit using extensible enums.
Dependencies
///|
struct ReadmePosition {
mut x : Int
mut y : Int
}
///|
struct ReadmeVelocity {
x : Int
y : Int
}
///|
struct ReadmeFrame {
value : Int
}
///|
@mecs.Component {
ReadmePosition(ReadmePosition)
ReadmeVelocity(ReadmeVelocity)
}
///|
@mecs.Resource {
ReadmeFrame(ReadmeFrame)
}
///|
impl @mecs.ComponentValue for ReadmePosition with component_id() {
component_id("ReadmePosition")
}
///|
impl @mecs.ComponentValue for ReadmePosition with to_component(self) {
ReadmePosition(self)
}
///|
impl @mecs.ComponentValue for ReadmePosition with from_component(component) {
match component {
ReadmePosition(value) => Some(value)
_ => None
}
}
///|
impl @mecs.ComponentValue for ReadmeVelocity with component_id() {
component_id("ReadmeVelocity")
}
///|
impl @mecs.ComponentValue for ReadmeVelocity with to_component(self) {
ReadmeVelocity(self)
}
///|
impl @mecs.ComponentValue for ReadmeVelocity with from_component(component) {
match component {
ReadmeVelocity(value) => Some(value)
_ => None
}
}
///|
impl @mecs.ResourceValue for ReadmeFrame with resource_id() {
resource_id("ReadmeFrame")
}
///|
impl @mecs.ResourceValue for ReadmeFrame with to_resource(self) {
ReadmeFrame(self)
}
///|
impl @mecs.ResourceValue for ReadmeFrame with from_resource(resource) {
match resource {
ReadmeFrame(value) => Some(value)
_ => None
}
}
///|
fn readme_move_system(world : @mecs.World) -> Unit {
try! world.each2(fn(
velocity : ReadmeVelocity,
position : ReadmePosition,
) -> Unit {
position.x velocity.x
position.y velocity.y
})
}
///|
fn readme_frame_system(world : @mecs.World) -> Unit {
let frame : ReadmeFrame = world.get_resource()
world.set_resource(ReadmeFrame::{ value: frame.value + 1 })
}
///|
test "readme quick start" {
let world = @mecs.World()
world.set_resource(ReadmeFrame::{ value: 0 })
let entity = world.spawn_with(
(ReadmePosition::{ x: 0, y: 0 }, ReadmeVelocity::{ x: 2, y: 3 }),
)
world
..add_system(System(readme_move_system))
..add_system(System(readme_frame_system))
|> ignore
try! world.step()
let position : ReadmePosition = world.require_component(entity)
let rows : Array[(@mecs.EntityId, (ReadmeVelocity, ReadmePosition))] = world
.query2_entities()
.to_array()
inspect((position.x, position.y), content="(2, 3)")
inspect((world.get_resource() : ReadmeFrame).value, content="1")
inspect(rows.length(), content="1")
}///|
let moving = @mecs.QueryFilter().with_component(_hint=(None : ReadmeVelocity?))
///|
let moving_positions : Array[ReadmePosition] = world
.query1_filtered(moving)
.to_array()
///|
let stationary = @mecs.QueryFilter().without_component(
_hint=(None : ReadmeVelocity?),
)
///|
let stationary_positions : Array[ReadmePosition] = world
.query1_filtered(stationary)
.to_array()fn[A : ComponentValue, B : ComponentValue] insert_into(bundle : (A, B), world : World, entity : EntityId) -> Unitfn[A : ComponentValue, B : ComponentValue, C : ComponentValue] insert_into(bundle : (A, B, C), world : World, entity : EntityId) -> Unitfn[A : ComponentValue, B : ComponentValue, C : ComponentValue, D : ComponentValue] insert_into(bundle : (A, B, C, D), world : World, entity : EntityId) -> Unitpub(open) trait ComponentValue {
component_id() -> ComponentId
to_component(Self) -> Component
from_component(Component) -> Self?
}fn[A : ComponentValue, B : ComponentValue, C : ComponentValue] iter(world : World) -> Iter[(A, B, C)]fn[A : ComponentValue, B : ComponentValue, C : ComponentValue, D : ComponentValue] iter(world : World) -> Iter[(A, B, C, D)]fn[A : ComponentValue, B : ComponentValue, C : ComponentValue, D : ComponentValue, E : ComponentValue] iter(world : World) -> Iter[(A, B, C, D, E)]pub(open) trait ResourceValue {
resource_id() -> ResourceId
to_resource(Self) -> Resource
from_resource(Resource) -> Self?
}pub(all) suberror EcsError {
EntityMissing(EntityId)
ComponentMissing(EntityId, ComponentId)
ComponentVariantMismatch(EntityId, ComponentId)
ResourceMissing(ResourceId)
ResourceVariantMismatch(ResourceId)
} derive(Eq, Debug)pub struct CommandSystem {
name : String
func : (World, Commands) -> Unit
}
fn CommandSystem::CommandSystem(func : (World, Commands) -> Unit, name? : String) -> CommandSystemtype Commandsfn[C : ComponentValue] Commands::insert_component(self : Commands, entity : EntityId, component : C) -> Unitfn[C : ComponentValue] Commands::remove_component(self : Commands, entity : EntityId, _hint? : C?) -> Unitpub struct ComponentId {
name : String
} derive(Eq, Hash, Debug)
fn ComponentId::ComponentId(name : String) -> ComponentIdtype EntityOpsfn[C : ComponentValue] EntityOps::insert_component(self : EntityOps, component : C) -> Unit raise NotSpawnedfn[C : ComponentValue] EntityOps::insert_component_checked(self : EntityOps, component : C) -> Unit raise EcsErrorfn[C : ComponentValue] EntityOps::remove_component_checked(self : EntityOps, _hint? : C?) -> Unit raise EcsErrorfn[C : ComponentValue] QueryFilter::without_component(self : QueryFilter, _hint? : C?) -> QueryFilterpub struct ResourceId {
name : String
} derive(Eq, Hash, Debug)
fn ResourceId::ResourceId(name : String) -> ResourceIdpub struct SystemLabel {
name : String
} derive(Eq, Hash, Debug)
fn SystemLabel::SystemLabel(name : String) -> SystemLabelfn World::add_command_system_fn_to_stage(self : World, stage : Stage, func : (World, Commands) -> Unit, name? : String, before? : Array[SystemLabel], after? : Array[SystemLabel], run_if? : (World) -> Bool) -> Unitfn World::add_command_system_to_stage(self : World, stage : Stage, system : CommandSystem, before? : Array[SystemLabel], after? : Array[SystemLabel], run_if? : (World) -> Bool) -> Unitfn World::add_system_fn_to_stage(self : World, stage : Stage, func : (World) -> Unit, name? : String, before? : Array[SystemLabel], after? : Array[SystemLabel], run_if? : (World) -> Bool) -> Unitfn World::add_system_to_stage(self : World, stage : Stage, system : System, before? : Array[SystemLabel], after? : Array[SystemLabel], run_if? : (World) -> Bool) -> Unitfn[A : ComponentValue, B : ComponentValue] World::each2(self : World, f : (A, B) -> Unit) -> Unit raise NotSpawnedfn[A : ComponentValue, B : ComponentValue, C : ComponentValue] World::each3(self : World, f : (A, B, C) -> Unit) -> Unit raise NotSpawnedfn[A : ComponentValue, B : ComponentValue] World::for_each2(self : World, f : (A, B) -> Unit) -> Unitfn[A : ComponentValue, B : ComponentValue, C : ComponentValue] World::for_each3(self : World, f : (A, B, C) -> Unit) -> Unitfn[A : ComponentValue, B : ComponentValue, C : ComponentValue, D : ComponentValue] World::for_each4(self : World, f : (A, B, C, D) -> Unit) -> Unitfn[A : ComponentValue, B : ComponentValue, C : ComponentValue, D : ComponentValue, E : ComponentValue] World::for_each5(self : World, f : (A, B, C, D, E) -> Unit) -> Unitfn[C : ComponentValue] World::get_component_checked(self : World, entity : EntityId) -> C raise EcsErrorfn[C : ComponentValue] World::insert_component(self : World, entity : EntityId, component : C) -> Unit raise NotSpawnedfn[C : ComponentValue] World::insert_component_checked(self : World, entity : EntityId, component : C) -> Unit raise EcsErrorfn[C : ComponentValue] World::query1_entities_filtered(self : World, filter : QueryFilter) -> Iter2[EntityId, C]fn[A : ComponentValue, B : ComponentValue] World::query2_entities(self : World) -> Iter2[EntityId, (A, B)]fn[A : ComponentValue, B : ComponentValue] World::query2_entities_filtered(self : World, filter : QueryFilter) -> Iter2[EntityId, (A, B)]fn[A : ComponentValue, B : ComponentValue] World::query2_filtered(self : World, filter : QueryFilter) -> Iter[(A, B)]fn[A : ComponentValue, B : ComponentValue, C : ComponentValue] World::query3(self : World) -> Iter[(A, B, C)]fn[A : ComponentValue, B : ComponentValue, C : ComponentValue] World::query3_entities(self : World) -> Iter2[EntityId, (A, B, C)]fn[A : ComponentValue, B : ComponentValue, C : ComponentValue] World::query3_entities_filtered(self : World, filter : QueryFilter) -> Iter2[EntityId, (A, B, C)]fn[A : ComponentValue, B : ComponentValue, C : ComponentValue] World::query3_filtered(self : World, filter : QueryFilter) -> Iter[(A, B, C)]fn[A : ComponentValue, B : ComponentValue, C : ComponentValue, D : ComponentValue] World::query4(self : World) -> Iter[(A, B, C, D)]fn[A : ComponentValue, B : ComponentValue, C : ComponentValue, D : ComponentValue] World::query4_entities(self : World) -> Iter2[EntityId, (A, B, C, D)]fn[A : ComponentValue, B : ComponentValue, C : ComponentValue, D : ComponentValue] World::query4_entities_filtered(self : World, filter : QueryFilter) -> Iter2[EntityId, (A, B, C, D)]fn[A : ComponentValue, B : ComponentValue, C : ComponentValue, D : ComponentValue] World::query4_filtered(self : World, filter : QueryFilter) -> Iter[(A, B, C, D)]fn[A : ComponentValue, B : ComponentValue, C : ComponentValue, D : ComponentValue, E : ComponentValue] World::query5(self : World) -> Iter[(A, B, C, D, E)]fn[A : ComponentValue, B : ComponentValue, C : ComponentValue, D : ComponentValue, E : ComponentValue] World::query5_entities(self : World) -> Iter2[EntityId, (A, B, C, D, E)]fn[A : ComponentValue, B : ComponentValue, C : ComponentValue, D : ComponentValue, E : ComponentValue] World::query5_entities_filtered(self : World, filter : QueryFilter) -> Iter2[EntityId, (A, B, C, D, E)]fn[A : ComponentValue, B : ComponentValue, C : ComponentValue, D : ComponentValue, E : ComponentValue] World::query5_filtered(self : World, filter : QueryFilter) -> Iter[(A, B, C, D, E)]fn[C : ComponentValue] World::remove_component(self : World, entity : EntityId, _hint? : C?) -> Unitfn[C : ComponentValue] World::remove_component_checked(self : World, entity : EntityId, _hint? : C?) -> Unit raise EcsErrorfn[R : ResourceValue] World::remove_resource_checked(self : World, _hint? : R?) -> Unit raise EcsErrorA type-safe ECS library in MoonBit using extensible enums.
Dependencies