Skip to content

Commit

Permalink
Implement display of rankings
Browse files Browse the repository at this point in the history
  • Loading branch information
Beyley committed Dec 2, 2023
1 parent 551d754 commit 5f1b950
Show file tree
Hide file tree
Showing 7 changed files with 178 additions and 39 deletions.
5 changes: 5 additions & 0 deletions game/config.zig
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ const Self = @This();
volume: f64,
window_scale: f32,
display_romaji: bool,
vsync: bool,

pub fn readConfig() !Self {
var file = try std.fs.cwd().openFile("UTyping_config.txt", .{});
Expand All @@ -18,6 +19,7 @@ pub fn readConfig() !Self {
.volume = 0.25,
.window_scale = 1.0,
.display_romaji = true,
.vsync = false,
};

while (try ini_reader.next()) |item| {
Expand All @@ -28,6 +30,9 @@ pub fn readConfig() !Self {
self.window_scale = try std.fmt.parseFloat(f32, item.value);
} else if (std.mem.eql(u8, item.key, "DisplayRomaji")) {
self.display_romaji = try std.fmt.parseInt(u1, item.value, 2) != 0;
} else if (std.mem.eql(u8, item.key, "WaitVSync")) {
//Bit of an ugly hack, but sure!
self.vsync = std.ascii.eqlIgnoreCase(item.value, "true");
} else {
std.debug.print("Unknown config option \"{s}\" with value \"{s}\"\n", .{ item.key, item.value });
}
Expand Down
8 changes: 8 additions & 0 deletions game/fontstash.zig
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,14 @@ pub const Normal: Fontstash.State = .{
},
};

pub const Ranking: Fontstash.State = .{
.font = Mincho,
.size = 16,
.alignment = .{
.vertical = .top,
},
};

gfx: *Gfx,
renderer: Renderer,
context: *Fontstash,
Expand Down
9 changes: 6 additions & 3 deletions game/gfx.zig
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ const c = @import("main.zig").c;
const zmath = @import("zmath");
const img = @import("zigimg");

const Config = @import("config.zig");

const Self = @This();

pub const Vector2 = @Vector(2, f32);
Expand All @@ -15,6 +17,7 @@ pub const ColorF = @Vector(4, f32);
pub const ColorB = @Vector(4, u8);
///A rectangle with its bounds specified as u32
pub const RectU = @Vector(4, u32);
pub const RectF = @Vector(4, f32);

pub const Vector2One: Vector2 = @splat(@as(f32, 1));
pub const Vector2Zero: Vector2 = @splat(@as(f32, 0));
Expand Down Expand Up @@ -130,9 +133,9 @@ const PresentMode = enum(c_uint) {
mailbox = 3,
};

pub fn init(window: *c.SDL_Window, scale: f32) !Self {
pub fn init(window: *c.SDL_Window, config: Config) !Self {
var self: Self = Self{
.scale = scale,
.scale = config.window_scale,
};

//Update the viewport
Expand Down Expand Up @@ -165,7 +168,7 @@ pub fn init(window: *c.SDL_Window, scale: f32) !Self {
var modes_to_try: []const PresentMode = &.{ .mailbox, .fifo, .immediate };

//If we are on an iGPU, lets prefer standard vsync over mailbox
if (properties.adapterType == c.WGPUAdapterType_IntegratedGPU) {
if (config.vsync) {
modes_to_try = &.{ .fifo, .mailbox, .immediate };
}

Expand Down
2 changes: 1 addition & 1 deletion game/main.zig
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ fn runGame() !void {
try bass.setConfig(.global_stream_volume, @intFromFloat(state.config.volume * 10000));

//Initialize our graphics
var gfx: Gfx = try Gfx.init(window, state.config.window_scale);
var gfx: Gfx = try Gfx.init(window, state.config);
defer gfx.deinit();

const imgui_context = c.igCreateContext(null);
Expand Down
31 changes: 16 additions & 15 deletions game/music.zig
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,22 @@ pub fn readFromFile(allocator: std.mem.Allocator, path: std.fs.Dir, file: std.fs
self.fumen.* = try Fumen.readFromFile(allocator, fumen_file, path);
errdefer self.fumen.deinit();

const ranking_path = try path.realpathAlloc(allocator, self.ranking_file_name);
const ranking_path = path.realpathAlloc(allocator, self.ranking_file_name) catch |err| blk: {
//If we got a FileNotFound error, write out a new blank ranking file
if (err == std.fs.Dir.OpenError.FileNotFound) {
const ranking = Ranking.init();

var new_ranking_file = try path.createFile(self.ranking_file_name, .{});

try ranking.writeRanking(new_ranking_file.writer());

new_ranking_file.close();

break :blk try path.realpathAlloc(allocator, self.ranking_file_name);
} else {
return err;
}
};
defer allocator.free(ranking_path);

var ranking_file = try std.fs.openFileAbsolute(ranking_path, .{});
Expand Down Expand Up @@ -332,20 +347,6 @@ pub fn draw(
_ = try render_state.fontstash.drawText(.{ title_x, title_y + y }, self.title, state);
}

pub fn drawRanking(
self: Self,
render_state: Screen.RenderState,
pos: Gfx.Vector2,
ranking_pos: isize,
rank_len: usize,
) !void {
_ = self;
_ = rank_len;
_ = ranking_pos;
_ = pos;
_ = render_state;
}

pub fn drawComment(self: Self, render_state: Screen.RenderState, pos: Gfx.Vector2) !void {
for (self.comment, 0..) |comment, i| {
_ = try render_state.fontstash.drawText(
Expand Down
144 changes: 129 additions & 15 deletions game/ranking.zig
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,20 @@ pub const UTypingDate = packed struct(i32) {
year: u16,
};

pub fn init() Self {
var self = Self{
.play_time = 0,
.play_count = 0,
.achievement = .no_data,
.changed = false,
.scores = undefined,
};

@memset(&self.scores, Score.init());

return self;
}

/// Gets the current date, in the UTyping date format
pub fn getUTypingDate() UTypingDate {
//Get the current timestamp
Expand All @@ -53,19 +67,19 @@ pub fn draw(
pos: Gfx.Vector2,
rank_begin: usize,
rank_len: usize,
comptime font: []const u8,
) !void {
_ = render_state;
for (rank_begin..(rank_begin + rank_len)) |i| {
//Break out if we are drawing more than the max amount of storable ranks
if (i >= ranking_len) {
break;
}

try self.scores[i].draw(pos + Gfx.Vector2{ 0, 48 * i }, i + 1, font);
try self.scores[i].draw(render_state, pos + Gfx.Vector2{ 0, @floatFromInt(48 * i) }, i + 1);
}
}

const ranking_file_version = 5;

pub fn readRanking(file: std.fs.File) !Self {
var ranking = Self{
.achievement = .no_data,
Expand All @@ -89,8 +103,6 @@ pub fn readRanking(file: std.fs.File) !Self {
return err;
};

const ranking_file_version = 5;

//If the first byte of the version is greater than 32, than assume version is 0
if ((version & 0xff) > ' ') {
version = 0;
Expand All @@ -108,7 +120,7 @@ pub fn readRanking(file: std.fs.File) !Self {
return error.UnknownRankingVersion;
}

//In version 4, achivement was added to the score data34
//In version 4, achivement was added to the score data
if (version >= 4) {
ranking.achievement = try reader.readEnum(RankingLevel, .little);
}
Expand Down Expand Up @@ -144,6 +156,17 @@ pub fn readRanking(file: std.fs.File) !Self {
return ranking;
}

pub fn writeRanking(self: Self, writer: std.fs.File.Writer) !void {
try writer.writeInt(i32, ranking_file_version, .little);
try writer.writeInt(i32, @intFromEnum(self.achievement), .little);
try writer.writeInt(i32, self.play_count, .little);
try writer.writeInt(i32, self.play_time, .little);
try writer.writeInt(i32, self.scores.len, .little);
for (&self.scores) |score| {
try score.write(writer);
}
}

pub const RankingLevel = enum(i32) {
no_data = 0,
failed = 0x0100,
Expand Down Expand Up @@ -194,7 +217,9 @@ pub const Score = struct {
.month = 0,
.year = 0,
},
.challenge = .{},
.challenge = .{
.speed = 0,
},
};

//Zero-init the score to all zeroes
Expand All @@ -210,13 +235,72 @@ pub const Score = struct {
render_state: RenderState,
pos: Gfx.Vector2,
n: usize,
comptime font: []const u8,
) !void {
_ = font;
_ = n;
_ = pos;
_ = render_state;
_ = self;
var buf: [256]u8 = undefined;
var stream = std.io.fixedBufferStream(&buf);
const writer = stream.writer();

const color = Gfx.ColorF{ 1, 1, 1, 1 };
{
stream.pos = 0;
try formatOrdinal(writer, n);
try std.fmt.format(writer, ": {s} {d:0>8} 点( {d:0>7} + {d:0>7} ),", .{
std.mem.sliceTo(&self.name, 0),
@as(u32, @intCast(self.score)),
@as(u32, @intCast(self.score_accuracy)),
@as(u32, @intCast(self.score_typing)),
});

var state = Fontstash.Ranking;
state.color = color;

_ = try render_state.fontstash.drawText(pos + Gfx.Vector2{ 40, 6 }, buf[0..stream.pos], state);
}
{
stream.pos = 0;
if (self.date.year == 0) {
try std.fmt.format(writer, "----/--/--", .{});
} else {
try std.fmt.format(writer, "{d:0>4}/{d:0>2}/{d:0>2}", .{
@as(u32, @intCast(self.date.year)),
@as(u32, @intCast(self.date.month)),
@as(u32, @intCast(self.date.day)),
});
}

var state = Fontstash.Ranking;
state.color = color;
state.alignment.horizontal = .right;

_ = try render_state.fontstash.drawText(pos + Gfx.Vector2{ Screen.display_width - 40, 6 }, buf[0..stream.pos], state);
}
{
stream.pos = 0;
try self.challenge.format({}, {}, writer);
if (self.combo_max >= 0) {
try std.fmt.format(writer, ", 最大 {d:0>4} コンボ, ({d:0>4}/{d:0>4}/{d:0>4}/{d:0>4}/{d:0>4})", .{
@as(u32, @intCast(self.combo_max)),
@as(u32, @intCast(self.count[0])),
@as(u32, @intCast(self.count[1])),
@as(u32, @intCast(self.count[2])),
@as(u32, @intCast(self.count[3])),
@as(u32, @intCast(self.count[4])),
});
} else {
try std.fmt.format(writer, ", フル コンボ, ({d:0>4}/{d:0>4}/{d:0>4}/{d:0>4}/{d:0>4})", .{
@as(u32, @intCast(self.count[0])),
@as(u32, @intCast(self.count[1])),
@as(u32, @intCast(self.count[2])),
@as(u32, @intCast(self.count[3])),
@as(u32, @intCast(self.count[4])),
});
}
var state = Fontstash.Ranking;
state.color = color;
state.alignment.horizontal = .right;

_ = try render_state.fontstash.drawText(pos + Gfx.Vector2{ Screen.display_width - 40, 48 - 6 - 16 }, buf[0..stream.pos], state);
}
}

pub fn getLevel(self: Score) RankingLevel {
Expand All @@ -226,8 +310,10 @@ pub const Score = struct {
return .perfect;
}

const challenge_num = 7;

pub fn read(reader: anytype, version: i32) !Score {
var score = init();
var score = Score.init();

//In version 1, the score name length was bumped from 8 to 16
if (version >= 1) {
Expand All @@ -254,7 +340,6 @@ pub const Score = struct {
//Read the max combo
score.combo_max = try reader.readInt(i32, .little);

const challenge_num = 7;
//In version 1, challenges were added
if (version >= 1) {
//Iterate over all known challenges
Expand Down Expand Up @@ -291,4 +376,33 @@ pub const Score = struct {

return score;
}

pub fn write(self: Score, writer: std.fs.File.Writer) !void {
try writer.writeAll(&self.name);
try writer.writeInt(i32, self.score, .little);
try writer.writeInt(i32, self.score_accuracy, .little);
try writer.writeInt(i32, self.score_typing, .little);
for (&self.count) |count| {
try writer.writeInt(i32, count, .little);
}
try writer.writeInt(i32, self.count_all, .little);
try writer.writeInt(i32, self.combo_max, .little);

try writer.writeByte(@intFromBool(self.challenge.hidden));
try writer.writeByte(@intFromBool(self.challenge.sudden));
try writer.writeByte(@intFromBool(self.challenge.stealth));
try writer.writeByte(@intFromBool(self.challenge.lyrics_stealth));
try writer.writeByte(@intFromBool(self.challenge.sin));
try writer.writeByte(@intFromBool(self.challenge.cos));
try writer.writeByte(@intFromBool(self.challenge.tan));

for (challenge_num..16) |_| {
try writer.writeByte(0);
}

try writer.writeInt(i32, @intFromFloat(self.challenge.speed * 10), .little);
try writer.writeInt(i32, self.challenge.key, .little);

try writer.writeInt(i32, @bitCast(self.date), .little);
}
};
18 changes: 13 additions & 5 deletions game/screens/song_select.zig
Original file line number Diff line number Diff line change
Expand Up @@ -860,15 +860,23 @@ pub fn renderScreen(self: *Screen, render_state: RenderState) anyerror!void {

fn drawMainRanking(render_state: Screen.RenderState, music: Music, ranking_pos: isize, pos: Gfx.Vector2, height: f32) !void {
const yMin = @max(pos[1], 0);
_ = yMin;
const yMax = @min(pos[1] + height, 360);
_ = yMax;

// TODO: debug why scissors are borked :(
// try render_state.renderer.setScissor(.{ 10, yMin, Screen.display_width - 20, yMax - yMin });
var scissor: Gfx.RectF = .{ 10, yMin, Screen.display_width - 20, yMax - yMin };
scissor *= @splat(render_state.gfx.scale);

const scissor_u: Gfx.RectU = .{
@intFromFloat(@max(0, scissor[0])),
@intFromFloat(@max(0, scissor[1])),
@intFromFloat(@max(0, scissor[2])),
@intFromFloat(@max(0, scissor[3])),
};

try render_state.renderer.setScissor(scissor_u);
try render_state.fontstash.renderer.setScissor(scissor_u);

if (ranking_pos >= 0) {
try music.drawRanking(render_state, .{ pos[0], pos[1] + 6 }, ranking_pos, ranking_draw_len);
try music.ranking.draw(render_state, .{ pos[0], pos[1] + 6 }, @intCast(ranking_pos), ranking_draw_len);
} else {
try music.drawComment(render_state, .{ pos[0], pos[1] + 6 });
try music.drawPlayData(render_state, .{ pos[0], pos[1] + 6 + h_comment + 4 });
Expand Down

0 comments on commit 5f1b950

Please sign in to comment.