~ntgg/snake-zig

d0a97763b2addd4e4dbbd6e531341ab769939b10 — Noah Graff 5 months ago ebb4eb3 master
compatable with zig 0.5.0+51cbd9682 now
7 files changed, 34 insertions(+), 30 deletions(-)

M build.zig
M src/context.zig
M src/game_state.zig
M src/graphics.zig
M src/main.zig
M src/shaders.zig
M src/snake.zig
M build.zig => build.zig +1 -1
@@ 8,7 8,7 @@ pub fn build(b: *Builder) void {
    exe.setTheTarget(target);

    exe.addIncludeDir("stb_image");
    exe.addCSourceFile("stb_image/stb_image_impl.c", [_][]const u8{"-std=c99"});
    exe.addCSourceFile("stb_image/stb_image_impl.c", &[_][]const u8{"-std=c99"});
    exe.linkSystemLibrary("c");
    exe.linkSystemLibrary("glfw");
    exe.linkSystemLibrary("epoxy");

M src/context.zig => src/context.zig +4 -4
@@ 10,7 10,7 @@ const GfxContext = graphics.GfxContext;
const Key = @import("key.zig").Key;

extern fn errorCallback(err: c_int, description: [*c]const u8) void {
    panic("Error:\nNum: 0x{x:4}\nDescription: {}\n", err, description);
    panic("Error:\nNum: 0x{x:4}\nDescription: {}\n", .{err, description});
}

pub const Context = struct {


@@ 28,13 28,13 @@ pub const Context = struct {
    pub fn init(grid_width: usize, grid_height: usize, window_width: c_int, window_height: c_int) Context {
        _ = c.glfwSetErrorCallback(errorCallback);
        if (c.glfwInit() == c.GL_FALSE) {
            panic("GLFW init failure\n");
            panic("GLFW init failure\n", .{});
        }

        var ctx: Context = undefined;
        ctx.dt = 0.0;

        ctx.window = graphics.createWindow(c"Snake!", window_width, window_height);
        ctx.window = graphics.createWindow("Snake!", window_width, window_height);

        ctx.gfx = GfxContext.init(ctx.window);
        std.debug.assert(ctx.gfx.framebuffer_width >= window_width);


@@ 49,7 49,7 @@ pub const Context = struct {

        var seed_bytes: [@sizeOf(u64)]u8 = undefined;
        std.crypto.randomBytes(seed_bytes[0..]) catch |err| {
            panic("unable to seed rng!\nError:{}\n", err);
            panic("unable to seed rng!\nError:{}\n", .{err});
        };

        ctx.prng = std.rand.DefaultPrng.init(std.mem.readIntNative(u64, &seed_bytes));

M src/game_state.zig => src/game_state.zig +5 -5
@@ 93,7 93,7 @@ pub const PlayingState = struct {
            },
            alloc,
        ) catch {
            panic("Not enough memory for the snake!");
            panic("Not enough memory for the snake!", .{});
        };
        const apple_pos = GridPos{
            .x = ctx.prng.random.int(usize) % ctx.grid_width,


@@ 120,7 120,7 @@ pub const PlayingState = struct {
        };
    }

    pub fn update(self: *PlayingState, ctx: *Context) !?State {
    pub fn update(self: *PlayingState, ctx: *Context) anyerror!?State {
        self.until_tick -= ctx.dt;
        if (self.until_tick <= 0.0) {
            self.until_tick = self.tick_rate;


@@ 134,7 134,7 @@ pub const PlayingState = struct {
        try self.snake.move(ctx.grid_width, ctx.grid_height);
        for (self.snake.tail.toSlice()) |seg| {
            if (self.snake.head_pos.equal(seg.pos)) {
                return State{ .GameOver = GameOverState{ .score = self.snake.tail.count() } };
                return State{ .GameOver = GameOverState{ .score = self.snake.tail.len } };
            }
        }
        if (self.snake.head_pos.equal(self.apple_pos)) {


@@ 175,8 175,8 @@ pub const GameOverState = struct {
    score: usize,

    pub fn draw(state: *GameOverState, ctx: *Context) void {
        const out_string = std.fmt.allocPrint(c_allocator, "Your snake was {} segments long.", state.score) catch {
            panic("out of memory!");
        const out_string = std.fmt.allocPrint(c_allocator, "Your snake was {} segments long.", .{state.score}) catch {
            panic("out of memory!", .{});
        };
        graphics.drawCenteredText(&ctx.gfx, "Game Over!", -1, 6.0);
        graphics.drawCenteredText(&ctx.gfx, out_string, 0, 4.0);

M src/graphics.zig => src/graphics.zig +4 -4
@@ 22,7 22,7 @@ pub fn createWindow(title: [*]const u8, width: c_int, height: c_int) *c.GLFWwind
    c.glfwWindowHint(c.GLFW_RESIZABLE, c.GL_FALSE);

    return c.glfwCreateWindow(width, height, title, null, null) orelse {
        panic("unable to create a winow!\n");
        panic("unable to create a winow!\n", .{});
    };
}



@@ 53,11 53,11 @@ pub const GfxContext = struct {
        c.glPixelStorei(c.GL_UNPACK_ALIGNMENT, 1);

        const snake_sprites = Spritesheet.init(snake_png, snake_spritesheet_cell_size, snake_spritesheet_cell_size) catch {
            panic("Could not read snake spritesheet!\n");
            panic("Could not read snake spritesheet!\n", .{});
        };

        const text_sprites = Spritesheet.init(text_png, text_spritsheet_cell_width, text_spritsheet_cell_height) catch {
            panic("Could not read text spritesheet!\n");
            panic("Could not read text spritesheet!\n", .{});
        };

        const projection = Mat4.orthographic(


@@ 68,7 68,7 @@ pub const GfxContext = struct {
        );

        const all_shaders = AllShaders.init() catch {
            panic("Could not create shaders!\n");
            panic("Could not create shaders!\n", .{});
        };

        return GfxContext{

M src/main.zig => src/main.zig +1 -1
@@ 17,7 17,7 @@ var pressed_keys: ArrayList(Key) = ArrayList(Key).init(c_allocator);
extern fn keyCallback(window: ?*c.GLFWwindow, glfw_key: c_int, scancode: c_int, action: c_int, mods: c_int) void {
    if (action != c.GLFW_PRESS) return;
    if (Key.fromGLFW(glfw_key)) |key| {
        pressed_keys.append(key) catch panic("Ran out of memory!");
        pressed_keys.append(key) catch panic("Ran out of memory!", .{});
    }
}


M src/shaders.zig => src/shaders.zig +12 -12
@@ 21,7 21,7 @@ fn initGlShader(source: []const u8, name: [*]const u8, kind: c.GLenum) !c.GLuint

    const message = try c_allocator.alloc(u8, @intCast(usize, error_size));
    c.glGetShaderInfoLog(shader_id, error_size, &error_size, message.ptr);
    std.debug.panic("Could not compile {} shader:\n{}\n", name, message);
    std.debug.panic("Could not compile {} shader:\n{}\n", .{name, message});
}

pub const AllShaders = struct {


@@ 61,9 61,9 @@ pub const AllShaders = struct {
            \\    FragColor = Color;
            \\}
        );
        shaders.primitive_attrib_position = try shaders.primitive.attribLocation(c"VertexPosition");
        shaders.primitive_uniform_mvp = try shaders.primitive.uniformLocation(c"MVP");
        shaders.primitive_uniform_color = try shaders.primitive.uniformLocation(c"Color");
        shaders.primitive_attrib_position = try shaders.primitive.attribLocation("VertexPosition");
        shaders.primitive_uniform_mvp = try shaders.primitive.uniformLocation("MVP");
        shaders.primitive_uniform_color = try shaders.primitive.uniformLocation("Color");

        shaders.texture = try ShaderProgram.create(
            \\#version 450


@@ 91,10 91,10 @@ pub const AllShaders = struct {
            \\    FragColor = texture(Tex, FragTexCoord);
            \\}
        );
        shaders.texture_attrib_tex_coord = try shaders.texture.attribLocation(c"TexCoord");
        shaders.texture_attrib_position = try shaders.texture.attribLocation(c"VertexPosition");
        shaders.texture_uniform_mvp = try shaders.texture.uniformLocation(c"MVP");
        shaders.texture_uniform_tex = try shaders.texture.uniformLocation(c"Tex");
        shaders.texture_attrib_tex_coord = try shaders.texture.attribLocation("TexCoord");
        shaders.texture_attrib_position = try shaders.texture.attribLocation("VertexPosition");
        shaders.texture_uniform_mvp = try shaders.texture.uniformLocation("MVP");
        shaders.texture_uniform_tex = try shaders.texture.uniformLocation("Tex");

        return shaders;
    }


@@ 117,8 117,8 @@ pub const ShaderProgram = struct {
        fragment_source: []const u8,
    ) !ShaderProgram {
        var program: Self = undefined;
        program.vertex_id = try initGlShader(vertex_source, c"vertex", c.GL_VERTEX_SHADER);
        program.fragment_id = try initGlShader(fragment_source, c"fragment", c.GL_FRAGMENT_SHADER);
        program.vertex_id = try initGlShader(vertex_source, "vertex", c.GL_VERTEX_SHADER);
        program.fragment_id = try initGlShader(fragment_source, "fragment", c.GL_FRAGMENT_SHADER);

        program.program_id = c.glCreateProgram();
        c.glAttachShader(program.program_id, program.vertex_id);


@@ 135,7 135,7 @@ pub const ShaderProgram = struct {
        c.glGetProgramiv(program.program_id, c.GL_INFO_LOG_LENGTH, &error_size);
        const message = try c_allocator.alloc(u8, @intCast(usize, error_size));
        c.glGetProgramInfoLog(program.program_id, error_size, &error_size, message.ptr);
        std.debug.panic("Error linking shader program: {}\n", message);
        std.debug.panic("Error linking shader program: {}\n", .{message});
    }

    pub fn destroy(self: *Self) void {


@@ 169,7 169,7 @@ pub const ShaderProgram = struct {
    }

    pub fn setUniform(self: Self, uniform_id: c.GLint, value: var) void {
        const T = @typeOf(value);
        const T = @TypeOf(value);
        switch (T) {
            c_int => c.glUniform1i(uniform_id, value),
            f32 => c.glUniform1f(uniform_id, value),

M src/snake.zig => src/snake.zig +7 -3
@@ 35,7 35,7 @@ const Segment = struct {
                } else if (self.forward_dir == .Left and dir == .Up or self.forward_dir == .Up and dir == .Left) {
                    return .CornerLU;
                } else {
                    std.debug.panic("not a vaild corner: {}, {}", self.forward_dir, dir);
                    std.debug.panic("not a vaild corner: {}, {}", .{ self.forward_dir, dir });
                }
            }
        } else {


@@ 94,13 94,17 @@ pub const Snake = struct {
        }

        if (self.add_segment) {
            try self.tail.append(Segment{ .pos = self.head_pos, .forward_dir = self.head_dir, .back_dir = self.tail.at(self.tail.count() - 1).forward_dir.init_opposite() });
            try self.tail.append(Segment{
                .pos = self.head_pos,
                .forward_dir = self.head_dir,
                .back_dir = self.tail.at(self.tail.len - 1).forward_dir.init_opposite(),
            });
            self.head_pos.wrapping_move(self.head_dir, grid_width, grid_height);
            self.add_segment = false;
        } else {
            for (self.tail.toSlice()) |*seg| seg.move(grid_width, grid_height);
            for (self.tail.toSlice()) |*seg, i| {
                if (i + 1 < self.tail.count()) {
                if (i + 1 < self.tail.len) {
                    const next_seg = self.tail.at(i + 1);
                    seg.forward_dir = next_seg.forward_dir;
                } else {