mach/ecs/src/main.zig

99 lines
3.4 KiB
Zig

//! mach/ecs is an Entity component system implementation.
//!
//! ## Design principles:
//!
//! * Clean-room implementation (author has not read any other ECS implementation code.)
//! * Solve the problems ECS solves, in a way that is natural to Zig and leverages Zig comptime.
//! * Avoid patent infringement upon Unity ECS patent claims.
//! * Fast. Optimal for CPU caches, multi-threaded, leverage comptime as much as is reasonable.
//! * Simple. Small API footprint, should be natural and fun - not like you're writing boilerplate.
//! * Enable other libraries to provide tracing, editors, visualizers, profilers, etc.
//!
//! ## Copyright & patent mitigation
//!
//! The initial implementation was a clean-room implementation by Stephen Gutekanst without having
//! read other ECS implementations' code, but with speaking to people familiar with other ECS
//! implementations. Contributions past the initial implementation may be made by individuals in
//! non-clean-room settings.
//!
//! Critically, this entity component system stores components for a classified archetype using
//! independent arrays allocated per component as well as hashmaps for sparse component data as an
//! optimization. This is a novel and fundamentally different process than what is described in
//! Unity Software Inc's patent US 10,599,560. This is not legal advice.
//!
const std = @import("std");
const testing = std.testing;
pub const EntityID = @import("entities.zig").EntityID;
pub const Entities = @import("entities.zig").Entities;
pub const Module = @import("systems.zig").Module;
pub const Modules = @import("systems.zig").Modules;
pub const Messages = @import("systems.zig").Messages;
pub const MessagesTag = @import("systems.zig").MessagesTag;
pub const World = @import("systems.zig").World;
// TODO:
// * Iteration
// * Querying
// * Multi threading
// * Multiple entities having one value
// * Sparse storage?
test "inclusion" {
std.testing.refAllDeclsRecursive(@This());
}
test "example" {
const allocator = testing.allocator;
const PhysicsMsg = Messages(.{
.tick = void,
});
const physicsUpdate = (struct {
pub fn physicsUpdate(msg: PhysicsMsg) void {
switch (msg) {
.tick => std.debug.print("\nphysics tick!\n", .{}),
}
}
}).physicsUpdate;
const modules = Modules(.{
.physics = Module(.{
.components = .{
.id = u32,
},
.globals = struct {
pointer: u8,
},
.messages = PhysicsMsg,
.update = physicsUpdate,
}),
.renderer = Module(.{
.components = .{
.id = u16,
},
}),
});
//-------------------------------------------------------------------------
// Create a world.
var world = try World(modules).init(allocator);
defer world.deinit();
// Initialize globals.
world.set(.physics, .pointer, 123);
_ = world.get(.physics, .pointer); // == 123
const player1 = try world.entities.new();
const player2 = try world.entities.new();
const player3 = try world.entities.new();
try world.entities.setComponent(player1, .physics, .id, 1234);
try world.entities.setComponent(player1, .renderer, .id, 1234);
try world.entities.setComponent(player2, .physics, .id, 1234);
try world.entities.setComponent(player3, .physics, .id, 1234);
world.tick();
}