CyberBasic now includes a feature-rich ECS system that provides dynamic component management, entity queries, hierarchical scenes, and much more.
- Hardcoded components in Entity struct
- Only
addComponent()- no get/remove/has - No component queries
- No component systems
- Limited to 6 component types
- Dynamic component storage - Add any component type at runtime
- Full CRUD operations - Add, Get, Remove, Has, SetData
- Component queries - Find entities by component type(s)
- Hierarchical entities - Parent/child relationships
- 12+ built-in component types - Transform, Sprite, Model3D, RigidBody, Collider, Health, AI, Inventory, Animation, Light, AudioSource, Script
- Component data access - Read and modify component properties
- Scene management - Create, destroy, query entities in scenes
Entities are containers for components. They have:
- Unique ID
- Name
- Active state
- Parent/child relationships
- Scene membership
Components are data containers attached to entities:
- Transform (position, rotation, scale)
- Sprite (2D rendering)
- Model3D (3D rendering)
- RigidBody (physics)
- Collider (collision detection)
- Health (gameplay)
- AI (behavior)
- Inventory (items)
- Animation (frame-based)
- Light (lighting)
- AudioSource (sound)
- Script (custom logic)
Scenes contain entities and manage their lifecycle:
- Create/destroy entities
- Query entities by component
- Update/draw all entities
VAR scene = Scene("MainScene")VAR player = scene.createEntity("Player")
VAR child = scene.createEntity("Child", player) // With parentscene.destroyEntity(player) // Also destroys children recursivelyVAR sprites = scene.query("Sprite") // All entities with Sprite component
FOR EACH entity IN sprites
PRINT entity.name
NEXT// Entities with BOTH Sprite AND Transform
VAR renderables = scene.queryAll("Sprite", "Transform")VAR delta = Clock.getDelta()
scene.update(delta)scene.draw() // Draws all entities with Sprite/Model3D componentsVAR count = scene.getEntityCount()VAR player = scene.createEntity("Player")
// Add Transform component
player.addComponent("Transform")
// Add Sprite with custom data
VAR spriteData = {
textureId = 1,
visible = TRUE,
tint = "WHITE"
}
player.addComponent("Sprite", spriteData)
// Add Health component
VAR healthData = {
maxHealth = 100,
currentHealth = 100
}
player.addComponent("Health", healthData)VAR transform = player.getComponent("Transform")
VAR x = transform.x
VAR y = transform.y
VAR z = transform.zIF player.hasComponent("Sprite") THEN
PRINT "Player has sprite"
END IFplayer.removeComponent("Sprite")VAR newData = {
currentHealth = 50
}
player.setComponentData("Health", newData)player.setPosition(100, 200, 0)VAR pos = player.getPosition()
PRINT "X: " + STR(pos.x) + ", Y: " + STR(pos.y)player.setActive(FALSE) // Hide/disable entityVAR weapon = scene.createEntity("Weapon")
weapon.setParent(player) // Weapon follows playerVAR transform = {
x = 0.0,
y = 0.0,
z = 0.0,
rotationX = 0.0,
rotationY = 0.0,
rotationZ = 0.0,
scaleX = 1.0,
scaleY = 1.0,
scaleZ = 1.0
}VAR sprite = {
textureId = 0,
visible = TRUE,
tint = "WHITE"
}VAR model = {
modelId = 0,
visible = TRUE,
tint = "WHITE"
}VAR body = {
bodyId = 0,
mass = 1.0,
friction = 0.5,
restitution = 0.0
}VAR collider = {
shape = "Box", // "Box" or "Sphere"
width = 1.0,
height = 1.0,
depth = 1.0,
radius = 0.5,
isTrigger = FALSE
}VAR health = {
maxHealth = 100.0,
currentHealth = 100.0,
isDead = FALSE
}VAR ai = {
behaviorTree = "",
state = "Idle",
targetId = 0
}VAR inventory = {
items = [],
maxSize = 10
}VAR anim = {
animationId = 0,
playing = FALSE,
loop = TRUE
}VAR light = {
type = "Point", // "Point", "Directional", "Spot"
color = "WHITE",
intensity = 1.0,
range = 10.0
}VAR audio = {
soundId = 0,
volume = 1.0,
pitch = 1.0,
loop = FALSE
}VAR script = {
scriptName = "",
enabled = TRUE
}// Initialize game
GAME.init(800, 600, "ECS Demo", 60)
// Create scene
VAR scene = Scene("GameScene")
// Create player entity
VAR player = scene.createEntity("Player")
player.addComponent("Transform")
player.addComponent("Sprite", {textureId = 1, visible = TRUE})
player.addComponent("Health", {maxHealth = 100, currentHealth = 100})
player.addComponent("Collider", {shape = "Box", width = 32, height = 32})
player.setPosition(400, 300, 0)
// Create enemy entity
VAR enemy = scene.createEntity("Enemy")
enemy.addComponent("Transform")
enemy.addComponent("Sprite", {textureId = 2, visible = TRUE})
enemy.addComponent("Health", {maxHealth = 50, currentHealth = 50})
enemy.addComponent("AI", {state = "Patrol"})
enemy.setPosition(200, 200, 0)
// Create weapon as child of player
VAR weapon = scene.createEntity("Weapon")
weapon.addComponent("Transform")
weapon.addComponent("Sprite", {textureId = 3})
weapon.setParent(player)
// Game loop
WHILE NOT GAME.shouldClose()
GAME.beginFrame()
VAR delta = Clock.getDelta()
// Update scene
scene.update(delta)
// Query all entities with Health component
VAR healthEntities = scene.query("Health")
FOR EACH entity IN healthEntities
VAR health = entity.getComponent("Health")
IF health.currentHealth <= 0 THEN
entity.setActive(FALSE)
END IF
NEXT
// Draw scene
scene.draw()
GAME.endFrame()
WEND
GAME.close()// Find all entities with Sprite AND Transform
VAR renderables = scene.queryAll("Sprite", "Transform")
// Find all entities with Health AND AI
VAR enemies = scene.queryAll("Health", "AI")VAR parent = scene.createEntity("Parent")
VAR child1 = scene.createEntity("Child1", parent)
VAR child2 = scene.createEntity("Child2", parent)
// When parent moves, children follow (automatic in update)
parent.setPosition(100, 100, 0)// Add component at runtime
IF player.hasComponent("Health") THEN
VAR health = player.getComponent("Health")
health.currentHealth = health.currentHealth - 10
player.setComponentData("Health", health)
END IF
// Remove component
IF player.hasComponent("Sprite") THEN
player.removeComponent("Sprite")
END IF- Component queries are O(n) where n is number of entities with that component
- Use
queryAll()sparingly - it's more expensive than singlequery() - Destroy entities when done to free memory
- Consider component pooling for frequently created/destroyed entities
Planned features:
- Component systems (UpdateSystem, RenderSystem, etc.)
- Component events/callbacks
- Component serialization (save/load)
- Component archetypes/prefabs
- Component dependencies
- Component validation
- Component pooling
- Multi-threaded component updates