Remove ecs

master
Louis Pearson 2022-01-22 13:06:34 -07:00
parent c87da2a4ae
commit 555c200033
2 changed files with 66 additions and 266 deletions

View File

@ -1,191 +0,0 @@
const std = @import("std");
const ArgsTuple = std.meta.Tuple;
const Tuple = std.meta.Tuple;
pub fn World(comptime ComponentBase: type) type {
// Build a component type at comptime based off of ComponentBase. It makes all the fields
// nullable so they are easy to pull out of the store.
const ComponentCon = componentConstructor: {
var fields = std.meta.fields(ComponentBase);
var newFields: [fields.len]std.builtin.TypeInfo.StructField = undefined;
inline for (fields) |field, i| {
const T = field.field_type;
const default: ?T = null;
newFields[i] = std.builtin.TypeInfo.StructField{
.name = field.name,
.field_type = ?T,
.default_value = default,
.is_comptime = false,
.alignment = if (@sizeOf(T) > 0) @alignOf(T) else 0,
};
}
break :componentConstructor @Type(.{ .Struct = .{
.layout = .Auto,
.fields = &newFields,
.decls = &[_]std.builtin.TypeInfo.Declaration{},
.is_tuple = false,
} });
};
return struct {
components: ComponentPool,
alloc: std.mem.Allocator,
pub const Query = ComponentQuery;
pub const Component = ComponentCon;
const ComponentPool = std.MultiArrayList(Component);
const ComponentEnum = std.meta.FieldEnum(Component);
const ComponentSet = std.EnumSet(ComponentEnum);
const ComponentQuery = struct {
required: ComponentSet = ComponentSet.init(.{}),
excluded: ComponentSet = ComponentSet.init(.{}),
pub fn init() @This() {
return @This(){};
}
pub fn query(require_set: []const ComponentEnum, exclude_set: []const ComponentEnum) @This() {
var this = @This(){};
for (require_set) |f| {
this.required.insert(f);
}
for (exclude_set) |f| {
this.excluded.insert(f);
}
return this;
}
pub fn require(require_set: []const ComponentEnum) @This() {
var this = @This(){};
for (require_set) |f| {
this.required.insert(f);
}
return this;
}
pub fn exclude(exclude_set: []const ComponentEnum) @This() {
var this = @This(){};
for (exclude_set) |f| {
this.excluded.insert(f);
}
return this;
}
};
const fields = std.meta.fields(Component);
pub fn init(alloc: std.mem.Allocator) @This() {
return @This(){
.components = ComponentPool{},
.alloc = alloc,
};
}
pub fn create(this: *@This(), component: Component) !usize {
const len = this.components.len;
try this.components.append(this.alloc, component);
return len;
}
pub fn destroy(this: *@This(), entity: usize) void {
// TODO
_ = this;
_ = entity;
@compileError("unimplemented");
}
/// Returns a copy of the components on an entity
pub fn get(this: *@This(), entity: usize) Component {
return this.components.get(entity);
}
pub fn set(this: *@This(), entity: usize, component: Component) void {
this.components.set(entity, component);
}
fn enum2type(comptime enumList: []const ComponentEnum) []type {
var t: [enumList.len]type = undefined;
inline for (enumList) |e, i| {
const field_type = @typeInfo(fields[@enumToInt(e)].field_type);
t[i] = *field_type.Optional.child;
}
return &t;
}
pub fn process(this: *@This(), dt: f32, comptime comp: []const ComponentEnum, func: anytype) void {
const Args = Tuple([_]type{f32} ++ enum2type(comp));
var i = this.iter(Query.require(comp));
while (i.next()) |eID| {
var e = this.get(eID);
var args: Args = undefined;
args[0] = dt;
inline for (comp) |f, j| {
args[j + 1] = &(@field(e, @tagName(f)).?);
}
@call(.{}, func, args);
this.set(eID, e);
}
}
pub fn processWithID(this: *@This(), dt: f32, comptime comp: []const ComponentEnum, func: anytype) void {
const Args = Tuple([_]type{ f32, usize } ++ enum2type(comp));
var i = this.iter(Query.require(comp));
while (i.next()) |eID| {
var e = this.get(eID);
var args: Args = undefined;
args[0] = dt;
args[1] = eID;
inline for (comp) |f, j| {
args[j + 2] = &(@field(e, @tagName(f)).?);
}
@call(.{}, func, args);
this.set(eID, e);
}
}
pub fn iterAll(this: *@This()) Iterator {
return Iterator.init(this, ComponentQuery{});
}
pub fn iter(this: *@This(), query: ComponentQuery) Iterator {
return Iterator.init(this, query);
}
const Self = @This();
const Iterator = struct {
world: *Self,
index: usize,
query: ComponentQuery,
pub fn init(w: *Self, q: ComponentQuery) @This() {
return @This(){
.world = w,
.index = 0,
.query = q,
};
}
pub fn next(this: *@This()) ?usize {
if (this.index == this.world.components.len) return null;
var match = false;
while (!match) {
if (this.index == this.world.components.len) return null;
const e = this.world.components.get(this.index);
match = true;
inline for (fields) |f| {
const fenum = std.meta.stringToEnum(ComponentEnum, f.name) orelse unreachable;
const required = this.query.required.contains(fenum);
const excluded = this.query.excluded.contains(fenum);
const has = @field(e, f.name) != null;
if ((required and !has) or (excluded and has)) {
match = false;
break;
}
}
this.index += 1;
if (match) return this.index - 1;
}
return null;
}
};
};
}

View File

@ -1,6 +1,5 @@
const std = @import("std");
const w4 = @import("wasm4.zig");
const ecs = @import("ecs.zig");
const assets = @import("assets");
const input = @import("input.zig");
const util = @import("util.zig");
@ -271,6 +270,7 @@ export fn update() void {
velocityProcess(1, &player.pos);
physicsProcess(1, &player.pos, &player.physics);
circuitManipulationProcess(1, &player.pos, &player.control);
wireManipulationProcess(1, &player.pos, &player.control);
controlProcess(1, &player.pos, &player.control, &player.physics, &player.kinematic);
kinematicProcess(1, &player.pos, &player.kinematic);
controlAnimProcess(1, &player.sprite, &player.controlAnim, &player.control);
@ -369,84 +369,75 @@ fn circuitManipulationProcess(_: f32, pos: *Pos, control: *Control) void {
}
}
// fn wireManipulationProcess(_: f32, pos: *Pos, control: *Control) void {
// var offset = switch (control.facing) {
// .left => Vec2f{ -6, -4 },
// .right => Vec2f{ 6, -4 },
// .up => Vec2f{ 0, -12 },
// .down => Vec2f{ 0, 4 },
// };
// var offsetPos = pos.pos + offset;
// var entity: World.Component = undefined;
// var mapPos = util.world2cell(offsetPos);
fn wireManipulationProcess(_: f32, pos: *Pos, control: *Control) void {
var offset = switch (control.facing) {
.left => Vec2f{ -6, -4 },
.right => Vec2f{ 6, -4 },
.up => Vec2f{ 0, -12 },
.down => Vec2f{ 0, 4 },
};
var offsetPos = pos.pos + offset;
var mapPos = util.world2cell(offsetPos);
// if (control.grabbing) |details| {
// entity = world.get(details.id);
// var wire = &entity.wire.?;
// var nodes = wire.nodes.slice();
if (control.grabbing) |details| {
var wire = &wires.slice()[details.id];
var nodes = wire.nodes.slice();
// var maxLength = wireMaxLength(wire);
// var length = wireLength(wire);
var maxLength = wireMaxLength(wire);
var length = wireLength(wire);
// if (length > maxLength * 1.5) {
// nodes[details.which].pinned = false;
// control.grabbing = null;
// world.set(details.id, entity);
// return;
// } else {
// nodes[details.which].pos = pos.pos + Vec2f{ 0, -4 };
// }
if (length > maxLength * 1.5) {
nodes[details.which].pinned = false;
control.grabbing = null;
return;
} else {
nodes[details.which].pos = pos.pos + Vec2f{ 0, -4 };
}
// if (Circuit.is_plug(circuit.get_cell(mapPos) orelse 0)) {
// const active = circuit.isEnabled(mapPos);
// indicator = .{ .t = .plug, .pos = mapPos * @splat(2, @as(i32, 8)) + Vec2{ 4, 4 }, .active = active };
// if (input.btnp(.one, .two)) {
// nodes[details.which].pinned = true;
// nodes[details.which].pos = vec2tovec2f(indicator.?.pos);
// nodes[details.which].last = vec2tovec2f(indicator.?.pos);
// control.grabbing = null;
// }
// } else if (input.btnp(.one, .two)) {
// nodes[details.which].pinned = false;
// control.grabbing = null;
// }
// world.set(details.id, entity);
// } else {
// const interactDistance = 4;
// var minDistance: f32 = interactDistance;
// var wireIter = world.iter(WireQuery);
// var interactWireID: ?usize = null;
// var which: usize = 0;
// while (wireIter.next()) |entityID| {
// entity = world.get(entityID);
// const wire = entity.wire.?;
// const nodes = wire.nodes.constSlice();
// const begin = nodes[0].pos;
// const end = nodes[wire.nodes.len - 1].pos;
// var dist = util.distancef(begin, offsetPos);
// if (dist < minDistance) {
// minDistance = dist;
// indicator = .{ .t = .wire, .pos = vec2ftovec2(begin), .active = wire.enabled };
// interactWireID = entityID;
// which = 0;
// }
// dist = util.distancef(end, offsetPos);
// if (dist < minDistance) {
// minDistance = dist;
// indicator = .{ .t = .wire, .pos = vec2ftovec2(end), .active = wire.enabled };
// interactWireID = entityID;
// which = wire.nodes.len - 1;
// }
// }
// if (interactWireID) |wireID| {
// entity = world.get(wireID);
// if (input.btnp(.one, .two)) {
// control.grabbing = .{ .id = wireID, .which = which };
// }
// world.set(wireID, entity);
// }
// }
// }
if (Circuit.is_plug(circuit.get_cell(mapPos) orelse 0)) {
const active = circuit.isEnabled(mapPos);
indicator = .{ .t = .plug, .pos = mapPos * @splat(2, @as(i32, 8)) + Vec2{ 4, 4 }, .active = active };
if (input.btnp(.one, .two)) {
nodes[details.which].pinned = true;
nodes[details.which].pos = vec2tovec2f(indicator.?.pos);
nodes[details.which].last = vec2tovec2f(indicator.?.pos);
control.grabbing = null;
}
} else if (input.btnp(.one, .two)) {
nodes[details.which].pinned = false;
control.grabbing = null;
}
} else {
const interactDistance = 4;
var minDistance: f32 = interactDistance;
var interactWireID: ?usize = null;
var which: usize = 0;
for (wires.slice()) |*wire, wireID| {
const nodes = wire.nodes.constSlice();
const begin = nodes[0].pos;
const end = nodes[wire.nodes.len - 1].pos;
var dist = util.distancef(begin, offsetPos);
if (dist < minDistance) {
minDistance = dist;
indicator = .{ .t = .wire, .pos = vec2ftovec2(begin), .active = wire.enabled };
interactWireID = wireID;
which = 0;
}
dist = util.distancef(end, offsetPos);
if (dist < minDistance) {
minDistance = dist;
indicator = .{ .t = .wire, .pos = vec2ftovec2(end), .active = wire.enabled };
interactWireID = wireID;
which = wire.nodes.len - 1;
}
}
if (interactWireID) |wireID| {
if (input.btnp(.one, .two)) {
control.grabbing = .{ .id = wireID, .which = which };
}
}
}
}
fn wirePhysicsProcess(dt: f32, wire: *Wire) void {
var nodes = wire.nodes.slice();