scrap current asset manager
This commit is contained in:
parent
9becd7d56b
commit
7954a8915a
@ -1,172 +0,0 @@
|
|||||||
const std = @import("std");
|
|
||||||
const Lib = @import("engine_lib");
|
|
||||||
|
|
||||||
const AssetBundle = @This();
|
|
||||||
|
|
||||||
fonts: std.ArrayList(Font),
|
|
||||||
sounds: std.ArrayList(Sound),
|
|
||||||
textures: std.ArrayList(Texture),
|
|
||||||
data: std.ArrayList(u8),
|
|
||||||
|
|
||||||
const DataSegment = extern struct {
|
|
||||||
offset: u64,
|
|
||||||
len: u64,
|
|
||||||
};
|
|
||||||
|
|
||||||
const Font = extern struct {
|
|
||||||
asset_id: Lib.Asset.Id,
|
|
||||||
info: Lib.Font.Info,
|
|
||||||
data: DataSegment
|
|
||||||
};
|
|
||||||
|
|
||||||
const Sound = extern struct {
|
|
||||||
asset_id: Lib.Asset.Id,
|
|
||||||
info: Lib.Sound.Info,
|
|
||||||
data: DataSegment
|
|
||||||
};
|
|
||||||
|
|
||||||
const Texture = extern struct {
|
|
||||||
asset_id: Lib.Asset.Id,
|
|
||||||
info: Lib.Texture.Info,
|
|
||||||
data: DataSegment
|
|
||||||
};
|
|
||||||
|
|
||||||
const Header = extern struct {
|
|
||||||
magic: Magic,
|
|
||||||
fonts_len: u32,
|
|
||||||
sounds_len: u32,
|
|
||||||
textures_len: u32,
|
|
||||||
data_len: u32,
|
|
||||||
|
|
||||||
pub const Magic = enum(u32) {
|
|
||||||
v1 = 0x961C8C65,
|
|
||||||
_,
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
const endianness: std.builtin.Endian = .little;
|
|
||||||
|
|
||||||
pub fn init() AssetBundle {
|
|
||||||
return AssetBundle{
|
|
||||||
.fonts = .empty,
|
|
||||||
.sounds = .empty,
|
|
||||||
.textures = .empty,
|
|
||||||
.data = .empty,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn deinit(self: *AssetBundle, gpa: std.mem.Allocator) void {
|
|
||||||
self.sounds.deinit(gpa);
|
|
||||||
self.textures.deinit(gpa);
|
|
||||||
self.fonts.deinit(gpa);
|
|
||||||
self.data.deinit(gpa);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn getData(self: AssetBundle, data: DataSegment) []const u8 {
|
|
||||||
return self.data.items[data.offset..][0..data.len];
|
|
||||||
}
|
|
||||||
|
|
||||||
fn insertData(
|
|
||||||
self: *AssetBundle,
|
|
||||||
gpa: std.mem.Allocator,
|
|
||||||
data: []const u8
|
|
||||||
) !DataSegment {
|
|
||||||
const data_offset = self.data.items.len;
|
|
||||||
try self.data.appendSlice(gpa, data);
|
|
||||||
|
|
||||||
return DataSegment{
|
|
||||||
.offset = data_offset,
|
|
||||||
.len = data.len
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn appendSound(
|
|
||||||
self: *AssetBundle,
|
|
||||||
gpa: std.mem.Allocator,
|
|
||||||
id: Lib.Asset.Id,
|
|
||||||
data: []const u8,
|
|
||||||
info: Lib.Sound.Info,
|
|
||||||
) !void {
|
|
||||||
try self.sounds.append(gpa, Sound{
|
|
||||||
.asset_id = id,
|
|
||||||
.data = try self.insertData(gpa, data),
|
|
||||||
.info = info
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn appendFont(
|
|
||||||
self: *AssetBundle,
|
|
||||||
gpa: std.mem.Allocator,
|
|
||||||
id: Lib.Asset.Id,
|
|
||||||
data: []const u8,
|
|
||||||
info: Lib.Font.Info,
|
|
||||||
) !void {
|
|
||||||
try self.fonts.append(gpa, Font{
|
|
||||||
.asset_id = id,
|
|
||||||
.data = try self.insertData(gpa, data),
|
|
||||||
.info = info
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn appendTexture(
|
|
||||||
self: *AssetBundle,
|
|
||||||
gpa: std.mem.Allocator,
|
|
||||||
id: Lib.Asset.Id,
|
|
||||||
data: []const u8,
|
|
||||||
info: Lib.Texture.Info
|
|
||||||
) !void {
|
|
||||||
try self.textures.append(gpa, Texture{
|
|
||||||
.asset_id = id,
|
|
||||||
.info = info,
|
|
||||||
.data = try self.insertData(gpa, data)
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn write(self: AssetBundle, writer: *std.Io.Writer) !void {
|
|
||||||
try writer.writeStruct(Header{
|
|
||||||
.magic = .v1,
|
|
||||||
.fonts_len = @intCast(self.fonts.items.len),
|
|
||||||
.sounds_len = @intCast(self.sounds.items.len),
|
|
||||||
.textures_len = @intCast(self.textures.items.len),
|
|
||||||
.data_len = @intCast(self.data.items.len)
|
|
||||||
}, endianness);
|
|
||||||
|
|
||||||
try writer.writeSliceEndian(Font, self.fonts.items, endianness);
|
|
||||||
try writer.writeSliceEndian(Sound, self.sounds.items, endianness);
|
|
||||||
try writer.writeSliceEndian(Texture, self.textures.items, endianness);
|
|
||||||
try writer.writeAll(self.data.items);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn read(self: *AssetBundle, gpa: std.mem.Allocator, reader: *std.Io.Reader) !void {
|
|
||||||
const header = try reader.takeStruct(Header, endianness);
|
|
||||||
if (header.magic != .v1) {
|
|
||||||
return error.InvalidMagic;
|
|
||||||
}
|
|
||||||
|
|
||||||
try self.fonts.ensureTotalCapacity(gpa, header.fonts_len);
|
|
||||||
try self.sounds.ensureTotalCapacity(gpa, header.sounds_len);
|
|
||||||
try self.textures.ensureTotalCapacity(gpa, header.textures_len);
|
|
||||||
try self.data.ensureTotalCapacity(gpa, header.data_len);
|
|
||||||
|
|
||||||
self.fonts.clearRetainingCapacity();
|
|
||||||
self.sounds.clearRetainingCapacity();
|
|
||||||
self.textures.clearRetainingCapacity();
|
|
||||||
self.data.clearRetainingCapacity();
|
|
||||||
|
|
||||||
try reader.readSliceEndian(
|
|
||||||
Font,
|
|
||||||
self.fonts.addManyAsSliceAssumeCapacity(header.fonts_len),
|
|
||||||
endianness
|
|
||||||
);
|
|
||||||
try reader.readSliceEndian(
|
|
||||||
Sound,
|
|
||||||
self.sounds.addManyAsSliceAssumeCapacity(header.sounds_len),
|
|
||||||
endianness
|
|
||||||
);
|
|
||||||
try reader.readSliceEndian(
|
|
||||||
Texture,
|
|
||||||
self.textures.addManyAsSliceAssumeCapacity(header.textures_len),
|
|
||||||
endianness
|
|
||||||
);
|
|
||||||
try reader.readSliceAll(self.data.addManyAsSliceAssumeCapacity(header.data_len));
|
|
||||||
}
|
|
||||||
@ -35,7 +35,6 @@ const KindDynamic = struct {
|
|||||||
.init = try ensureLookup(lib, GameCallbacks.InitFn, "init"),
|
.init = try ensureLookup(lib, GameCallbacks.InitFn, "init"),
|
||||||
.tick = try ensureLookup(lib, GameCallbacks.TickFn, "tick"),
|
.tick = try ensureLookup(lib, GameCallbacks.TickFn, "tick"),
|
||||||
.deinit = try ensureLookup(lib, GameCallbacks.DeinitFn, "deinit"),
|
.deinit = try ensureLookup(lib, GameCallbacks.DeinitFn, "deinit"),
|
||||||
.loadAssets = if (build_options.asset_hot_reload) try ensureLookup(lib, GameCallbacks.LoadAssetsFn, "loadAssets") else {},
|
|
||||||
.debug = if (build_options.has_imgui) try ensureLookup(lib, GameCallbacks.DebugFn, "debug") else {},
|
.debug = if (build_options.has_imgui) try ensureLookup(lib, GameCallbacks.DebugFn, "debug") else {},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -212,7 +211,6 @@ const KindStatic = struct {
|
|||||||
.init = game.init,
|
.init = game.init,
|
||||||
.deinit = game.deinit,
|
.deinit = game.deinit,
|
||||||
.tick = game.tick,
|
.tick = game.tick,
|
||||||
.loadAssets = if (build_options.asset_hot_reload) game.loadAssets else {},
|
|
||||||
.debug = if (build_options.has_imgui) game.debug else {},
|
.debug = if (build_options.has_imgui) game.debug else {},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@ -19,7 +19,6 @@ const STBImage = @import("stb_image");
|
|||||||
const Gfx = Graphics;
|
const Gfx = Graphics;
|
||||||
|
|
||||||
pub const Lib = @import("engine_lib");
|
pub const Lib = @import("engine_lib");
|
||||||
pub const AssetBundle = @import("./asset_bundle.zig");
|
|
||||||
|
|
||||||
const build_options = Lib.build_options;
|
const build_options = Lib.build_options;
|
||||||
const debug_keybinds = (builtin.mode == .Debug);
|
const debug_keybinds = (builtin.mode == .Debug);
|
||||||
@ -124,18 +123,15 @@ const GameState = struct {
|
|||||||
self: *GameState,
|
self: *GameState,
|
||||||
init_fn: GameCallbacks.InitFn,
|
init_fn: GameCallbacks.InitFn,
|
||||||
initial: Init,
|
initial: Init,
|
||||||
asset_registry: Lib.Asset.Registry
|
|
||||||
) void {
|
) void {
|
||||||
assert(self.frame == null);
|
assert(self.frame == null);
|
||||||
const opts = Lib.Init{
|
const opts = Lib.Init{
|
||||||
.gpa = self.gpa,
|
.gpa = self.gpa,
|
||||||
.seed = initial.seed,
|
.seed = initial.seed,
|
||||||
.assets = asset_registry
|
|
||||||
};
|
};
|
||||||
self.state = init_fn(&opts);
|
self.state = init_fn(&opts);
|
||||||
|
|
||||||
self.frame = .init(self.gpa, initial.screen_size);
|
self.frame = .init(self.gpa, initial.screen_size);
|
||||||
self.frame.?.assets = asset_registry;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn runGameDeinit(self: *GameState, deinit_fn: GameCallbacks.DeinitFn) void {
|
fn runGameDeinit(self: *GameState, deinit_fn: GameCallbacks.DeinitFn) void {
|
||||||
@ -254,157 +250,12 @@ const Recording = struct {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const AssetManager = struct {
|
|
||||||
const LoadAsset = union(enum) {
|
|
||||||
font: struct {
|
|
||||||
id: Lib.Font.Id,
|
|
||||||
path: []const u8
|
|
||||||
},
|
|
||||||
sound: struct {
|
|
||||||
id: Lib.Sound.Id,
|
|
||||||
path: []const u8
|
|
||||||
},
|
|
||||||
texture: struct {
|
|
||||||
id: Lib.Texture.Id,
|
|
||||||
path: []const u8
|
|
||||||
},
|
|
||||||
|
|
||||||
pub fn clone(self: LoadAsset, arena: std.mem.Allocator) !LoadAsset {
|
|
||||||
return switch (self) {
|
|
||||||
.font => |opts| LoadAsset{
|
|
||||||
.font = .{
|
|
||||||
.id = opts.id,
|
|
||||||
.path = try arena.dupe(u8, opts.path)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
.sound => |opts| LoadAsset{
|
|
||||||
.sound = .{
|
|
||||||
.id = opts.id,
|
|
||||||
.path = try arena.dupe(u8, opts.path)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
.texture => |opts| LoadAsset{
|
|
||||||
.texture = .{
|
|
||||||
.id = opts.id,
|
|
||||||
.path = try arena.dupe(u8, opts.path)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
gpa: std.mem.Allocator,
|
|
||||||
assets: std.ArrayList(Lib.Asset),
|
|
||||||
textures: std.ArrayList(Lib.Texture),
|
|
||||||
|
|
||||||
dir: ?std.fs.Dir,
|
|
||||||
queued_loads_arena: std.heap.ArenaAllocator,
|
|
||||||
queued_loads: std.ArrayList(LoadAsset),
|
|
||||||
|
|
||||||
pub fn init(gpa: std.mem.Allocator) AssetManager {
|
|
||||||
return AssetManager{
|
|
||||||
.gpa = gpa,
|
|
||||||
.assets = .empty,
|
|
||||||
.textures = .empty,
|
|
||||||
.dir = null,
|
|
||||||
.queued_loads_arena = .init(gpa),
|
|
||||||
.queued_loads = .empty
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn deinit(self: *AssetManager) void {
|
|
||||||
self.queued_loads_arena.deinit();
|
|
||||||
self.assets.deinit(self.gpa);
|
|
||||||
self.textures.deinit(self.gpa);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn initRegistry(self: AssetManager) Lib.Asset.Registry {
|
|
||||||
return Lib.Asset.Registry{
|
|
||||||
.assets = self.assets.items,
|
|
||||||
.textures = self.textures.items
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn enqueueLoad(self: *AssetManager, load: LoadAsset) !void {
|
|
||||||
const arena = self.queued_loads_arena.allocator();
|
|
||||||
|
|
||||||
try self.queued_loads.append(arena, try load.clone(arena));
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn performQueuedLoads(self: *AssetManager, graphics: *Graphics, audio: *Audio) !void {
|
|
||||||
if (self.dir == null) {
|
|
||||||
if (self.queued_loads.items.len > 0) {
|
|
||||||
return error.MissingAssetDirectory;
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const dir = self.dir.?;
|
|
||||||
for (self.queued_loads.items) |queued_load| {
|
|
||||||
switch (queued_load) {
|
|
||||||
.font => |opts| {
|
|
||||||
const font_data = try readFileAll(self.gpa, dir, opts.path);
|
|
||||||
defer self.gpa.free(font_data);
|
|
||||||
try graphics.setFontData(opts.id, font_data);
|
|
||||||
},
|
|
||||||
.sound => |opts| {
|
|
||||||
const sound_data = try readFileAll(self.gpa, dir, opts.path);
|
|
||||||
defer self.gpa.free(sound_data);
|
|
||||||
try audio.setSoundData(opts.id, .{
|
|
||||||
.data = sound_data,
|
|
||||||
.format = .vorbis
|
|
||||||
});
|
|
||||||
},
|
|
||||||
.texture => |opts| {
|
|
||||||
const image_data = try readFileAll(self.gpa, dir, opts.path);
|
|
||||||
defer self.gpa.free(image_data);
|
|
||||||
|
|
||||||
const image = try STBImage.load(image_data);
|
|
||||||
defer image.deinit();
|
|
||||||
|
|
||||||
// TODO: Assert that loaded data matches precomputed texture info
|
|
||||||
try graphics.setTextureData(opts.id, .{
|
|
||||||
.width = image.width,
|
|
||||||
.height = image.height,
|
|
||||||
.rgba = image.rgba8_pixels,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
_ = self.queued_loads_arena.reset(.free_all);
|
|
||||||
self.queued_loads = .empty;
|
|
||||||
}
|
|
||||||
|
|
||||||
fn hasTexture(self: AssetManager, texture_id: Lib.Texture.Id) bool {
|
|
||||||
for (self.textures.items) |texture| {
|
|
||||||
if (texture.id == texture_id) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn assertAssetsLoaded(self: AssetManager) void {
|
|
||||||
for (self.assets.items) |asset| {
|
|
||||||
switch (asset.kind) {
|
|
||||||
.texture => |texture_id| {
|
|
||||||
assert(self.hasTexture(texture_id));
|
|
||||||
},
|
|
||||||
else => {} // TODO:
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const Engine = @This();
|
const Engine = @This();
|
||||||
|
|
||||||
allocator: std.mem.Allocator,
|
allocator: std.mem.Allocator,
|
||||||
graphics: Graphics,
|
graphics: Graphics,
|
||||||
audio: Audio,
|
audio: Audio,
|
||||||
|
|
||||||
asset_bundle: ?AssetBundle = null,
|
|
||||||
asset_manager: AssetManager,
|
|
||||||
game_linking: GameLinking,
|
game_linking: GameLinking,
|
||||||
game_state: GameState,
|
game_state: GameState,
|
||||||
|
|
||||||
@ -473,123 +324,9 @@ pub fn run(self: *Engine, opts: RunOptions) !void {
|
|||||||
.play_recording = false,
|
.play_recording = false,
|
||||||
.recording_tick = 0,
|
.recording_tick = 0,
|
||||||
.seed = initial.seed,
|
.seed = initial.seed,
|
||||||
.asset_manager = .init(opts.allocator),
|
|
||||||
.asset_bundle = null,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
switch (opts.asset_loading) {
|
self.game_state.runGameInit(game_linking.callbacks.init, initial);
|
||||||
.bundle_bytes => |bundle_bytes| {
|
|
||||||
var asset_bundle = AssetBundle.init();
|
|
||||||
errdefer asset_bundle.deinit(opts.allocator);
|
|
||||||
|
|
||||||
var reader = std.Io.Reader.fixed(bundle_bytes);
|
|
||||||
asset_bundle.read(opts.allocator, &reader) catch |e| {
|
|
||||||
log.err("Failed to load asset bundle: {}", .{e});
|
|
||||||
return error.FailedToLoadAssetBundle;
|
|
||||||
};
|
|
||||||
|
|
||||||
for (asset_bundle.fonts.items) |font| {
|
|
||||||
const font_id = try self.graphics.addFont();
|
|
||||||
try self.asset_manager.assets.append(self.allocator, .{
|
|
||||||
.id = font.asset_id,
|
|
||||||
.kind = .{ .font = font_id }
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
for (asset_bundle.textures.items) |texture| {
|
|
||||||
const texture_id = try self.graphics.addTexture();
|
|
||||||
try self.asset_manager.assets.append(self.allocator, .{
|
|
||||||
.id = texture.asset_id,
|
|
||||||
.kind = .{ .texture = texture_id }
|
|
||||||
});
|
|
||||||
|
|
||||||
try self.asset_manager.textures.append(self.asset_manager.gpa, .{
|
|
||||||
.id = texture_id,
|
|
||||||
.info = texture.info
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
for (asset_bundle.sounds.items) |sound| {
|
|
||||||
const sound_id = try self.audio.addSound();
|
|
||||||
try self.asset_manager.assets.append(self.allocator, .{
|
|
||||||
.id = sound.asset_id,
|
|
||||||
.kind = .{ .sound = sound_id }
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
self.asset_bundle = asset_bundle;
|
|
||||||
},
|
|
||||||
.dir_path => |asset_dir_path| {
|
|
||||||
if (!build_options.asset_hot_reload) {
|
|
||||||
return error.RuntimeAssetLoadingDisabled;
|
|
||||||
}
|
|
||||||
|
|
||||||
const dir = try std.fs.cwd().openDir(asset_dir_path, .{ .iterate = true });
|
|
||||||
|
|
||||||
var loader: Lib.Asset.Loader = .init(opts.allocator, dir);
|
|
||||||
defer loader.deinit();
|
|
||||||
game_linking.callbacks.loadAssets(&loader);
|
|
||||||
|
|
||||||
for (loader.assets.items) |asset_desc| {
|
|
||||||
switch (asset_desc.kind) {
|
|
||||||
.font => |path| {
|
|
||||||
const font_id = try self.graphics.addFont();
|
|
||||||
try self.asset_manager.assets.append(self.allocator, .{
|
|
||||||
.id = asset_desc.id,
|
|
||||||
.kind = .{ .font = font_id }
|
|
||||||
});
|
|
||||||
|
|
||||||
try self.asset_manager.enqueueLoad(.{
|
|
||||||
.font = .{
|
|
||||||
.id = font_id,
|
|
||||||
.path = path
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
.texture => |texture| {
|
|
||||||
const texture_id = try self.graphics.addTexture();
|
|
||||||
try self.asset_manager.assets.append(self.allocator, .{
|
|
||||||
.id = asset_desc.id,
|
|
||||||
.kind = .{ .texture = texture_id }
|
|
||||||
});
|
|
||||||
|
|
||||||
try self.asset_manager.enqueueLoad(.{
|
|
||||||
.texture = .{
|
|
||||||
.id = texture_id,
|
|
||||||
.path = texture.path
|
|
||||||
}
|
|
||||||
});
|
|
||||||
try self.asset_manager.textures.append(self.asset_manager.gpa, .{
|
|
||||||
.id = texture_id,
|
|
||||||
.info = texture.info
|
|
||||||
});
|
|
||||||
},
|
|
||||||
.sound => |path| {
|
|
||||||
const sound_id = try self.audio.addSound();
|
|
||||||
try self.asset_manager.assets.append(self.allocator, .{
|
|
||||||
.id = asset_desc.id,
|
|
||||||
.kind = .{ .sound = sound_id }
|
|
||||||
});
|
|
||||||
|
|
||||||
try self.asset_manager.enqueueLoad(.{
|
|
||||||
.sound = .{
|
|
||||||
.id = sound_id,
|
|
||||||
.path = path
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
self.asset_manager.dir = dir;
|
|
||||||
},
|
|
||||||
.bundle_path => {
|
|
||||||
// TODO:
|
|
||||||
unreachable;
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
self.game_state.runGameInit(game_linking.callbacks.init, initial, self.asset_manager.initRegistry());
|
|
||||||
|
|
||||||
if (opts.do_recording) {
|
if (opts.do_recording) {
|
||||||
self.recording = .init(opts.allocator, initial);
|
self.recording = .init(opts.allocator, initial);
|
||||||
@ -669,45 +406,6 @@ fn sokolInit(self: *Engine) !void {
|
|||||||
|
|
||||||
try self.graphics.setupSokol();
|
try self.graphics.setupSokol();
|
||||||
self.audio.setupSokol();
|
self.audio.setupSokol();
|
||||||
|
|
||||||
try self.asset_manager.performQueuedLoads(&self.graphics, &self.audio);
|
|
||||||
if (self.asset_bundle) |*asset_bundle| {
|
|
||||||
const registry = self.asset_manager.initRegistry();
|
|
||||||
|
|
||||||
for (asset_bundle.fonts.items) |font| {
|
|
||||||
const font_id = registry.getFont(font.asset_id);
|
|
||||||
assert(font_id != Lib.Font.Id.nil);
|
|
||||||
try self.graphics.setFontData(font_id, asset_bundle.getData(font.data));
|
|
||||||
}
|
|
||||||
|
|
||||||
for (asset_bundle.textures.items) |texture| {
|
|
||||||
const texture_id = registry.getTexture(texture.asset_id);
|
|
||||||
assert(texture_id != Lib.Texture.Id.nil);
|
|
||||||
|
|
||||||
const image = try STBImage.load(asset_bundle.getData(texture.data));
|
|
||||||
defer image.deinit();
|
|
||||||
|
|
||||||
try self.graphics.setTextureData(texture_id, .{
|
|
||||||
.width = image.width,
|
|
||||||
.height = image.height,
|
|
||||||
.rgba = image.rgba8_pixels
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
for (asset_bundle.sounds.items) |sound| {
|
|
||||||
const sound_id = registry.getSound(sound.asset_id);
|
|
||||||
assert(sound_id != Lib.Sound.Id.nil);
|
|
||||||
try self.audio.setSoundData(sound_id, .{
|
|
||||||
.data = asset_bundle.getData(sound.data),
|
|
||||||
.format = .vorbis
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
asset_bundle.deinit(self.allocator);
|
|
||||||
self.asset_bundle = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
self.asset_manager.assertAssetsLoaded();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn sokolCleanup(self: *Engine) void {
|
fn sokolCleanup(self: *Engine) void {
|
||||||
@ -724,7 +422,6 @@ fn sokolCleanup(self: *Engine) void {
|
|||||||
self.audio.deinit();
|
self.audio.deinit();
|
||||||
self.graphics.deinit(self.allocator);
|
self.graphics.deinit(self.allocator);
|
||||||
self.game_linking.deinit(self.allocator);
|
self.game_linking.deinit(self.allocator);
|
||||||
self.asset_manager.deinit();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn sokolFrame(self: *Engine) !void {
|
fn sokolFrame(self: *Engine) !void {
|
||||||
@ -799,7 +496,7 @@ fn sokolFrame(self: *Engine) !void {
|
|||||||
self.game_state.deinit();
|
self.game_state.deinit();
|
||||||
|
|
||||||
self.game_state = .init(self.allocator);
|
self.game_state = .init(self.allocator);
|
||||||
self.game_state.runGameInit(self.game_linking.callbacks.init, initial, self.asset_manager.initRegistry());
|
self.game_state.runGameInit(self.game_linking.callbacks.init, initial);
|
||||||
|
|
||||||
if (self.recording) |recording| {
|
if (self.recording) |recording| {
|
||||||
recording.deinit();
|
recording.deinit();
|
||||||
@ -851,7 +548,7 @@ fn showDebugWindow(self: *Engine) !void {
|
|||||||
self.game_state.deinit();
|
self.game_state.deinit();
|
||||||
|
|
||||||
self.game_state = .init(self.allocator);
|
self.game_state = .init(self.allocator);
|
||||||
self.game_state.runGameInit(self.game_linking.callbacks.init, recording.initial, self.asset_manager.initRegistry());
|
self.game_state.runGameInit(self.game_linking.callbacks.init, recording.initial);
|
||||||
|
|
||||||
self.play_recording = true;
|
self.play_recording = true;
|
||||||
self.recording_tick = 0;
|
self.recording_tick = 0;
|
||||||
|
|||||||
@ -1,207 +0,0 @@
|
|||||||
const std = @import("std");
|
|
||||||
const log = std.log.scoped(.engine);
|
|
||||||
|
|
||||||
const STBImage = @import("stb_image");
|
|
||||||
|
|
||||||
const Font = @import("./font.zig");
|
|
||||||
const Sound = @import("./sound.zig");
|
|
||||||
const Texture = @import("./texture.zig");
|
|
||||||
|
|
||||||
const Asset = @This();
|
|
||||||
|
|
||||||
id: Id,
|
|
||||||
kind: union(Type) {
|
|
||||||
font: Font.Id,
|
|
||||||
sound: Sound.Id,
|
|
||||||
texture: Texture.Id,
|
|
||||||
},
|
|
||||||
|
|
||||||
pub const Id = u32;
|
|
||||||
pub const Type = enum {
|
|
||||||
font,
|
|
||||||
sound,
|
|
||||||
texture
|
|
||||||
};
|
|
||||||
|
|
||||||
pub const Loader = struct {
|
|
||||||
const Descriptor = struct {
|
|
||||||
const KindTexture = struct {
|
|
||||||
path: []const u8,
|
|
||||||
info: Texture.Info
|
|
||||||
};
|
|
||||||
|
|
||||||
id: Id,
|
|
||||||
kind: union(Type) {
|
|
||||||
font: []const u8,
|
|
||||||
sound: []const u8,
|
|
||||||
texture: KindTexture
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
arena: std.heap.ArenaAllocator,
|
|
||||||
dir: std.fs.Dir,
|
|
||||||
assets: std.ArrayList(Descriptor),
|
|
||||||
add_failed: bool,
|
|
||||||
|
|
||||||
pub fn init(gpa: std.mem.Allocator, dir: std.fs.Dir) Loader {
|
|
||||||
return Loader{
|
|
||||||
.arena = .init(gpa),
|
|
||||||
.dir = dir,
|
|
||||||
.assets = .empty,
|
|
||||||
.add_failed = false
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn deinit(self: *Loader) void {
|
|
||||||
self.arena.deinit();
|
|
||||||
self.* = undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
fn readFile(self: *Loader, gpa: std.mem.Allocator, path: []const u8) ![]u8 {
|
|
||||||
const f = try self.dir.openFile(path, .{});
|
|
||||||
defer f.close();
|
|
||||||
|
|
||||||
var wa: std.Io.Writer.Allocating = .init(gpa);
|
|
||||||
defer wa.deinit();
|
|
||||||
|
|
||||||
var buffer: [4 * 4096]u8 = undefined;
|
|
||||||
var reader = f.reader(&buffer);
|
|
||||||
_ = try reader.interface.stream(&wa.writer, .unlimited);
|
|
||||||
|
|
||||||
return try wa.toOwnedSlice();
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn addFont(self: *Loader, id: Asset.Id, path: []const u8) void {
|
|
||||||
const allocator = self.arena.allocator();
|
|
||||||
const path_dupe = allocator.dupe(u8, path) catch |e| {
|
|
||||||
log.err("Failed to duplicate path: {}", .{e});
|
|
||||||
return;
|
|
||||||
};
|
|
||||||
|
|
||||||
self.assets.append(allocator, Descriptor{
|
|
||||||
.id = id,
|
|
||||||
.kind = .{ .font = path_dupe }
|
|
||||||
}) catch |e| {
|
|
||||||
log.err("Failed add sound: {}", .{e});
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn addSound(self: *Loader, id: Asset.Id, path: []const u8) void {
|
|
||||||
const allocator = self.arena.allocator();
|
|
||||||
const path_dupe = allocator.dupe(u8, path) catch |e| {
|
|
||||||
log.err("Failed to duplicate path: {}", .{e});
|
|
||||||
return;
|
|
||||||
};
|
|
||||||
|
|
||||||
self.assets.append(allocator, Descriptor{
|
|
||||||
.id = id,
|
|
||||||
.kind = .{ .sound = path_dupe }
|
|
||||||
}) catch |e| {
|
|
||||||
log.err("Failed add sound: {}", .{e});
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
fn addTextureFallible(self: *Loader, id: Asset.Id, path: []const u8) !void {
|
|
||||||
const allocator = self.arena.allocator();
|
|
||||||
|
|
||||||
var image_info: Texture.Info = undefined;
|
|
||||||
{
|
|
||||||
const file_contents = try self.readFile(allocator, path);
|
|
||||||
defer allocator.free(file_contents);
|
|
||||||
|
|
||||||
const image = try STBImage.load(file_contents);
|
|
||||||
defer image.deinit();
|
|
||||||
|
|
||||||
image_info = .{
|
|
||||||
.width = image.width,
|
|
||||||
.height = image.height,
|
|
||||||
.format = .png
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
const path_dupe = allocator.dupe(u8, path) catch |e| {
|
|
||||||
log.err("Failed to duplicate path: {}", .{e});
|
|
||||||
return;
|
|
||||||
};
|
|
||||||
|
|
||||||
const texture = Descriptor.KindTexture{
|
|
||||||
.path = path_dupe,
|
|
||||||
.info = image_info
|
|
||||||
};
|
|
||||||
|
|
||||||
self.assets.append(allocator, Descriptor{
|
|
||||||
.id = id,
|
|
||||||
.kind = .{ .texture = texture }
|
|
||||||
}) catch |e| {
|
|
||||||
log.err("Failed add sound: {}", .{e});
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn addTexture(self: *Loader, id: Asset.Id, path: []const u8) void {
|
|
||||||
self.addTextureFallible(id, path) catch |e| {
|
|
||||||
log.err("Failed to add texture: {}", .{e});
|
|
||||||
self.add_failed = true;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
pub const Registry = struct {
|
|
||||||
assets: []const Asset,
|
|
||||||
textures: []const Texture,
|
|
||||||
|
|
||||||
pub const empty = Registry{
|
|
||||||
.assets = &.{},
|
|
||||||
.textures = &.{}
|
|
||||||
};
|
|
||||||
|
|
||||||
pub fn getAsset(self: Registry, id: Asset.Id) ?Asset {
|
|
||||||
// TODO: Make this O(1)?
|
|
||||||
for (self.assets) |asset| {
|
|
||||||
if (asset.id == id) {
|
|
||||||
return asset;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn getSound(self: Registry, id: Asset.Id) Sound.Id {
|
|
||||||
const asset = self.getAsset(id) orelse return Sound.Id.nil;
|
|
||||||
if (asset.kind != .sound) {
|
|
||||||
return Sound.Id.nil;
|
|
||||||
}
|
|
||||||
return asset.kind.sound;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn getFont(self: Registry, id: Asset.Id) Font.Id {
|
|
||||||
const asset = self.getAsset(id) orelse return Font.Id.nil;
|
|
||||||
if (asset.kind != .font) {
|
|
||||||
return Font.Id.nil;
|
|
||||||
}
|
|
||||||
return asset.kind.font;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn getTexture(self: Registry, id: Asset.Id) Texture.Id {
|
|
||||||
const asset = self.getAsset(id) orelse return Texture.Id.nil;
|
|
||||||
if (asset.kind != .texture) {
|
|
||||||
return Texture.Id.nil;
|
|
||||||
}
|
|
||||||
return asset.kind.texture;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn getTextureInfo(self: Registry, id: Texture.Id) Texture.Info {
|
|
||||||
if (id == .nil) {
|
|
||||||
log.warn("Failed to access .nil texture info", .{});
|
|
||||||
return .nil;
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: Make this O(1)?
|
|
||||||
for (self.textures) |texture| {
|
|
||||||
if (texture.id == id) {
|
|
||||||
return texture.info;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
log.warn("Failed to find texture info, id={}", .{id});
|
|
||||||
return .nil;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
@ -146,7 +146,6 @@ pub const MouseButton = enum {
|
|||||||
pub const Texture = @import("./texture.zig");
|
pub const Texture = @import("./texture.zig");
|
||||||
pub const Font = @import("./font.zig");
|
pub const Font = @import("./font.zig");
|
||||||
pub const Sound = @import("./sound.zig");
|
pub const Sound = @import("./sound.zig");
|
||||||
pub const Asset = @import("./asset.zig");
|
|
||||||
|
|
||||||
pub const Sprite = struct {
|
pub const Sprite = struct {
|
||||||
texture: Texture.Id,
|
texture: Texture.Id,
|
||||||
@ -289,8 +288,6 @@ pub const Frame = struct {
|
|||||||
screen_size: Vec2,
|
screen_size: Vec2,
|
||||||
clear_color: Vec4,
|
clear_color: Vec4,
|
||||||
|
|
||||||
assets: Asset.Registry,
|
|
||||||
|
|
||||||
pub fn init(
|
pub fn init(
|
||||||
gpa: std.mem.Allocator,
|
gpa: std.mem.Allocator,
|
||||||
screen_size: Vec2
|
screen_size: Vec2
|
||||||
@ -309,7 +306,6 @@ pub const Frame = struct {
|
|||||||
.audio_commands = .empty,
|
.audio_commands = .empty,
|
||||||
.hide_cursor = false,
|
.hide_cursor = false,
|
||||||
.screen_size = screen_size,
|
.screen_size = screen_size,
|
||||||
.assets = .empty
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -477,8 +473,6 @@ pub const Frame = struct {
|
|||||||
pub const Init = struct {
|
pub const Init = struct {
|
||||||
gpa: std.mem.Allocator,
|
gpa: std.mem.Allocator,
|
||||||
seed: u64,
|
seed: u64,
|
||||||
|
|
||||||
assets: Asset.Registry,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const Callbacks = struct {
|
pub const Callbacks = struct {
|
||||||
@ -488,12 +482,10 @@ pub const Callbacks = struct {
|
|||||||
pub const TickFn = *const fn(state: State, frame: *Frame) callconv(.c) void;
|
pub const TickFn = *const fn(state: State, frame: *Frame) callconv(.c) void;
|
||||||
pub const DeinitFn = *const fn(state: State) callconv(.c) void;
|
pub const DeinitFn = *const fn(state: State) callconv(.c) void;
|
||||||
pub const DebugFn = *const fn(state: State, imgui: *ImGui) callconv(.c) void;
|
pub const DebugFn = *const fn(state: State, imgui: *ImGui) callconv(.c) void;
|
||||||
pub const LoadAssetsFn = *const fn(assets: *Asset.Loader) callconv(.c) void;
|
|
||||||
|
|
||||||
init: InitFn,
|
init: InitFn,
|
||||||
tick: TickFn,
|
tick: TickFn,
|
||||||
deinit: DeinitFn,
|
deinit: DeinitFn,
|
||||||
loadAssets: if (build_options.asset_hot_reload) LoadAssetsFn else void,
|
|
||||||
debug: if (build_options.has_imgui) DebugFn else void
|
debug: if (build_options.has_imgui) DebugFn else void
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -501,8 +493,7 @@ pub fn exportCallbacksIfNeeded(
|
|||||||
comptime init: Callbacks.InitFn,
|
comptime init: Callbacks.InitFn,
|
||||||
comptime tick: Callbacks.TickFn,
|
comptime tick: Callbacks.TickFn,
|
||||||
comptime deinit: Callbacks.DeinitFn,
|
comptime deinit: Callbacks.DeinitFn,
|
||||||
comptime debug: Callbacks.DebugFn,
|
comptime debug: Callbacks.DebugFn
|
||||||
comptime assets: Callbacks.LoadAssetsFn,
|
|
||||||
) void {
|
) void {
|
||||||
const builtin = @import("builtin");
|
const builtin = @import("builtin");
|
||||||
if (builtin.output_mode != .Lib) {
|
if (builtin.output_mode != .Lib) {
|
||||||
@ -512,9 +503,6 @@ pub fn exportCallbacksIfNeeded(
|
|||||||
@export(init, .{ .name = "init", .linkage = .strong });
|
@export(init, .{ .name = "init", .linkage = .strong });
|
||||||
@export(tick, .{ .name = "tick", .linkage = .strong });
|
@export(tick, .{ .name = "tick", .linkage = .strong });
|
||||||
@export(deinit, .{ .name = "deinit", .linkage = .strong });
|
@export(deinit, .{ .name = "deinit", .linkage = .strong });
|
||||||
if (build_options.asset_hot_reload) {
|
|
||||||
@export(assets, .{ .name = "loadAssets", .linkage = .strong });
|
|
||||||
}
|
|
||||||
if (build_options.has_imgui) {
|
if (build_options.has_imgui) {
|
||||||
@export(debug, .{ .name = "debug", .linkage = .strong });
|
@export(debug, .{ .name = "debug", .linkage = .strong });
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,84 +0,0 @@
|
|||||||
const std = @import("std");
|
|
||||||
const Game = @import("game");
|
|
||||||
const Engine = @import("engine");
|
|
||||||
const Lib = Engine.Lib;
|
|
||||||
const AssetBundle = Engine.AssetBundle;
|
|
||||||
|
|
||||||
fn readFileAll(gpa: std.mem.Allocator, dir: std.fs.Dir, sub_path: []const u8) ![]u8 {
|
|
||||||
const f = try dir.openFile(sub_path, .{});
|
|
||||||
defer f.close();
|
|
||||||
|
|
||||||
var wa: std.Io.Writer.Allocating = .init(gpa);
|
|
||||||
defer wa.deinit();
|
|
||||||
|
|
||||||
var buffer: [4 * 4096]u8 = undefined;
|
|
||||||
var reader = f.reader(&buffer);
|
|
||||||
_ = try reader.interface.stream(&wa.writer, .unlimited);
|
|
||||||
|
|
||||||
return try wa.toOwnedSlice();
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn main() !void {
|
|
||||||
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
|
|
||||||
const allocator = gpa.allocator();
|
|
||||||
defer _ = gpa.deinit();
|
|
||||||
|
|
||||||
const args = try std.process.argsAlloc(allocator);
|
|
||||||
defer std.process.argsFree(allocator, args);
|
|
||||||
|
|
||||||
if (args.len != 3) {
|
|
||||||
std.debug.print("Usage: ./asset-bundler <asset-dir> <output>", .{});
|
|
||||||
std.process.exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
const cwd = std.fs.cwd();
|
|
||||||
const asset_dir_path = args[1];
|
|
||||||
const output_path = args[2];
|
|
||||||
|
|
||||||
const asset_dir = try cwd.openDir(asset_dir_path, .{ .iterate = true });
|
|
||||||
|
|
||||||
var loader: Lib.Asset.Loader = .init(allocator, asset_dir);
|
|
||||||
defer loader.deinit();
|
|
||||||
Game.loadAssets(&loader);
|
|
||||||
|
|
||||||
var bundle = AssetBundle.init();
|
|
||||||
defer bundle.deinit(allocator);
|
|
||||||
|
|
||||||
for (loader.assets.items) |asset_desc| {
|
|
||||||
const id = asset_desc.id;
|
|
||||||
switch (asset_desc.kind) {
|
|
||||||
.font => |path| {
|
|
||||||
const font_data = try readFileAll(allocator, asset_dir, path);
|
|
||||||
defer allocator.free(font_data);
|
|
||||||
|
|
||||||
// TODO:
|
|
||||||
try bundle.appendFont(allocator, id, font_data, .{ .format = .ttf });
|
|
||||||
},
|
|
||||||
.sound => |path| {
|
|
||||||
const sound_data = try readFileAll(allocator, asset_dir, path);
|
|
||||||
defer allocator.free(sound_data);
|
|
||||||
|
|
||||||
try bundle.appendSound(allocator, id, sound_data, .{
|
|
||||||
// TODO:
|
|
||||||
.format = .vorbis,
|
|
||||||
.playback_style = .decode_once
|
|
||||||
});
|
|
||||||
},
|
|
||||||
.texture => |opts| {
|
|
||||||
const texture_data = try readFileAll(allocator, asset_dir, opts.path);
|
|
||||||
defer allocator.free(texture_data);
|
|
||||||
|
|
||||||
try bundle.appendTexture(allocator, id, texture_data, opts.info);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const output_file = try std.fs.cwd().createFile(output_path, .{ });
|
|
||||||
defer output_file.close();
|
|
||||||
|
|
||||||
var buffer: [4096 * 4]u8 = undefined;
|
|
||||||
var writer = output_file.writer(&buffer);
|
|
||||||
|
|
||||||
try bundle.write(&writer.interface);
|
|
||||||
try writer.interface.flush();
|
|
||||||
}
|
|
||||||
61
src/game.zig
61
src/game.zig
@ -9,20 +9,6 @@ const rgb = Engine.Math.rgb;
|
|||||||
|
|
||||||
const Game = @This();
|
const Game = @This();
|
||||||
|
|
||||||
const FontName = enum {
|
|
||||||
regular,
|
|
||||||
bold,
|
|
||||||
italic,
|
|
||||||
};
|
|
||||||
|
|
||||||
const AssetId = enum {
|
|
||||||
font_regular,
|
|
||||||
font_bold,
|
|
||||||
font_italic,
|
|
||||||
sound_wood,
|
|
||||||
texture_icon,
|
|
||||||
};
|
|
||||||
|
|
||||||
const State = struct {
|
const State = struct {
|
||||||
gpa: Allocator,
|
gpa: Allocator,
|
||||||
player: Vec2,
|
player: Vec2,
|
||||||
@ -40,25 +26,6 @@ pub fn init(opts: *const Engine.Init) callconv(.c) *anyopaque {
|
|||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn getFont(assets: Engine.Asset.Registry, font_name: FontName) FontId {
|
|
||||||
const asset_id = switch (font_name) {
|
|
||||||
.regular => AssetId.font_regular,
|
|
||||||
.bold => AssetId.font_bold,
|
|
||||||
.italic => AssetId.font_italic,
|
|
||||||
};
|
|
||||||
return assets.getFont(@intFromEnum(asset_id));
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn loadAssets(assets: *Engine.Asset.Loader) callconv(.c) void {
|
|
||||||
assets.addFont(@intFromEnum(AssetId.font_regular), "roboto-font/Roboto-Regular.ttf");
|
|
||||||
assets.addFont(@intFromEnum(AssetId.font_bold), "roboto-font/Roboto-Bold.ttf");
|
|
||||||
assets.addFont(@intFromEnum(AssetId.font_italic), "roboto-font/Roboto-Italic.ttf");
|
|
||||||
|
|
||||||
assets.addSound(@intFromEnum(AssetId.sound_wood), "wood01.ogg");
|
|
||||||
|
|
||||||
assets.addTexture(@intFromEnum(AssetId.texture_icon), "icon.png");
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn deinit(state_ptr: *anyopaque) callconv(.c) void {
|
pub fn deinit(state_ptr: *anyopaque) callconv(.c) void {
|
||||||
const state: *State = @alignCast(@ptrCast(state_ptr));
|
const state: *State = @alignCast(@ptrCast(state_ptr));
|
||||||
const gpa = state.gpa;
|
const gpa = state.gpa;
|
||||||
@ -89,10 +56,10 @@ pub fn tick(state_ptr: *anyopaque, frame: *Engine.Frame) callconv(.c) void {
|
|||||||
dir = dir.normalized();
|
dir = dir.normalized();
|
||||||
|
|
||||||
if (dir.x != 0 or dir.y != 0) {
|
if (dir.x != 0 or dir.y != 0) {
|
||||||
frame.playAudio(.{
|
// frame.playAudio(.{
|
||||||
.id = frame.assets.getSound(@intFromEnum(AssetId.sound_wood)),
|
// .id = frame.assets.getSound(@intFromEnum(AssetId.sound_wood)),
|
||||||
.volume = 0.1
|
// .volume = 0.1
|
||||||
});
|
// });
|
||||||
}
|
}
|
||||||
|
|
||||||
state.player = state.player.add(dir.multiplyScalar(50 * dt));
|
state.player = state.player.add(dir.multiplyScalar(50 * dt));
|
||||||
@ -102,7 +69,7 @@ pub fn tick(state_ptr: *anyopaque, frame: *Engine.Frame) callconv(.c) void {
|
|||||||
.color = rgb(20, 20, 20)
|
.color = rgb(20, 20, 20)
|
||||||
});
|
});
|
||||||
|
|
||||||
const icon = frame.assets.getTexture(@intFromEnum(AssetId.texture_icon));
|
// const icon = frame.assets.getTexture(@intFromEnum(AssetId.texture_icon));
|
||||||
|
|
||||||
const size = Vec2.init(20, 20);
|
const size = Vec2.init(20, 20);
|
||||||
frame.drawRectangle(.{
|
frame.drawRectangle(.{
|
||||||
@ -111,10 +78,10 @@ pub fn tick(state_ptr: *anyopaque, frame: *Engine.Frame) callconv(.c) void {
|
|||||||
.size = size
|
.size = size
|
||||||
},
|
},
|
||||||
.color = rgb(200, 2, 200),
|
.color = rgb(200, 2, 200),
|
||||||
.sprite = .{
|
// .sprite = .{
|
||||||
.texture = icon,
|
// .texture = icon,
|
||||||
.uv = .unit
|
// .uv = .unit
|
||||||
}
|
// }
|
||||||
});
|
});
|
||||||
if (dir.x != 0 or dir.y != 0) {
|
if (dir.x != 0 or dir.y != 0) {
|
||||||
frame.drawRectanglOutline(state.player.sub(size.divideScalar(2)), size, rgb(20, 20, 20), 3);
|
frame.drawRectanglOutline(state.player.sub(size.divideScalar(2)), size, rgb(20, 20, 20), 3);
|
||||||
@ -131,10 +98,10 @@ pub fn tick(state_ptr: *anyopaque, frame: *Engine.Frame) callconv(.c) void {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
frame.drawText(state.player, "Player", .{
|
// frame.drawText(state.player, "Player", .{
|
||||||
.font = getFont(frame.assets, .regular),
|
// .font = getFont(frame.assets, .regular),
|
||||||
.size = 10
|
// .size = 10
|
||||||
});
|
// });
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn debug(state_ptr: *anyopaque, imgui: *Engine.ImGui) callconv(.c) void {
|
pub fn debug(state_ptr: *anyopaque, imgui: *Engine.ImGui) callconv(.c) void {
|
||||||
@ -144,5 +111,5 @@ pub fn debug(state_ptr: *anyopaque, imgui: *Engine.ImGui) callconv(.c) void {
|
|||||||
}
|
}
|
||||||
|
|
||||||
comptime {
|
comptime {
|
||||||
Engine.exportCallbacksIfNeeded(init, tick, deinit, debug, loadAssets);
|
Engine.exportCallbacksIfNeeded(init, tick, deinit, debug);
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user