Database now handles entities

master
Louis Pearson 2022-08-08 18:00:25 -06:00
parent a35d481b15
commit 240587344d
4 changed files with 162 additions and 122 deletions

View File

@ -207,6 +207,7 @@ fn loadLevel(lvl: usize) !void {
map.clear(); map.clear();
circuit.clearMap(); circuit.clearMap();
level = try db.levelLoad(alloc, lvl); level = try db.levelLoad(alloc, lvl);
const levelc = world.Coordinate.fromWorld(level.world_x, level.world_y);
try extract.extractLevel(.{ try extract.extractLevel(.{
.alloc = frame_alloc, .alloc = frame_alloc,
@ -225,9 +226,11 @@ fn loadLevel(lvl: usize) !void {
{ {
_ = try wires.resize(0); _ = try wires.resize(0);
var a: usize = 0; var a: usize = 0;
while (level.getWire(a)) |wire| : (a += 1) { while (db.getWire(level, a)) |wire| : (a += 1) {
const p1 = util.vec2ToVec2f(Vec2{ wire[0].x, wire[0].y } * tile_size + Vec2{ 4, 4 }); const coord0 = wire[0].coord.subC(levelc);
const p2 = util.vec2ToVec2f(Vec2{ wire[1].x, wire[1].y } * tile_size + Vec2{ 4, 4 }); const coord1 = wire[1].coord.subC(levelc);
const p1 = util.vec2ToVec2f(coord0.toVec2() * tile_size + Vec2{ 4, 4 });
const p2 = util.vec2ToVec2f(coord1.toVec2() * tile_size + Vec2{ 4, 4 });
var w = try wires.addOne(); var w = try wires.addOne();
_ = try w.nodes.resize(0); _ = try w.nodes.resize(0);
@ -249,15 +252,16 @@ fn loadLevel(lvl: usize) !void {
{ {
var i: usize = 0; var i: usize = 0;
while (level.getDoor(i)) |door| : (i += 1) { while (db.getDoor(level, i)) |door| : (i += 1) {
try circuit.addDoor(Vec2{ door.x, door.y }); const coord = door.coord.subC(levelc);
try circuit.addDoor(coord.toVec2());
} }
} }
{ {
var i: usize = 0; var i: usize = 0;
while (level.getJoin(i)) |join| : (i += 1) { while (level.getJoin(i)) |join| : (i += 1) {
const globalc = Coord.fromWorld(level.world_x, level.world_y).addC(join); const globalc = levelc.addC(join);
var e = false; var e = false;
if (db.isEnergized(globalc)) { if (db.isEnergized(globalc)) {
e = true; e = true;
@ -270,9 +274,10 @@ fn loadLevel(lvl: usize) !void {
try coins.resize(0); try coins.resize(0);
// if (!try Disk.load()) { // if (!try Disk.load()) {
var i: usize = 0; var i: usize = 0;
while (level.getCoin(i)) |coin| : (i += 1) { while (db.getCoin(level, i)) |coin| : (i += 1) {
const coord = coin.coord.subC(levelc);
try coins.append(.{ try coins.append(.{
.pos = Pos.init(util.vec2ToVec2f(Vec2{ coin.x, coin.y } * tile_size)), .pos = Pos.init(util.vec2ToVec2f(coord.toVec2() * tile_size)),
.sprite = .{ .offset = .{ 0, 0 }, .size = .{ 8, 8 }, .index = 4, .flags = .{ .bpp = .b2 } }, .sprite = .{ .offset = .{ 0, 0 }, .size = .{ 8, 8 }, .index = 4, .flags = .{ .bpp = .b2 } },
.anim = Anim{ .anim = &anim_store.coin }, .anim = Anim{ .anim = &anim_store.coin },
.area = .{ .pos = .{ 0, 0 }, .size = .{ 8, 8 } }, .area = .{ .pos = .{ 0, 0 }, .size = .{ 8, 8 } },
@ -342,18 +347,20 @@ pub fn start() !void {
db = try world.Database.init(db_alloc); db = try world.Database.init(db_alloc);
try loadLevel(0); const spawn = db.getSpawn();
const spawnArr = level.getSpawn() orelse return error.NoPlayerSpawn; const spawn_worldc = spawn.coord.toWorld();
const spawn = Vec2{ spawnArr[0], spawnArr[1] }; const first_level = db.findLevel(spawn_worldc[0], spawn_worldc[1]) orelse return error.SpawnOutOfBounds;
camera = @divTrunc(spawn, @splat(2, @as(i32, 20))) * @splat(2, @as(i32, 20)); try loadLevel(first_level);
camera = @divTrunc(spawn.coord.toVec2(), @splat(2, @as(i32, 20))) * @splat(2, @as(i32, 20));
const tile_size = Vec2{ 8, 8 }; const tile_size = Vec2{ 8, 8 };
const offset = Vec2{ 4, 8 }; const offset = Vec2{ 4, 8 };
player = .{ player = .{
.pos = Pos.init(util.vec2ToVec2f(spawn * tile_size + offset)), .pos = Pos.init(util.vec2ToVec2f(spawn.coord.toVec2() * tile_size + offset)),
.control = .{ .controller = .player, .state = .stand }, .control = .{ .controller = .player, .state = .stand },
.sprite = .{ .offset = .{ -4, -8 }, .size = .{ 8, 8 }, .index = 8, .flags = .{ .bpp = .b2 } }, .sprite = .{ .offset = .{ -4, -8 }, .size = .{ 8, 8 }, .index = 8, .flags = .{ .bpp = .b2 } },
.physics = .{ .friction = Vec2f{ 0.15, 0.1 }, .gravity = Vec2f{ 0, 0.25 } }, .physics = .{ .friction = Vec2f{ 0.15, 0.1 }, .gravity = Vec2f{ 0, 0.25 } },
@ -713,15 +720,19 @@ fn updateCircuit() !void {
// Add doors to map // Add doors to map
var i: usize = 0; var i: usize = 0;
while (level.getDoor(i)) |door| : (i += 1) { while (db.getDoor(level, i)) |door| : (i += 1) {
const tile: u8 = if (door.kind == .Door) world.Tiles.Door else world.Tiles.Trapdoor; const tile: u8 = if (door.kind == .Door) world.Tiles.Door else world.Tiles.Trapdoor;
try map.set_cell(.{ door.x, door.y }, tile); const globalc = world.Coordinate.fromWorld(level.world_x, level.world_y);
const coord = door.coord.subC(globalc);
w4.tracef("[getDoor] (%d, %d)", coord.val[0], coord.val[1]);
try map.set_cell(coord.toVec2(), tile);
} }
// Remove doors that have been unlocked // Remove doors that have been unlocked
const enabledDoors = try circuit.enabledDoors(frame_alloc); const enabledDoors = try circuit.enabledDoors(frame_alloc);
defer frame_alloc.free(enabledDoors.items); defer frame_alloc.free(enabledDoors.items);
for (enabledDoors.items) |door| { for (enabledDoors.items) |door| {
w4.tracef("[enabledDoors] (%d, %d)", door[0], door[1]);
try map.set_cell(door, world.Tiles.Empty); try map.set_cell(door, world.Tiles.Empty);
} }

View File

@ -50,7 +50,7 @@ export fn update() void {
error.EndOfStream => showErr(@errorName(e)), error.EndOfStream => showErr(@errorName(e)),
error.OutOfMemory => showErr(@errorName(e)), error.OutOfMemory => showErr(@errorName(e)),
error.NullTiles => showErr(@errorName(e)), error.NullTiles => showErr(@errorName(e)),
error.NoPlayerSpawn => showErr(@errorName(e)), error.SpawnOutOfBounds => showErr(@errorName(e)),
error.InvalidLevel => showErr(@errorName(e)), error.InvalidLevel => showErr(@errorName(e)),
}, },
} }

View File

@ -178,20 +178,37 @@ pub const Coordinate = struct {
return .{ .val = .{ coord.val[0] + val[0], coord.val[1] + val[1] } }; return .{ .val = .{ coord.val[0] + val[0], coord.val[1] + val[1] } };
} }
pub fn sub(coord: Coordinate, val: [2]i16) Coordinate {
return .{ .val = .{ coord.val[0] - val[0], coord.val[1] - val[1] } };
}
pub fn addC(coord: Coordinate, other: Coordinate) Coordinate { pub fn addC(coord: Coordinate, other: Coordinate) Coordinate {
return .{ .val = .{ coord.val[0] + other.val[0], coord.val[1] + other.val[1] } }; return .{ .val = .{ coord.val[0] + other.val[0], coord.val[1] + other.val[1] } };
} }
pub fn subC(coord: Coordinate, other: Coordinate) Coordinate {
return .{ .val = .{ coord.val[0] - other.val[0], coord.val[1] - other.val[1] } };
}
pub fn eq(coord: Coordinate, other: Coordinate) bool { pub fn eq(coord: Coordinate, other: Coordinate) bool {
return coord.val[0] == other.val[0] and coord.val[1] == other.val[1]; return coord.val[0] == other.val[0] and coord.val[1] == other.val[1];
} }
pub fn within(coord: Coord, nw: Coord, se: Coord) bool {
return coord.val[0] >= nw.val[0] and coord.val[1] >= nw.val[1] and
coord.val[0] < se.val[0] and coord.val[1] < se.val[1];
}
pub fn toWorld(coord: Coordinate) [2]i8 { pub fn toWorld(coord: Coordinate) [2]i8 {
const world_x = @intCast(i8, @divFloor(coord.val[0], LEVELSIZE)); const world_x = @intCast(i8, @divFloor(coord.val[0], LEVELSIZE));
const world_y = @intCast(i8, @divFloor(coord.val[1], LEVELSIZE)); const world_y = @intCast(i8, @divFloor(coord.val[1], LEVELSIZE));
return .{ world_x, world_y }; return .{ world_x, world_y };
} }
pub fn toVec2(coord: Coordinate) @Vector(2, i32) {
return .{ coord.val[0], coord.val[1] };
}
pub fn fromWorld(x: i8, y: i8) Coordinate { pub fn fromWorld(x: i8, y: i8) Coordinate {
return .{ .val = .{ return .{ .val = .{
@intCast(i16, x) * 20, @intCast(i16, x) * 20,
@ -222,50 +239,37 @@ pub const Level = struct {
world_y: i8, world_y: i8,
width: u16, width: u16,
size: u16, size: u16,
entity_count: u16,
tiles: ?[]TileData, tiles: ?[]TileData,
entities: ?[]Entity = null,
pub fn init(x: u8, y: u8, width: u16, buf: []TileData, entities: []Entity) Level { pub fn init(x: u8, y: u8, width: u16, buf: []TileData) Level {
return Level{ return Level{
.world_x = x, .world_x = x,
.world_y = y, .world_y = y,
.width = width, .width = width,
.size = buf.len, .size = buf.len,
.entity_count = entities.len,
.tiles = buf, .tiles = buf,
.entities = entities,
}; };
} }
pub fn calculateSize(level: Level) !usize { pub fn calculateSize(level: Level) !usize {
const tiles = level.tiles orelse return error.NullTiles; const tiles = level.tiles orelse return error.NullTiles;
const entities = level.entities orelse return error.NullEntities;
return @sizeOf(i8) + // world_x return @sizeOf(i8) + // world_x
@sizeOf(i8) + // world_y @sizeOf(i8) + // world_y
@sizeOf(u16) + // width @sizeOf(u16) + // width
@sizeOf(u16) + // size @sizeOf(u16) + // size
@sizeOf(u16) + // entity_count tiles.len;
tiles.len + //
entities.len * 5;
} }
pub fn write(level: Level, writer: anytype) !void { pub fn write(level: Level, writer: anytype) !void {
var tiles = level.tiles orelse return error.NullTiles; var tiles = level.tiles orelse return error.NullTiles;
var entities = level.entities orelse return error.NullEntities;
try writer.writeInt(i8, level.world_x, .Little); try writer.writeInt(i8, level.world_x, .Little);
try writer.writeInt(i8, level.world_y, .Little); try writer.writeInt(i8, level.world_y, .Little);
try writer.writeInt(u16, level.width, .Little); try writer.writeInt(u16, level.width, .Little);
try writer.writeInt(u16, level.size, .Little); try writer.writeInt(u16, level.size, .Little);
try writer.writeInt(u16, level.entity_count, .Little);
for (tiles) |tile| { for (tiles) |tile| {
try writer.writeByte(tile.toByte()); try writer.writeByte(tile.toByte());
} }
for (entities) |entity| {
try entity.write(writer);
}
} }
pub fn read(reader: anytype) !Level { pub fn read(reader: anytype) !Level {
@ -274,9 +278,7 @@ pub const Level = struct {
.world_y = try reader.readInt(i8, .Little), .world_y = try reader.readInt(i8, .Little),
.width = try reader.readInt(u16, .Little), .width = try reader.readInt(u16, .Little),
.size = try reader.readInt(u16, .Little), .size = try reader.readInt(u16, .Little),
.entity_count = try reader.readInt(u16, .Little),
.tiles = null, .tiles = null,
.entities = null,
}; };
} }
@ -289,25 +291,6 @@ pub const Level = struct {
} }
} }
pub fn readEntities(level: *Level, reader: anytype, buf: []Entity) !void {
std.debug.assert(buf.len >= level.entity_count);
level.entities = buf;
var i: usize = 0;
while (i < level.entity_count) : (i += 1) {
buf[i] = try Entity.read(reader);
}
}
pub fn getSpawn(level: *Level) ?[2]i16 {
std.debug.assert(level.entities != null);
for (level.entities.?) |entity| {
if (entity.kind == .Player) {
return [2]i16{ entity.x, entity.y };
}
}
return null;
}
pub fn getTile(level: Level, globalc: Coord) ?TileData { pub fn getTile(level: Level, globalc: Coord) ?TileData {
const tiles = level.tiles orelse return null; const tiles = level.tiles orelse return null;
const worldc = globalc.toLevelTopLeft(); const worldc = globalc.toLevelTopLeft();
@ -338,47 +321,6 @@ pub const Level = struct {
} }
return null; return null;
} }
pub fn getWire(level: *Level, num: usize) ?[2]Entity {
std.debug.assert(level.entities != null);
var node_begin: ?Entity = null;
var wire_count: usize = 0;
for (level.entities.?) |entity| {
if (entity.kind == .WireNode or entity.kind == .WireAnchor) {
node_begin = entity;
} else if (entity.kind == .WireEndNode or entity.kind == .WireEndAnchor) {
if (node_begin) |begin| {
if (wire_count == num) return [2]Entity{ begin, entity };
}
wire_count += 1;
}
}
return null;
}
pub fn getDoor(level: *Level, num: usize) ?Entity {
std.debug.assert(level.entities != null);
var count: usize = 0;
for (level.entities.?) |entity| {
if (entity.kind == .Door or entity.kind == .Trapdoor) {
if (count == num) return entity;
count += 1;
}
}
return null;
}
pub fn getCoin(level: *Level, num: usize) ?Entity {
std.debug.assert(level.entities != null);
var count: usize = 0;
for (level.entities.?) |entity| {
if (entity.kind == .Coin) {
if (count == num) return entity;
count += 1;
}
}
return null;
}
}; };
// AutoTile algorithm datatypes // AutoTile algorithm datatypes
@ -493,8 +435,7 @@ pub const EntityKind = enum(u8) {
pub const Entity = struct { pub const Entity = struct {
kind: EntityKind, kind: EntityKind,
x: i16, coord: Coordinate,
y: i16,
pub fn calculateSize() usize { pub fn calculateSize() usize {
return @sizeOf(u8) + // kind return @sizeOf(u8) + // kind
@ -504,15 +445,13 @@ pub const Entity = struct {
pub fn write(entity: Entity, writer: anytype) !void { pub fn write(entity: Entity, writer: anytype) !void {
try writer.writeInt(u8, @enumToInt(entity.kind), .Little); try writer.writeInt(u8, @enumToInt(entity.kind), .Little);
try writer.writeInt(i16, entity.x, .Little); try entity.coord.write(writer);
try writer.writeInt(i16, entity.y, .Little);
} }
pub fn read(reader: anytype) !Entity { pub fn read(reader: anytype) !Entity {
return Entity{ return Entity{
.kind = @intToEnum(EntityKind, try reader.readInt(u8, .Little)), .kind = @intToEnum(EntityKind, try reader.readInt(u8, .Little)),
.x = try reader.readInt(i16, .Little), .coord = try Coordinate.read(reader),
.y = try reader.readInt(i16, .Little),
}; };
} }
}; };
@ -546,11 +485,14 @@ pub const LevelHeader = struct {
pub fn write( pub fn write(
writer: anytype, writer: anytype,
level_headers: []LevelHeader, level_headers: []LevelHeader,
entities: []Entity,
circuit_nodes: []CircuitNode, circuit_nodes: []CircuitNode,
levels: []Level, levels: []Level,
) !void { ) !void {
// Write number of levels // Write number of levels
try writer.writeInt(u16, @intCast(u16, level_headers.len), .Little); try writer.writeInt(u16, @intCast(u16, level_headers.len), .Little);
// Write number of entities
try writer.writeInt(u16, @intCast(u16, entities.len), .Little);
// Write number of circuit nodes // Write number of circuit nodes
try writer.writeInt(u16, @intCast(u16, circuit_nodes.len), .Little); try writer.writeInt(u16, @intCast(u16, circuit_nodes.len), .Little);
@ -559,6 +501,11 @@ pub fn write(
try lvl_header.write(writer); try lvl_header.write(writer);
} }
// Write entity data
for (entities) |entity| {
try entity.write(writer);
}
// Write node data // Write node data
for (circuit_nodes) |node| { for (circuit_nodes) |node| {
try node.write(writer); try node.write(writer);
@ -574,6 +521,7 @@ const Cursor = std.io.FixedBufferStream([]const u8);
pub const Database = struct { pub const Database = struct {
cursor: Cursor, cursor: Cursor,
level_info: []LevelHeader, level_info: []LevelHeader,
entities: []Entity,
circuit_info: []CircuitNode, circuit_info: []CircuitNode,
level_data_begin: usize, level_data_begin: usize,
@ -589,6 +537,8 @@ pub const Database = struct {
// read number of levels // read number of levels
const level_count = try reader.readInt(u16, .Little); const level_count = try reader.readInt(u16, .Little);
// read number of entities
const entity_count = try reader.readInt(u16, .Little);
// read number of nodes // read number of nodes
const node_count = try reader.readInt(u16, .Little); const node_count = try reader.readInt(u16, .Little);
@ -599,23 +549,34 @@ pub const Database = struct {
level_headers[i] = try LevelHeader.read(reader); level_headers[i] = try LevelHeader.read(reader);
} }
// read entities
var entities = try alloc.alloc(Entity, entity_count);
for (entities) |_, i| {
entities[i] = try Entity.read(reader);
}
// read circuits
var circuit_nodes = try alloc.alloc(CircuitNode, node_count); var circuit_nodes = try alloc.alloc(CircuitNode, node_count);
// read headers
for (circuit_nodes) |_, i| { for (circuit_nodes) |_, i| {
circuit_nodes[i] = try CircuitNode.read(reader); circuit_nodes[i] = try CircuitNode.read(reader);
} }
// Save where the rest of the data ended, and the level data begins
var level_data_begin = @intCast(usize, try cursor.getPos()); var level_data_begin = @intCast(usize, try cursor.getPos());
return Database{ return Database{
.cursor = cursor, .cursor = cursor,
.level_info = level_headers, .level_info = level_headers,
.entities = entities,
.circuit_info = circuit_nodes, .circuit_info = circuit_nodes,
.level_data_begin = level_data_begin, .level_data_begin = level_data_begin,
}; };
} }
// Level functions
pub fn levelInfo(db: *Database, level: usize) !Level { pub fn levelInfo(db: *Database, level: usize) !Level {
if (level > db.level_info.len) return error.InvalidLevel; if (level > db.level_info.len) return error.InvalidLevel;
try db.cursor.seekTo(db.level_data_begin + db.level_info[level].offset); try db.cursor.seekTo(db.level_data_begin + db.level_info[level].offset);
@ -632,9 +593,6 @@ pub const Database = struct {
var level_buf = try alloc.alloc(TileData, level_info.size); var level_buf = try alloc.alloc(TileData, level_info.size);
try level_info.readTiles(reader, level_buf); try level_info.readTiles(reader, level_buf);
var entity_buf = try alloc.alloc(Entity, level_info.entity_count);
try level_info.readEntities(reader, entity_buf);
return level_info; return level_info;
} }
@ -647,6 +605,8 @@ pub const Database = struct {
return null; return null;
} }
// Circuit functions
fn getNodeID(db: *Database, coord: Coord) ?NodeID { fn getNodeID(db: *Database, coord: Coord) ?NodeID {
for (db.circuit_info) |node, i| { for (db.circuit_info) |node, i| {
if (!coord.eq(node.coord)) continue; if (!coord.eq(node.coord)) continue;
@ -752,6 +712,66 @@ pub const Database = struct {
if (i == 0) break; if (i == 0) break;
} }
} }
// Entity functions
pub fn getWire(database: *Database, level: Level, num: usize) ?[2]Entity {
const nw = Coord.fromWorld(level.world_x, level.world_y);
const se = nw.add(.{ 20, 20 });
var node_begin: ?Entity = null;
var wire_count: usize = 0;
for (database.entities) |entity| {
if (!entity.coord.within(nw, se)) continue;
if (entity.kind == .WireNode or entity.kind == .WireAnchor) {
node_begin = entity;
} else if (entity.kind == .WireEndNode or entity.kind == .WireEndAnchor) {
if (node_begin) |begin| {
if (wire_count == num) return [2]Entity{ begin, entity };
}
wire_count += 1;
}
}
return null;
}
pub fn getDoor(database: *Database, level: Level, num: usize) ?Entity {
const nw = Coord.fromWorld(level.world_x, level.world_y);
const se = nw.add(.{ 20, 20 });
var count: usize = 0;
for (database.entities) |entity| {
if (!entity.coord.within(nw, se)) continue;
if (entity.kind == .Door or entity.kind == .Trapdoor) {
if (count == num) return entity;
count += 1;
}
}
return null;
}
pub fn getCoin(database: *Database, level: Level, num: usize) ?Entity {
const nw = Coord.fromWorld(level.world_x, level.world_y);
const se = nw.add(.{ 20, 20 });
var count: usize = 0;
for (database.entities) |entity| {
if (!entity.coord.within(nw, se)) continue;
if (entity.kind == .Coin) {
if (count == num) return entity;
count += 1;
}
}
return null;
}
/// Returns the players spawn location.
/// Assumes a spawn exists and that there is only one of them
pub fn getSpawn(database: *Database) Entity {
for (database.entities) |entity| {
if (entity.kind == .Player) {
return entity;
}
}
@panic("No player spawn found! Invalid state");
}
}; };
// All levels in the game. If two rooms are next to each other, they // All levels in the game. If two rooms are next to each other, they

View File

@ -55,10 +55,11 @@ fn make(step: *std.build.Step) !void {
var levels = std.ArrayList(world.Level).init(allocator); var levels = std.ArrayList(world.Level).init(allocator);
defer levels.deinit(); defer levels.deinit();
for (ldtk.levels) |level| { var entity_array = std.ArrayList(world.Entity).init(allocator);
var entity_array = std.ArrayList(world.Entity).init(allocator); defer entity_array.deinit();
defer entity_array.deinit();
for (ldtk.levels) |level| {
std.log.warn("Level: {}", .{levels.items.len});
const parsed_level = try parseLevel(.{ const parsed_level = try parseLevel(.{
.allocator = allocator, .allocator = allocator,
.ldtk = ldtk, .ldtk = ldtk,
@ -70,7 +71,6 @@ fn make(step: *std.build.Step) !void {
} }
defer for (levels.items) |level| { defer for (levels.items) |level| {
allocator.free(level.tiles.?); allocator.free(level.tiles.?);
allocator.free(level.entities.?);
}; };
var circuit = try buildCircuit(allocator, levels.items); var circuit = try buildCircuit(allocator, levels.items);
@ -109,7 +109,7 @@ fn make(step: *std.build.Step) !void {
defer data.deinit(); defer data.deinit();
const writer = data.writer(); const writer = data.writer();
try world.write(writer, level_headers.items, circuit.items, levels.items); try world.write(writer, level_headers.items, entity_array.items, circuit.items, levels.items);
// Open output file and write data into it // Open output file and write data into it
cwd.makePath(this.builder.getInstallPath(.lib, "")) catch |e| switch (e) { cwd.makePath(this.builder.getInstallPath(.lib, "")) catch |e| switch (e) {
@ -163,20 +163,28 @@ fn parseLevel(opt: struct {
// Parsing code for wire entities. They're a little more complex // Parsing code for wire entities. They're a little more complex
// than the rest // than the rest
if (kind_opt) |kind| { if (kind_opt) |kind| {
const levelc = world.Coordinate.fromWorld(world_x, world_y);
if (kind != .WireNode) { if (kind != .WireNode) {
const entc = world.Coordinate.init(.{
@intCast(i16, entity.__grid[0]),
@intCast(i16, entity.__grid[1]),
});
const world_entity = world.Entity{ const world_entity = world.Entity{
.kind = kind, .kind = kind,
.x = @intCast(i16, entity.__grid[0]), .coord = levelc.addC(entc)
.y = @intCast(i16, entity.__grid[1]),
}; };
try entity_array.append(world_entity); try entity_array.append(world_entity);
} else { } else {
const p1_x: i16 = @intCast(i16, entity.__grid[0]);
const p1_y: i16 = @intCast(i16, entity.__grid[1]);
var anchor1 = false; var anchor1 = false;
var anchor2 = false; var anchor2 = false;
var p2_x: i16 = p1_x; const p1_c = world.Coordinate.init(.{
var p2_y: i16 = p1_y; @intCast(i16, entity.__grid[0]),
@intCast(i16, entity.__grid[1]),
});
var p2_c = world.Coordinate.init(.{
@intCast(i16, entity.__grid[0]),
@intCast(i16, entity.__grid[1]),
});
for (entity.fieldInstances) |field| { for (entity.fieldInstances) |field| {
if (std.mem.eql(u8, field.__identifier, "Anchor")) { if (std.mem.eql(u8, field.__identifier, "Anchor")) {
const anchors = field.__value.Array.items; const anchors = field.__value.Array.items;
@ -187,26 +195,28 @@ fn parseLevel(opt: struct {
const endpoint = field.__value.Array.items[end]; const endpoint = field.__value.Array.items[end];
const x = endpoint.Object.get("cx").?; const x = endpoint.Object.get("cx").?;
const y = endpoint.Object.get("cy").?; const y = endpoint.Object.get("cy").?;
p2_x = @intCast(i16, x.Integer); p2_c.val = .{
p2_y = @intCast(i16, y.Integer); @intCast(i16, x.Integer),
@intCast(i16, y.Integer),
};
} }
} }
const wire_begin = world.Entity{ const wire_begin = world.Entity{
.kind = if (anchor1) .WireAnchor else .WireNode, .kind = if (anchor1) .WireAnchor else .WireNode,
.x = p1_x, .coord = p1_c.addC(levelc),
.y = p1_y,
}; };
try entity_array.append(wire_begin); try entity_array.append(wire_begin);
const wire_end = world.Entity{ const wire_end = world.Entity{
.kind = if (anchor2) .WireEndAnchor else .WireEndNode, .kind = if (anchor2) .WireEndAnchor else .WireEndNode,
.x = p2_x, .coord = p2_c.addC(levelc),
.y = p2_y,
}; };
try entity_array.append(wire_end); try entity_array.append(wire_end);
} }
} }
} }
std.log.warn("Entities: {}", .{entity_array.items.len});
} else if (std.mem.eql(u8, layer.__identifier, "Circuit")) { } else if (std.mem.eql(u8, layer.__identifier, "Circuit")) {
// Circuit // Circuit
std.debug.assert(layer.__type == .IntGrid); std.debug.assert(layer.__type == .IntGrid);
@ -235,14 +245,13 @@ fn parseLevel(opt: struct {
const width = @intCast(u16, circuit.__cWid); const width = @intCast(u16, circuit.__cWid);
const size = @intCast(u16, width * circuit.__cHei); const size = @intCast(u16, width * circuit.__cHei);
// Entities go into global scope now
var parsed_level = world.Level{ var parsed_level = world.Level{
.world_x = world_x, .world_x = world_x,
.world_y = world_y, .world_y = world_y,
.width = @intCast(u16, width), .width = @intCast(u16, width),
.size = @intCast(u16, size), .size = @intCast(u16, size),
.entity_count = @intCast(u16, entity_array.items.len),
.tiles = try allocator.alloc(world.TileData, size), .tiles = try allocator.alloc(world.TileData, size),
.entities = try allocator.dupe(world.Entity, entity_array.items),
}; };
const tiles = parsed_level.tiles.?; const tiles = parsed_level.tiles.?;