summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/geom.zig36
-rw-r--r--src/main.zig14
-rw-r--r--src/misc.zig56
3 files changed, 51 insertions, 55 deletions
diff --git a/src/geom.zig b/src/geom.zig
index c84d2aa..af6bd21 100644
--- a/src/geom.zig
+++ b/src/geom.zig
@@ -30,7 +30,7 @@ fn dot(u: anytype, v: @TypeOf(u)) Child(@TypeOf(u)) {
 }
 
 export fn sqrlen(v: XYZ) f32 {
-    const u = @bitCast(@Vector(3, f32), v);
+    const u: @Vector(3, f32) = @bitCast(v);
     return dot(u, u);
 }
 
@@ -39,7 +39,7 @@ fn norm(v: anytype) Child(@TypeOf(v)) {
 }
 
 export fn len(v: XYZ) f32 {
-    const u = @bitCast(@Vector(3, f32), v);
+    const u: @Vector(3, f32) = @bitCast(v);
     return norm(u);
 }
 
@@ -53,16 +53,20 @@ export fn crossProduct(u: XYZ, v: XYZ) XYZ {
     };
 }
 
+inline fn splat(x: f32) @Vector(3, f32) {
+    return @splat(x);
+}
+
 export fn normalize(v: XYZ) XYZ {
-    const u = @bitCast(@Vector(3, f32), v);
+    const u: @Vector(3, f32) = @bitCast(v);
     const d = norm(u);
-    return if (d == 0) v else @bitCast(XYZ, u / @splat(3, d));
+    return if (d == 0) v else @bitCast(u / splat(d));
 }
 
 export fn reflect(v: XYZ, n: XYZ) XYZ {
-    const u = @bitCast(@Vector(3, f32), v);
-    const m = @bitCast(@Vector(3, f32), n);
-    return @bitCast(XYZ, u - m * @splat(3, dot(u, m) * 2));
+    const u: @Vector(3, f32) = @bitCast(v);
+    const m: @Vector(3, f32) = @bitCast(n);
+    return @bitCast(u - m * splat(dot(u, m) * 2));
 }
 
 fn rotate2d(i: *f32, j: *f32, a: f32) void {
@@ -84,15 +88,15 @@ export fn rotate(v: XYZ, deg_x: f32, deg_y: f32, deg_z: f32) XYZ {
 
 export fn segmentIntersectsSphere(a: XYZ, b: XYZ, i: XYZ, r: f32) bool {
     // FIXME: call directly with vectors
-    const p = @bitCast(@Vector(3, f32), a);
-    const q = @bitCast(@Vector(3, f32), b);
-    const c = @bitCast(@Vector(3, f32), i);
+    const p: @Vector(3, f32) = @bitCast(a);
+    const q: @Vector(3, f32) = @bitCast(b);
+    const c: @Vector(3, f32) = @bitCast(i);
 
-    if (@reduce(.Or, @max(p, q) < c - @splat(3, r))) return false;
-    if (@reduce(.Or, @min(p, q) > c + @splat(3, r))) return false;
+    if (@reduce(.Or, @max(p, q) < c - splat(r))) return false;
+    if (@reduce(.Or, @min(p, q) > c + splat(r))) return false;
     // https://en.wikipedia.org/wiki/Line–sphere_intersection
     const d = q - p; // line's direction
-    const u = d / @splat(3, norm(d)); // unit vector
+    const u = d / splat(norm(d)); // unit vector
     return sqr(dot(u, (p - c))) >= @reduce(.Add, sqr(p - c)) - sqr(r);
 }
 
@@ -242,8 +246,7 @@ export fn setFrustum(frustum: [*][4]f32, p: [*]const f32,
 export fn cubeInFrustum(frustum: [*][4]f32,
                         x: f32, y: f32, z: f32, size: f32) bool {
     const delta = [_]f32{ -size, size };
-    var i = @as(u8, 0);
-    loop: while (i < 6) : (i += 1) {
+    loop: for (0..6) |i| {
         for (delta) |dx| for (delta) |dy| for (delta) |dz|
             if (frustum[i][0] * (x + dx) + frustum[i][1] * (y + dy)
                 + frustum[i][2] * (z + dz) + frustum[i][3] > 0) continue :loop;
@@ -254,8 +257,7 @@ export fn cubeInFrustum(frustum: [*][4]f32,
 
 export fn sphereInFrustum(frustum: [*][4]f32,
                           x: f32, y: f32, z: f32, r: f32) bool {
-    var i = @as(u8, 0);
-    while (i < 6) : (i += 1)
+    for (0..6) |i|
         if (frustum[i][0] * x + frustum[i][1] * y
             + frustum[i][2] * z + frustum[i][3] <= -r)
             return false;
diff --git a/src/main.zig b/src/main.zig
index 49f2b49..b44b592 100644
--- a/src/main.zig
+++ b/src/main.zig
@@ -49,7 +49,7 @@ fn handleKey(window: gf.Window, key: gf.Key, scancode: c_int,
              action: gf.KeyAction, mods: gf.Mods) void {
     _ = window;
     _ = scancode;
-    c.handleKey(game, @enumToInt(key), @enumToInt(action), mods.toInt());
+    c.handleKey(game, @intFromEnum(key), @intFromEnum(action), mods.toInt());
 }
 
 fn look(window: gf.Window, xpos: f64, ypos: f64) void {
@@ -60,7 +60,7 @@ fn look(window: gf.Window, xpos: f64, ypos: f64) void {
 fn click(window: gf.Window, button: gf.MouseButton,
          action: gf.MouseButton.Action, mods: gf.Mods) void {
     _ = window;
-    c.click(game, @enumToInt(button), @enumToInt(action), mods.toInt());
+    c.click(game, @intFromEnum(button), @intFromEnum(action), mods.toInt());
 }
 
 /// Return a floating point value evenly distributed in the range [0, 1).
@@ -92,14 +92,14 @@ pub fn main() !void {
                                         "Black Shades", .{}, .{});
     try window.makeCurrent();
 
-    prng = DefaultPrng.init(@bitCast(u64, try gf.getTime()));
-    game = c.makeGame(@bitCast(c.Config, config),
-                      @bitCast(c.Scores, try loadScores(loca.user_data))).?;
-    defer saveScores(loca.user_data, @bitCast(Scores, c.getScores(game)))
+    prng = DefaultPrng.init(@bitCast(try gf.getTime()));
+    game = c.makeGame(@bitCast(config),
+                      @bitCast(try loadScores(loca.user_data))).?;
+    defer saveScores(loca.user_data, @bitCast(c.getScores(game)))
         catch unreachable;
 
     try window.setSizeCallback(resizeWindow);
-    try gf.swapInterval(@boolToInt(config.vsync));
+    try gf.swapInterval(@intFromBool(config.vsync));
     c.initGl(game);
 
     if (try gf.rawMouseMotionSupported())
diff --git a/src/misc.zig b/src/misc.zig
index 6f1d893..ebec4ef 100644
--- a/src/misc.zig
+++ b/src/misc.zig
@@ -18,7 +18,7 @@
 // along with Black Shades.  If not, see <https://www.gnu.org/licenses/>.
 
 const Dir = std.fs.Dir;
-const TokenIterator = std.mem.TokenIterator(u8);
+const TokenIterator = std.mem.TokenIterator(u8, .scalar);
 const allocPrint = std.fmt.allocPrint;
 const allocator = std.heap.c_allocator;
 const assert = std.debug.assert;
@@ -36,7 +36,7 @@ const sep = std.fs.path.sep;
 const span = std.mem.span;
 const startsWith = std.mem.startsWith;
 const std = @import("std");
-const tokenize = std.mem.tokenize;
+const tokenizeScalar = std.mem.tokenizeScalar;
 
 const al = @import("zeal");
 const gf = @import("gfz");
@@ -49,7 +49,7 @@ const c = @import("cimport.zig");
 /// Return whether the given keyboard key is pressed.
 export fn keyPress(key: c_int) bool {
     const window = (gf.Window.getCurrent() catch unreachable).?;
-    return (window.getKey(@intToEnum(gf.Key, key)) catch unreachable) == .press;
+    return (window.getKey(@enumFromInt(key)) catch unreachable) == .press;
 }
 
 /// Read given file to heap, allocated by C allocator.
@@ -80,22 +80,22 @@ export fn loadAnimation(name: [*:0]const u8) extern struct {
     }) catch unreachable;
     defer allocator.free(anim_file);
     const length = count(u8, anim_file, "\t") - 1;
-    var anim = tokenize(u8, anim_file, "\n");
+    var anim = tokenizeScalar(u8, anim_file, '\n');
     _ = anim.next().?; // ignore field names
 
     const frames = allocator.alloc(Frame, length) catch unreachable;
     for (frames) |*frame| {
-        var values = tokenize(u8, anim.next().?, "\t");
+        var values = tokenizeScalar(u8, anim.next().?, '\t');
         const frame_file = readFile(dir, "{s}{c}frames{c}{s}.tsv", .{
             name, sep, sep, values.next().?, // $animation/frames/$frame.tsv
         }) catch unreachable;
         defer allocator.free(frame_file);
         frame.speed = parseFloat(f32, values.next().?) catch unreachable;
 
-        var joints = tokenize(u8, frame_file, "\n");
+        var joints = tokenizeScalar(u8, frame_file, '\n');
         _ = joints.next().?; // ignore field names
-        for (frame.joints) |*joint| {
-            var coordinates = tokenize(u8, joints.next().?, "\t");
+        for (&frame.joints) |*joint| {
+            var coordinates = tokenizeScalar(u8, joints.next().?, '\t');
             joint.* = .{
                 .x = parseFloat(f32, coordinates.next().?) catch unreachable,
                 .y = parseFloat(f32, coordinates.next().?) catch unreachable,
@@ -126,7 +126,7 @@ const Joint = extern struct {
     parent: i8,
 
     pub fn load(self: *Joint, row: []const u8) !void {
-        var values = tokenize(u8, row, "\t");
+        var values = tokenizeScalar(u8, row, '\t');
         self.x = try parseFloat(f32, values.next().?);
         self.y = try parseFloat(f32, values.next().?);
         self.z = try parseFloat(f32, values.next().?);
@@ -143,7 +143,7 @@ export fn loadJoints(joints: [*]Joint) void {
     const file = readFile(cwd(), data_dir ++ "joints.tsv", .{})
         catch unreachable;
     defer allocator.free(file);
-    var tsv = tokenize(u8, file, "\n");
+    var tsv = tokenizeScalar(u8, file, '\n');
     _ = tsv.next().?; // ignore field names
     var i = @as(u8, 0);
     while (tsv.next()) |row| : (i += 1)
@@ -164,7 +164,7 @@ const OffIterator = struct {
     token_iterator: TokenIterator,
 
     pub fn init(buffer: []const u8) OffIterator {
-        var self = .{ .token_iterator = tokenize(u8, buffer, "\n") };
+        var self = .{ .token_iterator = tokenizeScalar(u8, buffer, '\n') };
         if (!endsWith(u8, self.token_iterator.next().?, "OFF"))
             self.token_iterator.reset();
         return self;
@@ -172,7 +172,7 @@ const OffIterator = struct {
 
     pub fn next(self: *OffIterator) ?TokenIterator {
         while (self.token_iterator.next()) |line| {
-            var words = tokenize(u8, line, " ");
+            var words = tokenizeScalar(u8, line, ' ');
             if (words.next()) |word| { // not empty
                 if (!startsWith(u8, word, "#")) { // not comment
                     words.reset();
@@ -247,7 +247,7 @@ const Muscle = extern struct {
     parent2: i8,
 
     pub fn load(self: *Muscle, row: []const u8) !void {
-        var values = tokenize(u8, row, "\t");
+        var values = tokenizeScalar(u8, row, '\t');
         self.length = try parseFloat(f32, values.next().?);
         self.initlen = try parseFloat(f32, values.next().?);
         self.minlen = try parseFloat(f32, values.next().?);
@@ -264,7 +264,7 @@ export fn loadMuscles(muscles: [*]Muscle) void {
     const file = readFile(cwd(), data_dir ++ "muscles.tsv", .{})
         catch unreachable;
     defer allocator.free(file);
-    var tsv = tokenize(u8, file, "\n");
+    var tsv = tokenizeScalar(u8, file, '\n');
     _ = tsv.next().?; // ignore field names
     var i = @as(u8, 0);
     while (tsv.next()) |row| : (i += 1)
@@ -306,7 +306,7 @@ export fn loadSound(filename: [*:0]const u8) u32 {
     const path = join(allocator, &.{ data_dir ++ "sounds", span(filename) })
         catch unreachable;
     defer allocator.free(path);
-    const audio = al.Audio.read(allocator, span(path)) catch unreachable;
+    const audio = al.Audio.read(allocator, path) catch unreachable;
     defer audio.free();
     const buffer = al.Buffer.init(audio) catch unreachable;
     return buffer.reference;
@@ -315,7 +315,7 @@ export fn loadSound(filename: [*:0]const u8) u32 {
 fn check(comptime errorString: fn (c_uint) callconv(.C) [*c]const u8,
          status: anytype) void {
     if (status != 0)
-        @panic(span(errorString(@intCast(c_uint, status))));
+        @panic(span(errorString(@intCast(status))));
 }
 
 /// Load PNG file into an OpenGL buffer and return it.
@@ -327,7 +327,7 @@ export fn loadTexture(filename: [*:0]const u8) u32 {
 
     var image = qoi.decodeBuffer(allocator, file) catch unreachable;
     defer image.deinit(allocator);
-    const data = @ptrCast([*c]const u8, image.pixels.ptr);
+    const data: [*c]const u8 = @ptrCast(image.pixels.ptr);
 
     var texture: u32 = undefined;
     c.glGenTextures(1, &texture);
@@ -337,8 +337,8 @@ export fn loadTexture(filename: [*:0]const u8) u32 {
     c.glTexParameteri(c.GL_TEXTURE_2D, c.GL_TEXTURE_MAG_FILTER, c.GL_LINEAR);
     c.glTexParameteri(c.GL_TEXTURE_2D, c.GL_TEXTURE_MIN_FILTER, c.GL_LINEAR);
 
-    const width = @intCast(i32, image.width);
-    const height = @intCast(i32, image.height);
+    const width: i32 = @intCast(image.width);
+    const height: i32 = @intCast(image.height);
     c.glPixelStorei(c.GL_UNPACK_ALIGNMENT, 1);
     c.glTexImage2D(c.GL_TEXTURE_2D, 0, 4, width, height,
                    0, c.GL_RGBA, c.GL_UNSIGNED_BYTE, data);
@@ -356,11 +356,6 @@ export fn playSound(source: u32, x: f32, y: f32, z: f32) void {
     src.play() catch unreachable;
 }
 
-// TODO: replace with @maximum from Zig 0.9+
-fn maximum(a: anytype, b: @TypeOf(a)) @TypeOf(a) {
-    return if (a > b) a else b;
-}
-
 /// Write scores to user data directory.
 pub fn saveScores(base_dir: []const u8, current: Scores) !void {
     const previous = try loadScores(base_dir);
@@ -370,7 +365,7 @@ pub fn saveScores(base_dir: []const u8, current: Scores) !void {
     defer dir.close();
     const format = "[scores]\nhigh score = {}\ncompleted = {}\n";
     const data = try allocPrint(allocator, format, .{
-        maximum(previous.high_score, current.high_score),
+        @max(previous.high_score, current.high_score),
         previous.completed or current.completed,
     });
     defer allocator.free(data);
@@ -385,12 +380,11 @@ const Text = struct {
 export fn buildFont(text: *Text) void {
     text.base = c.glGenLists(256);
     c.glBindTexture(c.GL_TEXTURE_2D, text.texture);
-    var i = @as(u16, 0);
-    while (i < 256) : (i += 1) {
+    for (0..256) |i| {
         // Character coords
-        const x = @intToFloat(f32, i % 16) / 16.0;
-        const y = @intToFloat(f32, i / 16) / 16.0;
-        c.glNewList(text.base + i, c.GL_COMPILE);
+        const x = @as(f32, @floatFromInt(i % 16)) / 16.0;
+        const y = @as(f32, @floatFromInt(i / 16)) / 16.0;
+        c.glNewList(@intCast(text.base + i), c.GL_COMPILE);
         // Use A Quad For Each Character
         c.glBegin(c.GL_QUADS);
         // Bottom left
@@ -437,7 +431,7 @@ export fn glPrint(text: *const Text, x: f64, y: f64, str: [*:0]const u8,
     else
         c.glListBase(text.base -% 32);
     // Write to screen
-    c.glCallLists(@intCast(c_int, len(str)), c.GL_BYTE, str);
+    c.glCallLists(@intCast(len(str)), c.GL_BYTE, str);
 
     // Restore
     c.glMatrixMode(c.GL_PROJECTION);