diff --git a/build.zig b/build.zig index d490d0e..3ccfdc6 100644 --- a/build.zig +++ b/build.zig @@ -33,9 +33,6 @@ pub fn build(b: *std.Build) !void { b.sysroot = root_path ++ "libs/system-sdk/macos12"; } - exe.addIncludePath(.{ .path = root_path ++ "game/osx" }); - exe.addCSourceFile(.{ .file = .{ .path = root_path ++ "game/osx/osx_helper.mm" }, .flags = &.{"-fobjc-arc"} }); - exe.linkFramework("Metal"); exe.linkFramework("QuartzCore"); exe.linkFramework("Foundation"); diff --git a/game/challenge.zig b/game/challenge.zig index d7facda..c987945 100644 --- a/game/challenge.zig +++ b/game/challenge.zig @@ -17,6 +17,9 @@ pub const ChallengeInfo = struct { /// The speed of the map speed: f64 = 1, key: i32 = 0, + /// A time added to the current time to "offset" the visuals/timing from the actual audio time, + /// this is used to fix audio delay caused by the OS, hardware, and poor map timing + audio_offset: i16 = 0, /// Whether or not the challenge is valid valid: bool = true, diff --git a/game/gfx.zig b/game/gfx.zig index 0bf7c7a..c1a9fba 100644 --- a/game/gfx.zig +++ b/game/gfx.zig @@ -543,12 +543,14 @@ pub const Instance = struct { } } else if (info.subsystem == c.SDL_SYSWM_COCOA) { if (@hasDecl(c, "SDL_VIDEO_DRIVER_COCOA")) { + const metal_view = c.SDL_Metal_CreateView(window); + descriptor.nextInChain = @as([*c]const c.WGPUChainedStruct, @ptrCast(&c.WGPUSurfaceDescriptorFromMetalLayer{ .chain = .{ .sType = c.WGPUSType_SurfaceDescriptorFromMetalLayer, .next = null, }, - .layer = c.createMetalLayer(info.info.cocoa.window), + .layer = c.SDL_Metal_GetLayer(metal_view), })); } else { return Error.MissingSDLCocoa; diff --git a/game/main.zig b/game/main.zig index 6952407..f42b4a1 100644 --- a/game/main.zig +++ b/game/main.zig @@ -20,9 +20,6 @@ pub const c = @cImport({ @cDefine("CIMGUI_USE_SDL2", "1"); @cDefine("CIMGUI_USE_WGPU", "1"); @cInclude("cimgui.h"); - if (builtin.target.isDarwin()) { - @cInclude("osx_helper.h"); - } }); fn runGame() !void { diff --git a/game/osx/osx_helper.h b/game/osx/osx_helper.h deleted file mode 100644 index 40fdc58..0000000 --- a/game/osx/osx_helper.h +++ /dev/null @@ -1 +0,0 @@ -void* createMetalLayer(void* window); \ No newline at end of file diff --git a/game/osx/osx_helper.mm b/game/osx/osx_helper.mm deleted file mode 100644 index 59fc9fa..0000000 --- a/game/osx/osx_helper.mm +++ /dev/null @@ -1,18 +0,0 @@ -#include "osx_helper.h" - -#include -#include -#include - -extern "C" { - -CAMetalLayer *createMetalLayer(NSWindow *ns_window) -{ - id metal_layer = NULL; - [ns_window.contentView setWantsLayer:YES]; - metal_layer = [CAMetalLayer layer]; - [ns_window.contentView setLayer:metal_layer]; - return metal_layer; -} - -} \ No newline at end of file diff --git a/game/screens/gameplay.zig b/game/screens/gameplay.zig index 9798717..8836ff3 100644 --- a/game/screens/gameplay.zig +++ b/game/screens/gameplay.zig @@ -83,11 +83,12 @@ const GameplayData = struct { accuracy_text: [:0]const u8 = "", ///The color of the accuracy text accuracy_text_color: Gfx.ColorF = .{ 1, 1, 1, 1 }, + + audio_offset: f64, }; const GaugeData = struct { //Gauge - gauge: isize, gauge_max: isize, gauge_last_count: isize, @@ -135,7 +136,10 @@ const GaugeData = struct { const count = data.active_note; if (count > self.gauge_last_count) { - var lost: isize = @intCast(count - self.clear_count); + const icount: isize = @intCast(count); + const iclear_count: isize = @intCast(self.clear_count); + + var lost: isize = icount - iclear_count; var t = lost - self.gauge_last_lost; self.gauge_last_lost = lost; while (t > 0) : (t -= 1) { @@ -289,6 +293,7 @@ pub fn initScreen(self: *Screen, allocator: std.mem.Allocator, gfx: Gfx) anyerro .accuracy_text = try std.time.Timer.start(), }, .gauge_data = GaugeData.init(self.state.current_map.?.fumen.lyrics.len), + .audio_offset = @as(f64, @floatFromInt(challenge.audio_offset)) / 1000.0, }; //Reset the hit status for all the lyrics before the game starts @@ -397,7 +402,7 @@ pub fn char(self: *Screen, typed_char: []const u8) anyerror!void { // std.debug.print("user wrote {s}\n", .{typed_char}); - var current_time = try self.state.audio_tracker.music.?.getSecondPosition(); + var current_time = try self.state.audio_tracker.music.?.getSecondPosition() - data.audio_offset; var current_note: *Fumen.Lyric = &data.music.fumen.lyrics[data.active_note]; var next_note: ?*Fumen.Lyric = if (data.active_note + 1 == data.music.fumen.lyrics.len) null else &data.music.fumen.lyrics[data.active_note + 1]; @@ -854,7 +859,7 @@ inline fn getDrawPosY(x: f32) f32 { pub fn renderScreen(self: *Screen, render_state: RenderState) anyerror!void { var data = self.getData(GameplayData); - data.current_time = try self.state.audio_tracker.music.?.getSecondPosition(); + data.current_time = try self.state.audio_tracker.music.?.getSecondPosition() - data.audio_offset; //In debug mode, allow the user to scrub through the song if (builtin.mode == .Debug) { diff --git a/game/screens/song_select.zig b/game/screens/song_select.zig index 5ce4e67..14e4ea0 100644 --- a/game/screens/song_select.zig +++ b/game/screens/song_select.zig @@ -158,6 +158,16 @@ pub fn keyDown(self: *Screen, key: c.SDL_Keysym) anyerror!void { data.challenge_info.key += 1; } }, + c.SDLK_LEFTBRACKET => { + if (data.challenge_info.audio_offset > -1000) { + data.challenge_info.audio_offset -= 1; + } + }, + c.SDLK_RIGHTBRACKET => { + if (data.challenge_info.audio_offset < 1000) { + data.challenge_info.audio_offset += 1; + } + }, c.SDLK_F6 => data.challenge_info.sin = !data.challenge_info.sin, c.SDLK_F7 => data.challenge_info.cos = !data.challenge_info.cos, c.SDLK_F8 => data.challenge_info.tan = !data.challenge_info.tan, @@ -817,6 +827,20 @@ pub fn renderScreen(self: *Screen, render_state: RenderState) anyerror!void { _ = try render_state.fontstash.drawText(.{ 430, Screen.display_height - 20 }, sct_text, state); } + { + var state = Fontstash.Normal; + + state.size *= render_state.gfx.scale; + var context: Fontstash.Fontstash.WriterContext = .{ + .state = state, + .draw = true, + .draw_position = Gfx.Vector2{ 470, Screen.display_height - 20 } * @as(Gfx.Vector2, @splat(render_state.gfx.scale)), + }; + var writer = try render_state.fontstash.context.writer(&context); + + try std.fmt.format(writer, "[ Offset: {d} ]", .{data.challenge_info.audio_offset}); + } + const step_timer_length = 1.0 / 60.0; data.step_timer += render_state.game_state.delta_time;