Begin splitting game.zig
parent
d0d47d850d
commit
ae34313849
|
@ -0,0 +1,59 @@
|
||||||
|
const std = @import("std");
|
||||||
|
const w4 = @import("wasm4.zig");
|
||||||
|
const util = @import("util.zig");
|
||||||
|
const Vec2 = util.Vec2;
|
||||||
|
const Vec2f = util.Vec2f;
|
||||||
|
const AABB = util.AABB;
|
||||||
|
const Anim = @import("anim.zig");
|
||||||
|
|
||||||
|
const approxEqAbs = std.math.approxEqAbs;
|
||||||
|
const AnimData = []const Anim.Ops;
|
||||||
|
|
||||||
|
// Components
|
||||||
|
pub const Pos = struct {
|
||||||
|
pos: Vec2f,
|
||||||
|
last: Vec2f,
|
||||||
|
pinned: bool = false,
|
||||||
|
pub fn init(pos: Vec2f) @This() {
|
||||||
|
return @This(){ .pos = pos, .last = pos };
|
||||||
|
}
|
||||||
|
pub fn initVel(pos: Vec2f, vel: Vec2f) @This() {
|
||||||
|
return @This(){ .pos = pos, .last = pos - vel };
|
||||||
|
}
|
||||||
|
};
|
||||||
|
pub const Control = struct {
|
||||||
|
controller: enum { player },
|
||||||
|
state: enum { stand, walk, jump, fall, wallSlide },
|
||||||
|
facing: enum { left, right, up, down } = .right,
|
||||||
|
grabbing: ?struct { id: usize, which: usize } = null,
|
||||||
|
};
|
||||||
|
pub const Sprite = struct {
|
||||||
|
offset: Vec2 = Vec2{ 0, 0 },
|
||||||
|
size: w4.Vec2,
|
||||||
|
index: usize,
|
||||||
|
flags: w4.BlitFlags,
|
||||||
|
};
|
||||||
|
pub const StaticAnim = Anim;
|
||||||
|
pub const ControlAnim = struct { anims: []AnimData, state: Anim };
|
||||||
|
pub const Kinematic = struct {
|
||||||
|
col: AABB,
|
||||||
|
move: Vec2f = Vec2f{ 0, 0 },
|
||||||
|
lastCol: Vec2f = Vec2f{ 0, 0 },
|
||||||
|
|
||||||
|
pub fn inAir(this: @This()) bool {
|
||||||
|
return approxEqAbs(f32, this.lastCol[1], 0, 0.01);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn onFloor(this: @This()) bool {
|
||||||
|
return approxEqAbs(f32, this.move[1], 0, 0.01) and this.lastCol[1] > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn isFalling(this: @This()) bool {
|
||||||
|
return this.move[1] > 0 and approxEqAbs(f32, this.lastCol[1], 0, 0.01);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn onWall(this: @This()) bool {
|
||||||
|
return this.isFalling() and !approxEqAbs(f32, this.lastCol[0], 0, 0.01);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
pub const Physics = struct { gravity: Vec2f, friction: Vec2f };
|
|
@ -0,0 +1,243 @@
|
||||||
|
const assets = @import("assets");
|
||||||
|
const std = @import("std");
|
||||||
|
const util = @import("util.zig");
|
||||||
|
const w4 = @import("wasm4.zig");
|
||||||
|
const game = @import("game.zig");
|
||||||
|
const comp = @import("component.zig");
|
||||||
|
const Anim = @import("anim.zig");
|
||||||
|
|
||||||
|
const Pos = comp.Pos;
|
||||||
|
const Vec2 = util.Vec2;
|
||||||
|
|
||||||
|
const SaveObj = enum(u4) {
|
||||||
|
Player,
|
||||||
|
Coin,
|
||||||
|
WireBeginPinned,
|
||||||
|
WireBeginLoose,
|
||||||
|
WireEndPinned,
|
||||||
|
WireEndLoose,
|
||||||
|
};
|
||||||
|
|
||||||
|
fn cell2u8(cell: util.Cell) [2]u8 {
|
||||||
|
return [_]u8{ @intCast(u8, cell[0]), @intCast(u8, cell[1]) };
|
||||||
|
}
|
||||||
|
|
||||||
|
fn vec2u16(vec2: util.Vec2) [2]u16 {
|
||||||
|
return [_]u16{ @intCast(u16, vec2[0]), @intCast(u16, vec2[1]) };
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write_diff(writer: anytype, stride: usize, initial: []const u8, mapBuf: []const u8) !u8 {
|
||||||
|
var written: u8 = 0;
|
||||||
|
for (initial) |init_tile, i| {
|
||||||
|
if (mapBuf[i] != init_tile) {
|
||||||
|
const x = @intCast(u8, i % @intCast(usize, stride));
|
||||||
|
const y = @intCast(u8, @divTrunc(i, @intCast(usize, stride)));
|
||||||
|
const temp = [3]u8{ x, y, mapBuf[i] };
|
||||||
|
try writer.writeAll(&temp);
|
||||||
|
written += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return written;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn load_diff(mapBuf: []u8, stride: usize, diff: []const u8) void {
|
||||||
|
var i: usize = 0;
|
||||||
|
while (i < diff.len) : (i += 3) {
|
||||||
|
const x = diff[i];
|
||||||
|
const y = diff[i + 1];
|
||||||
|
const tile = diff[i + 2];
|
||||||
|
const a = x + y * stride;
|
||||||
|
mapBuf[a] = tile;
|
||||||
|
// this.set_cell(Cell{ x, y }, tile);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn reset() void {
|
||||||
|
// TODO: implement reset
|
||||||
|
// This function should reset the game world without clearing the scores list,
|
||||||
|
// so a player can see how well they've done with the game in the past.
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn load() bool {
|
||||||
|
var load_buf: [1024]u8 = undefined;
|
||||||
|
const read = w4.diskr(&load_buf, 1024);
|
||||||
|
w4.tracef("%d bytes read", read);
|
||||||
|
|
||||||
|
// if (true) return false;
|
||||||
|
if (read <= 0) return false;
|
||||||
|
// for (load_buf[0 .. read - 1]) |byte| w4.tracef("%d", byte);
|
||||||
|
|
||||||
|
var stream = std.io.fixedBufferStream(load_buf[0..read]);
|
||||||
|
var reader = stream.reader();
|
||||||
|
|
||||||
|
var header: [5]u8 = undefined;
|
||||||
|
_ = reader.read(&header) catch w4.tracef("couldn't load header");
|
||||||
|
w4.tracef("%s", &header);
|
||||||
|
if (!std.mem.eql(u8, "wired", &header)) return false; // w4.tracef("did not load, incorrect header bytes");
|
||||||
|
|
||||||
|
game.score = reader.readByte() catch return false;
|
||||||
|
|
||||||
|
const obj_len = reader.readByte() catch return false;
|
||||||
|
// const map_len = reader.readByte() catch return false;
|
||||||
|
const conduit_len = reader.readByte() catch return false;
|
||||||
|
|
||||||
|
var i: usize = 0;
|
||||||
|
while (i < obj_len) : (i += 1) {
|
||||||
|
const b = reader.readByte() catch return false;
|
||||||
|
const obj = @intToEnum(SaveObj, @truncate(u4, b));
|
||||||
|
const id = @truncate(u4, b >> 4);
|
||||||
|
const x = reader.readIntBig(u16) catch return false;
|
||||||
|
const y = reader.readIntBig(u16) catch return false;
|
||||||
|
var pos = Pos.init(util.vec2ToVec2f(Vec2{ x, y }));
|
||||||
|
switch (obj) {
|
||||||
|
.Player => {
|
||||||
|
w4.tracef("player at %d, %d", x, y);
|
||||||
|
game.player.pos = pos;
|
||||||
|
// player.pos.pos += Vec2f{ 4, 6 };
|
||||||
|
},
|
||||||
|
.Coin => {
|
||||||
|
game.coins.append(.{
|
||||||
|
.pos = pos,
|
||||||
|
.sprite = .{ .offset = .{ 0, 0 }, .size = .{ 8, 8 }, .index = 4, .flags = .{ .bpp = .b2 } },
|
||||||
|
.anim = Anim{ .anim = &game.anim_store.coin },
|
||||||
|
.area = .{ .pos = .{ 0, 0 }, .size = .{ 8, 8 } },
|
||||||
|
}) catch unreachable;
|
||||||
|
},
|
||||||
|
.WireBeginPinned => {
|
||||||
|
var begin = game.wires.slice()[id].begin();
|
||||||
|
begin.* = pos;
|
||||||
|
begin.pinned = true;
|
||||||
|
game.wires.slice()[id].straighten();
|
||||||
|
},
|
||||||
|
.WireBeginLoose => {
|
||||||
|
var begin = game.wires.slice()[id].begin();
|
||||||
|
begin.* = pos;
|
||||||
|
begin.pinned = false;
|
||||||
|
game.wires.slice()[id].straighten();
|
||||||
|
},
|
||||||
|
.WireEndPinned => {
|
||||||
|
var end = game.wires.slice()[id].end();
|
||||||
|
end.* = pos;
|
||||||
|
end.pinned = true;
|
||||||
|
game.wires.slice()[id].straighten();
|
||||||
|
},
|
||||||
|
.WireEndLoose => {
|
||||||
|
var end = game.wires.slice()[id].end();
|
||||||
|
end.* = pos;
|
||||||
|
end.pinned = false;
|
||||||
|
game.wires.slice()[id].straighten();
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load map
|
||||||
|
var buf: [256]u8 = undefined;
|
||||||
|
// const len = reader.readByte() catch return;
|
||||||
|
// const bytes_map = reader.read(buf[0 .. map_len * 3]) catch return false;
|
||||||
|
// w4.tracef("loading %d map diffs... %d bytes", map_len, bytes_map);
|
||||||
|
// load_diff(&solids_mutable, assets.solid_size[0], buf[0..bytes_map]);
|
||||||
|
|
||||||
|
// Load conduit
|
||||||
|
// const conduit_len = reader.readByte() catch return;
|
||||||
|
const bytes_conduit = reader.read(buf[0 .. conduit_len * 3]) catch return false;
|
||||||
|
w4.tracef("loading %d conduit diffs... %d bytes", conduit_len, bytes_conduit);
|
||||||
|
for (buf[0..bytes_conduit]) |byte| w4.tracef("%d", byte);
|
||||||
|
load_diff(&game.conduit_mutable, assets.conduit_size[0], buf[0..bytes_conduit]);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn save() void {
|
||||||
|
var save_buf: [1024]u8 = undefined;
|
||||||
|
var save_stream = std.io.fixedBufferStream(&save_buf);
|
||||||
|
var save_writer = save_stream.writer();
|
||||||
|
save_writer.writeAll("wired") catch return w4.tracef("Couldn't write header");
|
||||||
|
save_writer.writeByte(game.score) catch return w4.tracef("Couldn't save score");
|
||||||
|
w4.tracef("score %d written", game.score);
|
||||||
|
|
||||||
|
// Write temporary length values
|
||||||
|
const lengths_start = save_stream.getPos() catch return w4.tracef("Couldn't get pos");
|
||||||
|
save_writer.writeByte(0) catch return w4.tracef("Couldn't write obj length");
|
||||||
|
// save_writer.writeByte(0) catch return w4.tracef("Couldn't write map length");
|
||||||
|
save_writer.writeByte(0) catch return w4.tracef("Couldn't write conduit length");
|
||||||
|
|
||||||
|
// Write player
|
||||||
|
const playerPos = vec2u16(util.vec2fToVec2(game.player.pos.pos));
|
||||||
|
save_writer.writeByte(@enumToInt(SaveObj.Player)) catch return w4.tracef("Player");
|
||||||
|
save_writer.writeIntBig(u16, playerPos[0]) catch return;
|
||||||
|
save_writer.writeIntBig(u16, playerPos[1]) catch return;
|
||||||
|
// save_writer.writeAll(&[_]u8{ @enumToInt(SaveObj.Player), @intCast(u8, player
|
||||||
|
var obj_len: u8 = 1;
|
||||||
|
|
||||||
|
for (game.coins.slice()) |coin, i| {
|
||||||
|
obj_len += 1;
|
||||||
|
const id = @intCast(u8, @truncate(u4, i)) << 4;
|
||||||
|
// const cell = util.world2cell(coin.pos.pos);
|
||||||
|
save_writer.writeByte(@enumToInt(SaveObj.Coin) | id) catch return w4.tracef("Couldn't save coin");
|
||||||
|
const pos = vec2u16(util.vec2fToVec2(coin.pos.pos));
|
||||||
|
save_writer.writeIntBig(u16, pos[0]) catch return;
|
||||||
|
save_writer.writeIntBig(u16, pos[1]) catch return;
|
||||||
|
// save_writer.writeInt(&) catch return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write wires
|
||||||
|
for (game.wires.slice()) |*wire, i| {
|
||||||
|
const id = @intCast(u8, @truncate(u4, i)) << 4;
|
||||||
|
const begin = wire.begin();
|
||||||
|
const end = wire.end();
|
||||||
|
obj_len += 1;
|
||||||
|
if (begin.pinned) {
|
||||||
|
// const cell = util.world2cell(begin.pos);
|
||||||
|
save_writer.writeByte(@enumToInt(SaveObj.WireBeginPinned) | id) catch return w4.tracef("Couldn't save wire");
|
||||||
|
// const pos = cell2u16(cell);
|
||||||
|
const pos = vec2u16(util.vec2fToVec2(begin.pos));
|
||||||
|
save_writer.writeIntBig(u16, pos[0]) catch return;
|
||||||
|
save_writer.writeIntBig(u16, pos[1]) catch return;
|
||||||
|
// save_writer.writeAll(&cell2u8(cell)) catch return;
|
||||||
|
} else {
|
||||||
|
// const cell = util.world2cell(begin.pos);
|
||||||
|
save_writer.writeByte(@enumToInt(SaveObj.WireBeginLoose) | id) catch return w4.tracef("Couldn't save wire");
|
||||||
|
// const pos = cell2u16(cell);
|
||||||
|
const pos = vec2u16(util.vec2fToVec2(begin.pos));
|
||||||
|
save_writer.writeIntBig(u16, pos[0]) catch return;
|
||||||
|
save_writer.writeIntBig(u16, pos[1]) catch return;
|
||||||
|
// save_writer.writeAll(&cell2u8(cell)) catch return;
|
||||||
|
}
|
||||||
|
obj_len += 1;
|
||||||
|
if (end.pinned) {
|
||||||
|
// const cell = util.world2cell(end.pos);
|
||||||
|
save_writer.writeByte(@enumToInt(SaveObj.WireEndPinned) | id) catch return w4.tracef("Couldn't save wire");
|
||||||
|
// const pos = cell2u16(cell);
|
||||||
|
const pos = vec2u16(util.vec2fToVec2(end.pos));
|
||||||
|
save_writer.writeIntBig(u16, pos[0]) catch return;
|
||||||
|
save_writer.writeIntBig(u16, pos[1]) catch return;
|
||||||
|
// save_writer.writeAll(&cell2u8(cell)) catch return;
|
||||||
|
} else {
|
||||||
|
// const cell = util.world2cell(end.pos);
|
||||||
|
save_writer.writeByte(@enumToInt(SaveObj.WireEndLoose) | id) catch return w4.tracef("Couldn't save wire");
|
||||||
|
// const pos = cell2u16(cell);
|
||||||
|
const pos = vec2u16(util.vec2fToVec2(end.pos));
|
||||||
|
save_writer.writeIntBig(u16, pos[0]) catch return;
|
||||||
|
save_writer.writeIntBig(u16, pos[1]) catch return;
|
||||||
|
// save_writer.writeAll(&cell2u8(cell)) catch return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write map
|
||||||
|
// const map_len = write_diff(save_writer, assets.solid_size[0], &assets.solid, &solids_mutable) catch return w4.tracef("Couldn't save map diff");
|
||||||
|
|
||||||
|
// Write conduit
|
||||||
|
const conduit_len = write_diff(save_writer, assets.conduit_size[0], &assets.conduit, &game.conduit_mutable) catch return w4.tracef("Couldn't save map diff");
|
||||||
|
|
||||||
|
const endPos = save_stream.getPos() catch return;
|
||||||
|
save_stream.seekTo(lengths_start) catch w4.tracef("Couldn't seek");
|
||||||
|
save_writer.writeByte(obj_len) catch return w4.tracef("Couldn't write obj length");
|
||||||
|
// save_writer.writeByte(map_len) catch return w4.tracef("Couldn't write map length");
|
||||||
|
save_writer.writeByte(conduit_len) catch return w4.tracef("Couldn't write conduit length");
|
||||||
|
|
||||||
|
save_stream.seekTo(endPos) catch return;
|
||||||
|
const save_slice = save_stream.getWritten();
|
||||||
|
const written = w4.diskw(save_slice.ptr, save_slice.len);
|
||||||
|
w4.tracef("%d bytes written", written);
|
||||||
|
for (save_buf[0..written]) |byte| w4.tracef("%d", byte);
|
||||||
|
}
|
307
src/game.zig
307
src/game.zig
|
@ -7,59 +7,24 @@ const Circuit = @import("circuit.zig");
|
||||||
const Map = @import("map.zig");
|
const Map = @import("map.zig");
|
||||||
const Music = @import("music.zig");
|
const Music = @import("music.zig");
|
||||||
const State = @import("main.zig").State;
|
const State = @import("main.zig").State;
|
||||||
|
const Disk = @import("disk.zig");
|
||||||
|
|
||||||
const Vec2 = util.Vec2;
|
const Vec2 = util.Vec2;
|
||||||
const Vec2f = util.Vec2f;
|
const Vec2f = util.Vec2f;
|
||||||
const AABB = util.AABB;
|
const AABB = util.AABB;
|
||||||
const Anim = @import("anim.zig");
|
const Anim = @import("anim.zig");
|
||||||
|
|
||||||
// Components
|
const comp = @import("component.zig");
|
||||||
const Pos = struct {
|
|
||||||
pos: Vec2f,
|
|
||||||
last: Vec2f,
|
|
||||||
pinned: bool = false,
|
|
||||||
pub fn init(pos: Vec2f) @This() {
|
|
||||||
return @This(){ .pos = pos, .last = pos };
|
|
||||||
}
|
|
||||||
pub fn initVel(pos: Vec2f, vel: Vec2f) @This() {
|
|
||||||
return @This(){ .pos = pos, .last = pos - vel };
|
|
||||||
}
|
|
||||||
};
|
|
||||||
const Control = struct {
|
|
||||||
controller: enum { player },
|
|
||||||
state: enum { stand, walk, jump, fall, wallSlide },
|
|
||||||
facing: enum { left, right, up, down } = .right,
|
|
||||||
grabbing: ?struct { id: usize, which: usize } = null,
|
|
||||||
};
|
|
||||||
const Sprite = struct {
|
|
||||||
offset: Vec2 = Vec2{ 0, 0 },
|
|
||||||
size: w4.Vec2,
|
|
||||||
index: usize,
|
|
||||||
flags: w4.BlitFlags,
|
|
||||||
};
|
|
||||||
const StaticAnim = Anim;
|
|
||||||
const ControlAnim = struct { anims: []AnimData, state: Anim };
|
|
||||||
const Kinematic = struct {
|
|
||||||
col: AABB,
|
|
||||||
move: Vec2f = Vec2f{ 0, 0 },
|
|
||||||
lastCol: Vec2f = Vec2f{ 0, 0 },
|
|
||||||
|
|
||||||
pub fn inAir(this: @This()) bool {
|
const Pos = comp.Pos;
|
||||||
return approxEqAbs(f32, this.lastCol[1], 0, 0.01);
|
const Control = comp.Control;
|
||||||
}
|
const Sprite = comp.Sprite;
|
||||||
|
const ControlAnim = comp.ControlAnim;
|
||||||
|
const StaticAnim = comp.StaticAnim;
|
||||||
|
const Kinematic = comp.Kinematic;
|
||||||
|
const Physics = comp.Physics;
|
||||||
|
const AnimData = []const Anim.Ops;
|
||||||
|
|
||||||
pub fn onFloor(this: @This()) bool {
|
|
||||||
return approxEqAbs(f32, this.move[1], 0, 0.01) and this.lastCol[1] > 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn isFalling(this: @This()) bool {
|
|
||||||
return this.move[1] > 0 and approxEqAbs(f32, this.lastCol[1], 0, 0.01);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn onWall(this: @This()) bool {
|
|
||||||
return this.isFalling() and !approxEqAbs(f32, this.lastCol[0], 0, 0.01);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
const Wire = struct {
|
const Wire = struct {
|
||||||
nodes: std.BoundedArray(Pos, 32) = std.BoundedArray(Pos, 32).init(0),
|
nodes: std.BoundedArray(Pos, 32) = std.BoundedArray(Pos, 32).init(0),
|
||||||
enabled: bool = false,
|
enabled: bool = false,
|
||||||
|
@ -82,7 +47,7 @@ const Wire = struct {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
const Physics = struct { gravity: Vec2f, friction: Vec2f };
|
|
||||||
const Player = struct {
|
const Player = struct {
|
||||||
pos: Pos,
|
pos: Pos,
|
||||||
control: Control,
|
control: Control,
|
||||||
|
@ -91,7 +56,6 @@ const Player = struct {
|
||||||
kinematic: Kinematic,
|
kinematic: Kinematic,
|
||||||
physics: Physics,
|
physics: Physics,
|
||||||
};
|
};
|
||||||
// const World = ecs.World(Component);
|
|
||||||
|
|
||||||
const Particle = struct {
|
const Particle = struct {
|
||||||
pos: Pos,
|
pos: Pos,
|
||||||
|
@ -176,14 +140,14 @@ var circuit: Circuit = undefined;
|
||||||
var particles: ParticleSystem = undefined;
|
var particles: ParticleSystem = undefined;
|
||||||
var prng = std.rand.DefaultPrng.init(0);
|
var prng = std.rand.DefaultPrng.init(0);
|
||||||
var random = prng.random();
|
var random = prng.random();
|
||||||
var player: Player = undefined;
|
pub var player: Player = undefined;
|
||||||
var music = Music.Procedural.init(.C3, &Music.Minor, 83);
|
var music = Music.Procedural.init(.C3, &Music.Minor, 83);
|
||||||
var wires = std.BoundedArray(Wire, 10).init(0) catch unreachable;
|
pub var wires = std.BoundedArray(Wire, 10).init(0) catch unreachable;
|
||||||
var camera = Vec2{ 0, 0 };
|
var camera = Vec2{ 0, 0 };
|
||||||
|
|
||||||
const Coin = struct { pos: Pos, sprite: Sprite, anim: Anim, area: AABB };
|
const Coin = struct { pos: Pos, sprite: Sprite, anim: Anim, area: AABB };
|
||||||
var coins = std.BoundedArray(Coin, 20).init(0) catch unreachable;
|
pub var coins = std.BoundedArray(Coin, 20).init(0) catch unreachable;
|
||||||
var score: u8 = 0;
|
pub var score: u8 = 0;
|
||||||
var ScoreCoin = Sprite{
|
var ScoreCoin = Sprite{
|
||||||
.size = Map.tile_size,
|
.size = Map.tile_size,
|
||||||
.index = 4,
|
.index = 4,
|
||||||
|
@ -191,20 +155,18 @@ var ScoreCoin = Sprite{
|
||||||
};
|
};
|
||||||
|
|
||||||
var solids_mutable = assets.solid;
|
var solids_mutable = assets.solid;
|
||||||
var conduit_mutable = assets.conduit;
|
pub var conduit_mutable = assets.conduit;
|
||||||
var conduitLevels_mutable: [conduit_mutable.len]u8 = undefined;
|
var conduitLevels_mutable: [conduit_mutable.len]u8 = undefined;
|
||||||
|
|
||||||
const anim_store = struct {
|
pub const anim_store = struct {
|
||||||
const stand = Anim.frame(8);
|
const stand = Anim.frame(8);
|
||||||
const walk = Anim.simple(4, &[_]usize{ 9, 10, 11, 12 });
|
const walk = Anim.simple(4, &[_]usize{ 9, 10, 11, 12 });
|
||||||
const jump = Anim.frame(13);
|
const jump = Anim.frame(13);
|
||||||
const fall = Anim.frame(14);
|
const fall = Anim.frame(14);
|
||||||
const wallSlide = Anim.frame(15);
|
const wallSlide = Anim.frame(15);
|
||||||
const coin = Anim.simple(15, &[_]usize{ 4, 5, 6 });
|
pub const coin = Anim.simple(15, &[_]usize{ 4, 5, 6 });
|
||||||
};
|
};
|
||||||
|
|
||||||
const AnimData = []const Anim.Ops;
|
|
||||||
|
|
||||||
const playerAnim = pac: {
|
const playerAnim = pac: {
|
||||||
var animArr = std.BoundedArray(AnimData, 100).init(0) catch unreachable;
|
var animArr = std.BoundedArray(AnimData, 100).init(0) catch unreachable;
|
||||||
animArr.append(&anim_store.stand) catch unreachable;
|
animArr.append(&anim_store.stand) catch unreachable;
|
||||||
|
@ -269,7 +231,7 @@ pub fn start() void {
|
||||||
}
|
}
|
||||||
|
|
||||||
// _ = w4.diskw("", 0);
|
// _ = w4.diskw("", 0);
|
||||||
if (!load()) {
|
if (!Disk.load()) {
|
||||||
for (assets.coins) |coin| {
|
for (assets.coins) |coin| {
|
||||||
coins.append(.{
|
coins.append(.{
|
||||||
.pos = Pos.init(util.vec2ToVec2f(coin * tile_size)),
|
.pos = Pos.init(util.vec2ToVec2f(coin * tile_size)),
|
||||||
|
@ -326,12 +288,12 @@ pub fn update(time: usize) State {
|
||||||
_ = coins.swapRemove(i);
|
_ = coins.swapRemove(i);
|
||||||
}
|
}
|
||||||
// We save here to prevent duplicate coins
|
// We save here to prevent duplicate coins
|
||||||
if (shouldSave) save();
|
if (shouldSave) Disk.save();
|
||||||
}
|
}
|
||||||
|
|
||||||
const newCamera = @divTrunc(util.world2cell(player.pos.pos), @splat(2, @as(i32, 20))) * @splat(2, @as(i32, 20));
|
const newCamera = @divTrunc(util.world2cell(player.pos.pos), @splat(2, @as(i32, 20))) * @splat(2, @as(i32, 20));
|
||||||
if (!@reduce(.And, newCamera == camera)) {
|
if (!@reduce(.And, newCamera == camera)) {
|
||||||
save();
|
Disk.save();
|
||||||
}
|
}
|
||||||
camera = newCamera;
|
camera = newCamera;
|
||||||
|
|
||||||
|
@ -417,233 +379,6 @@ pub fn update(time: usize) State {
|
||||||
return .Game;
|
return .Game;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn write_diff(writer: anytype, stride: usize, initial: []const u8, mapBuf: []const u8) !u8 {
|
|
||||||
var written: u8 = 0;
|
|
||||||
for (initial) |init_tile, i| {
|
|
||||||
if (mapBuf[i] != init_tile) {
|
|
||||||
const x = @intCast(u8, i % @intCast(usize, stride));
|
|
||||||
const y = @intCast(u8, @divTrunc(i, @intCast(usize, stride)));
|
|
||||||
const temp = [3]u8{ x, y, mapBuf[i] };
|
|
||||||
try writer.writeAll(&temp);
|
|
||||||
written += 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return written;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn load_diff(mapBuf: []u8, stride: usize, diff: []const u8) void {
|
|
||||||
var i: usize = 0;
|
|
||||||
while (i < diff.len) : (i += 3) {
|
|
||||||
const x = diff[i];
|
|
||||||
const y = diff[i + 1];
|
|
||||||
const tile = diff[i + 2];
|
|
||||||
const a = x + y * stride;
|
|
||||||
mapBuf[a] = tile;
|
|
||||||
// this.set_cell(Cell{ x, y }, tile);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn load() bool {
|
|
||||||
var load_buf: [1024]u8 = undefined;
|
|
||||||
const read = w4.diskr(&load_buf, 1024);
|
|
||||||
w4.tracef("%d bytes read", read);
|
|
||||||
|
|
||||||
// if (true) return false;
|
|
||||||
if (read <= 0) return false;
|
|
||||||
// for (load_buf[0 .. read - 1]) |byte| w4.tracef("%d", byte);
|
|
||||||
|
|
||||||
var stream = std.io.fixedBufferStream(load_buf[0..read]);
|
|
||||||
var reader = stream.reader();
|
|
||||||
|
|
||||||
var header: [5]u8 = undefined;
|
|
||||||
_ = reader.read(&header) catch w4.tracef("couldn't load header");
|
|
||||||
w4.tracef("%s", &header);
|
|
||||||
if (!std.mem.eql(u8, "wired", &header)) return false; // w4.tracef("did not load, incorrect header bytes");
|
|
||||||
|
|
||||||
score = reader.readByte() catch return false;
|
|
||||||
|
|
||||||
const obj_len = reader.readByte() catch return false;
|
|
||||||
// const map_len = reader.readByte() catch return false;
|
|
||||||
const conduit_len = reader.readByte() catch return false;
|
|
||||||
|
|
||||||
var i: usize = 0;
|
|
||||||
while (i < obj_len) : (i += 1) {
|
|
||||||
const b = reader.readByte() catch return false;
|
|
||||||
const obj = @intToEnum(SaveObj, @truncate(u4, b));
|
|
||||||
const id = @truncate(u4, b >> 4);
|
|
||||||
const x = reader.readIntBig(u16) catch return false;
|
|
||||||
const y = reader.readIntBig(u16) catch return false;
|
|
||||||
var pos = Pos.init(util.vec2ToVec2f(Vec2{ x, y }));
|
|
||||||
switch (obj) {
|
|
||||||
.Player => {
|
|
||||||
w4.tracef("player at %d, %d", x, y);
|
|
||||||
player.pos = pos;
|
|
||||||
// player.pos.pos += Vec2f{ 4, 6 };
|
|
||||||
},
|
|
||||||
.Coin => {
|
|
||||||
coins.append(.{
|
|
||||||
.pos = pos,
|
|
||||||
.sprite = .{ .offset = .{ 0, 0 }, .size = .{ 8, 8 }, .index = 4, .flags = .{ .bpp = .b2 } },
|
|
||||||
.anim = Anim{ .anim = &anim_store.coin },
|
|
||||||
.area = .{ .pos = .{ 0, 0 }, .size = .{ 8, 8 } },
|
|
||||||
}) catch unreachable;
|
|
||||||
},
|
|
||||||
.WireBeginPinned => {
|
|
||||||
var begin = wires.slice()[id].begin();
|
|
||||||
begin.* = pos;
|
|
||||||
begin.pinned = true;
|
|
||||||
wires.slice()[id].straighten();
|
|
||||||
},
|
|
||||||
.WireBeginLoose => {
|
|
||||||
var begin = wires.slice()[id].begin();
|
|
||||||
begin.* = pos;
|
|
||||||
begin.pinned = false;
|
|
||||||
wires.slice()[id].straighten();
|
|
||||||
},
|
|
||||||
.WireEndPinned => {
|
|
||||||
var end = wires.slice()[id].end();
|
|
||||||
end.* = pos;
|
|
||||||
end.pinned = true;
|
|
||||||
wires.slice()[id].straighten();
|
|
||||||
},
|
|
||||||
.WireEndLoose => {
|
|
||||||
var end = wires.slice()[id].end();
|
|
||||||
end.* = pos;
|
|
||||||
end.pinned = false;
|
|
||||||
wires.slice()[id].straighten();
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Load map
|
|
||||||
var buf: [256]u8 = undefined;
|
|
||||||
// const len = reader.readByte() catch return;
|
|
||||||
// const bytes_map = reader.read(buf[0 .. map_len * 3]) catch return false;
|
|
||||||
// w4.tracef("loading %d map diffs... %d bytes", map_len, bytes_map);
|
|
||||||
// load_diff(&solids_mutable, assets.solid_size[0], buf[0..bytes_map]);
|
|
||||||
|
|
||||||
// Load conduit
|
|
||||||
// const conduit_len = reader.readByte() catch return;
|
|
||||||
const bytes_conduit = reader.read(buf[0 .. conduit_len * 3]) catch return false;
|
|
||||||
w4.tracef("loading %d conduit diffs... %d bytes", conduit_len, bytes_conduit);
|
|
||||||
for (buf[0..bytes_conduit]) |byte| w4.tracef("%d", byte);
|
|
||||||
load_diff(&conduit_mutable, assets.conduit_size[0], buf[0..bytes_conduit]);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
const SaveObj = enum(u4) {
|
|
||||||
Player,
|
|
||||||
Coin,
|
|
||||||
WireBeginPinned,
|
|
||||||
WireBeginLoose,
|
|
||||||
WireEndPinned,
|
|
||||||
WireEndLoose,
|
|
||||||
};
|
|
||||||
|
|
||||||
fn cell2u8(cell: util.Cell) [2]u8 {
|
|
||||||
return [_]u8{ @intCast(u8, cell[0]), @intCast(u8, cell[1]) };
|
|
||||||
}
|
|
||||||
|
|
||||||
fn vec2u16(vec2: util.Vec2) [2]u16 {
|
|
||||||
return [_]u16{ @intCast(u16, vec2[0]), @intCast(u16, vec2[1]) };
|
|
||||||
}
|
|
||||||
|
|
||||||
fn save() void {
|
|
||||||
var save_buf: [1024]u8 = undefined;
|
|
||||||
var save_stream = std.io.fixedBufferStream(&save_buf);
|
|
||||||
var save_writer = save_stream.writer();
|
|
||||||
save_writer.writeAll("wired") catch return w4.tracef("Couldn't write header");
|
|
||||||
save_writer.writeByte(score) catch return w4.tracef("Couldn't save score");
|
|
||||||
w4.tracef("score %d written", score);
|
|
||||||
|
|
||||||
// Write temporary length values
|
|
||||||
const lengths_start = save_stream.getPos() catch return w4.tracef("Couldn't get pos");
|
|
||||||
save_writer.writeByte(0) catch return w4.tracef("Couldn't write obj length");
|
|
||||||
// save_writer.writeByte(0) catch return w4.tracef("Couldn't write map length");
|
|
||||||
save_writer.writeByte(0) catch return w4.tracef("Couldn't write conduit length");
|
|
||||||
|
|
||||||
// Write player
|
|
||||||
const playerPos = vec2u16(util.vec2fToVec2(player.pos.pos));
|
|
||||||
save_writer.writeByte(@enumToInt(SaveObj.Player)) catch return w4.tracef("Player");
|
|
||||||
save_writer.writeIntBig(u16, playerPos[0]) catch return;
|
|
||||||
save_writer.writeIntBig(u16, playerPos[1]) catch return;
|
|
||||||
// save_writer.writeAll(&[_]u8{ @enumToInt(SaveObj.Player), @intCast(u8, player
|
|
||||||
var obj_len: u8 = 1;
|
|
||||||
|
|
||||||
for (coins.slice()) |coin, i| {
|
|
||||||
obj_len += 1;
|
|
||||||
const id = @intCast(u8, @truncate(u4, i)) << 4;
|
|
||||||
// const cell = util.world2cell(coin.pos.pos);
|
|
||||||
save_writer.writeByte(@enumToInt(SaveObj.Coin) | id) catch return w4.tracef("Couldn't save coin");
|
|
||||||
const pos = vec2u16(util.vec2fToVec2(coin.pos.pos));
|
|
||||||
save_writer.writeIntBig(u16, pos[0]) catch return;
|
|
||||||
save_writer.writeIntBig(u16, pos[1]) catch return;
|
|
||||||
// save_writer.writeInt(&) catch return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Write wires
|
|
||||||
for (wires.slice()) |*wire, i| {
|
|
||||||
const id = @intCast(u8, @truncate(u4, i)) << 4;
|
|
||||||
const begin = wire.begin();
|
|
||||||
const end = wire.end();
|
|
||||||
obj_len += 1;
|
|
||||||
if (begin.pinned) {
|
|
||||||
// const cell = util.world2cell(begin.pos);
|
|
||||||
save_writer.writeByte(@enumToInt(SaveObj.WireBeginPinned) | id) catch return w4.tracef("Couldn't save wire");
|
|
||||||
// const pos = cell2u16(cell);
|
|
||||||
const pos = vec2u16(util.vec2fToVec2(begin.pos));
|
|
||||||
save_writer.writeIntBig(u16, pos[0]) catch return;
|
|
||||||
save_writer.writeIntBig(u16, pos[1]) catch return;
|
|
||||||
// save_writer.writeAll(&cell2u8(cell)) catch return;
|
|
||||||
} else {
|
|
||||||
// const cell = util.world2cell(begin.pos);
|
|
||||||
save_writer.writeByte(@enumToInt(SaveObj.WireBeginLoose) | id) catch return w4.tracef("Couldn't save wire");
|
|
||||||
// const pos = cell2u16(cell);
|
|
||||||
const pos = vec2u16(util.vec2fToVec2(begin.pos));
|
|
||||||
save_writer.writeIntBig(u16, pos[0]) catch return;
|
|
||||||
save_writer.writeIntBig(u16, pos[1]) catch return;
|
|
||||||
// save_writer.writeAll(&cell2u8(cell)) catch return;
|
|
||||||
}
|
|
||||||
obj_len += 1;
|
|
||||||
if (end.pinned) {
|
|
||||||
// const cell = util.world2cell(end.pos);
|
|
||||||
save_writer.writeByte(@enumToInt(SaveObj.WireEndPinned) | id) catch return w4.tracef("Couldn't save wire");
|
|
||||||
// const pos = cell2u16(cell);
|
|
||||||
const pos = vec2u16(util.vec2fToVec2(end.pos));
|
|
||||||
save_writer.writeIntBig(u16, pos[0]) catch return;
|
|
||||||
save_writer.writeIntBig(u16, pos[1]) catch return;
|
|
||||||
// save_writer.writeAll(&cell2u8(cell)) catch return;
|
|
||||||
} else {
|
|
||||||
// const cell = util.world2cell(end.pos);
|
|
||||||
save_writer.writeByte(@enumToInt(SaveObj.WireEndLoose) | id) catch return w4.tracef("Couldn't save wire");
|
|
||||||
// const pos = cell2u16(cell);
|
|
||||||
const pos = vec2u16(util.vec2fToVec2(end.pos));
|
|
||||||
save_writer.writeIntBig(u16, pos[0]) catch return;
|
|
||||||
save_writer.writeIntBig(u16, pos[1]) catch return;
|
|
||||||
// save_writer.writeAll(&cell2u8(cell)) catch return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Write map
|
|
||||||
// const map_len = write_diff(save_writer, assets.solid_size[0], &assets.solid, &solids_mutable) catch return w4.tracef("Couldn't save map diff");
|
|
||||||
|
|
||||||
// Write conduit
|
|
||||||
const conduit_len = write_diff(save_writer, assets.conduit_size[0], &assets.conduit, &conduit_mutable) catch return w4.tracef("Couldn't save map diff");
|
|
||||||
|
|
||||||
const endPos = save_stream.getPos() catch return;
|
|
||||||
save_stream.seekTo(lengths_start) catch w4.tracef("Couldn't seek");
|
|
||||||
save_writer.writeByte(obj_len) catch return w4.tracef("Couldn't write obj length");
|
|
||||||
// save_writer.writeByte(map_len) catch return w4.tracef("Couldn't write map length");
|
|
||||||
save_writer.writeByte(conduit_len) catch return w4.tracef("Couldn't write conduit length");
|
|
||||||
|
|
||||||
save_stream.seekTo(endPos) catch return;
|
|
||||||
const save_slice = save_stream.getWritten();
|
|
||||||
const written = w4.diskw(save_slice.ptr, save_slice.len);
|
|
||||||
w4.tracef("%d bytes written", written);
|
|
||||||
for (save_buf[0..written]) |byte| w4.tracef("%d", byte);
|
|
||||||
}
|
|
||||||
|
|
||||||
const Interaction = struct {
|
const Interaction = struct {
|
||||||
pos: Vec2,
|
pos: Vec2,
|
||||||
details: union(enum) {
|
details: union(enum) {
|
||||||
|
|
|
@ -15,7 +15,9 @@ pub fn start() void {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn update() State {
|
pub fn update() State {
|
||||||
w4.DRAW_COLORS.* = 0x0002;
|
w4.DRAW_COLORS.* = 0x0004;
|
||||||
|
w4.rect(Vec2{ 0, 0 }, Vec2{ 160, 160 });
|
||||||
|
w4.DRAW_COLORS.* = 0x0001;
|
||||||
var i: i32 = 1;
|
var i: i32 = 1;
|
||||||
w4.text("WIRED", Vec2{ 16, i * 16 });
|
w4.text("WIRED", Vec2{ 16, i * 16 });
|
||||||
i += 1;
|
i += 1;
|
||||||
|
|
Loading…
Reference in New Issue