get medium cards rendering

dev
LeRoyce Pearson 2024-02-23 14:44:27 -07:00
commit 15e1670ec3
7 changed files with 275 additions and 0 deletions

2
.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
zig-out/
zig-cache/

55
build.zig Normal file
View File

@ -0,0 +1,55 @@
const std = @import("std");
// Although this function looks imperative, note that its job is to
// declaratively construct a build graph that will be executed by an external
// runner.
pub fn build(b: *std.Build) void {
// Standard target options allows the person running `zig build` to choose
// what target to build for. Here we do not override the defaults, which
// means any target is allowed, and the default is native. Other options
// for restricting supported target set are available.
const target = b.standardTargetOptions(.{});
// Standard optimization options allow the person running `zig build` to select
// between Debug, ReleaseSafe, ReleaseFast, and ReleaseSmall. Here we do not
// set a preferred release mode, allowing the user to decide how to optimize.
const optimize = b.standardOptimizeOption(.{});
const seizer = b.dependency("seizer", .{
.target = target,
.optimize = optimize,
});
const exe = b.addExecutable(.{
.name = "seizer-rummy",
.root_source_file = .{ .path = "src/main.zig" },
.target = target,
.optimize = optimize,
});
exe.root_module.addImport("seizer", seizer.module("seizer"));
b.installArtifact(exe);
const run_cmd = b.addRunArtifact(exe);
run_cmd.step.dependOn(b.getInstallStep());
if (b.args) |args| {
run_cmd.addArgs(args);
}
const run_step = b.step("run", "Run the app");
run_step.dependOn(&run_cmd.step);
const exe_unit_tests = b.addTest(.{
.root_source_file = .{ .path = "src/main.zig" },
.target = target,
.optimize = optimize,
});
const run_exe_unit_tests = b.addRunArtifact(exe_unit_tests);
// Similar to creating the run step earlier, this exposes a `test` step to
// the `zig build --help` menu, providing a way for the user to request
// running the unit tests.
const test_step = b.step("test", "Run unit tests");
test_step.dependOn(&run_exe_unit_tests.step);
}

36
build.zig.zon Normal file
View File

@ -0,0 +1,36 @@
.{
.name = "seizer-rummy",
// This is a [Semantic Version](https://semver.org/).
// In a future version of Zig it will be used for package deduplication.
.version = "0.0.0",
// This field is optional.
// This is currently advisory only; Zig does not yet do anything
// with this value.
//.minimum_zig_version = "0.11.0",
// This field is optional.
// Each dependency must either provide a `url` and `hash`, or a `path`.
// `zig build --fetch` can be used to fetch all dependencies of a package, recursively.
// Once all dependencies are fetched, `zig build` no longer requires
// internet connectivity.
.dependencies = .{
.seizer = .{
.url = "https://github.com/leroycep/seizer/archive/dd1f9f6c94e91edfd96f0075c5f5d33aa30758f4.tar.gz",
.hash = "122009caed9e40d713c847b24c2abf8540299e32fb5e77f73ab2acdf5c27bc3e4c90",
},
},
.paths = .{
// This makes *all* files, recursively, included in this package. It is generally
// better to explicitly list the files and directories instead, to insure that
// fetching from tarballs, file system paths, and version control all result
// in the same contents hash.
"",
// For example...
//"build.zig",
//"build.zig.zon",
//"src",
//"LICENSE",
//"README.md",
},
}

BIN
src/cardsLarge_tilemap.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

BIN
src/cardsMedium_tilemap.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

BIN
src/cardsSmall_tilemap.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

182
src/main.zig Normal file
View File

@ -0,0 +1,182 @@
var gl_binding: gl.Binding = undefined;
const Suit = enum(u2) {
clubs = 0b00,
spades = 0b01,
hearts = 0b10,
diamonds = 0b11,
pub fn color(this: @This()) u1 {
return (@intFromEnum(this) & 0b10) >> 1;
}
};
const Card = packed struct(u6) {
suit: Suit,
rank: u4,
};
/// A texture with a regular grid of sprites
const TileSheet = struct {
texture: seizer.Texture,
tile_size: [2]u32,
pub const InitOptions = struct {
allocator: std.mem.Allocator,
image_file_contents: []const u8,
tile_size: [2]u32,
texture_options: seizer.Texture.InitFromFileOptions = .{},
};
pub fn init(options: InitOptions) !@This() {
const texture = try seizer.Texture.initFromFileContents(
options.allocator,
options.image_file_contents,
options.texture_options,
);
return @This(){
.texture = texture,
.tile_size = options.tile_size,
};
}
pub fn deinit(this: *@This()) void {
this.texture.deinit();
}
pub fn renderTile(this: @This(), canvas: *seizer.Canvas, tile_id: u32, pos: [2]f32, options: struct {
size: ?[2]f32 = null,
}) void {
const texture_sizef = [2]f32{
@floatFromInt(this.texture.size[0]),
@floatFromInt(this.texture.size[1]),
};
const tile_sizef = [2]f32{
@floatFromInt(this.tile_size[0]),
@floatFromInt(this.tile_size[1]),
};
const size_in_tiles = [2]u32{
@as(u32, @intCast(this.texture.size[0])) / this.tile_size[0],
@as(u32, @intCast(this.texture.size[1])) / this.tile_size[1],
};
const pos_in_tiles = [2]u32{
tile_id % size_in_tiles[0],
tile_id / size_in_tiles[0],
};
const pos_in_tilesf = [2]f32{
@floatFromInt(pos_in_tiles[0]),
@floatFromInt(pos_in_tiles[1]),
};
const uv = seizer.geometry.AABB(f32){
.min = .{
(pos_in_tilesf[0] * tile_sizef[0]) / texture_sizef[0],
(pos_in_tilesf[1] * tile_sizef[1]) / texture_sizef[1],
},
.max = .{
((pos_in_tilesf[0] + 1) * tile_sizef[0]) / texture_sizef[0],
((pos_in_tilesf[1] + 1) * tile_sizef[1]) / texture_sizef[1],
},
};
_ = canvas.printText(.{ 0, 0 }, "uv = {}", .{uv}, .{});
canvas.rect(pos, options.size orelse tile_sizef, .{
.texture = this.texture.glTexture,
.uv = uv,
});
}
};
// const cards_medium_spritesheet =
pub fn main() !void {
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
defer _ = gpa.deinit();
// GLFW setup
try seizer.backend.glfw.loadDynamicLibraries(gpa.allocator());
_ = seizer.backend.glfw.c.glfwSetErrorCallback(&seizer.backend.glfw.defaultErrorCallback);
const glfw_init_res = seizer.backend.glfw.c.glfwInit();
if (glfw_init_res != 1) {
std.debug.print("glfw init error: {}\n", .{glfw_init_res});
std.process.exit(1);
}
defer seizer.backend.glfw.c.glfwTerminate();
seizer.backend.glfw.c.glfwWindowHint(seizer.backend.glfw.c.GLFW_OPENGL_DEBUG_CONTEXT, seizer.backend.glfw.c.GLFW_TRUE);
seizer.backend.glfw.c.glfwWindowHint(seizer.backend.glfw.c.GLFW_CLIENT_API, seizer.backend.glfw.c.GLFW_OPENGL_ES_API);
seizer.backend.glfw.c.glfwWindowHint(seizer.backend.glfw.c.GLFW_CONTEXT_VERSION_MAJOR, 3);
seizer.backend.glfw.c.glfwWindowHint(seizer.backend.glfw.c.GLFW_CONTEXT_VERSION_MINOR, 0);
// Open window
const window = seizer.backend.glfw.c.glfwCreateWindow(720, 720, "Rummy", null, null) orelse return error.GlfwCreateWindow;
errdefer seizer.backend.glfw.c.glfwDestroyWindow(window);
seizer.backend.glfw.c.glfwMakeContextCurrent(window);
gl_binding.init(seizer.backend.glfw.GlBindingLoader);
gl.makeBindingCurrent(&gl_binding);
// Set up input callbacks
_ = seizer.backend.glfw.c.glfwSetFramebufferSizeCallback(window, &glfw_framebuffer_size_callback);
var card_tilemap = try TileSheet.init(.{
.allocator = gpa.allocator(),
.image_file_contents = @embedFile("./cardsMedium_tilemap.png"),
.tile_size = .{ 32, 32 },
.texture_options = .{
.min_filter = .nearest,
.mag_filter = .nearest,
},
});
defer card_tilemap.deinit();
var canvas = try seizer.Canvas.init(gpa.allocator(), .{});
defer canvas.deinit(gpa.allocator());
while (seizer.backend.glfw.c.glfwWindowShouldClose(window) != seizer.backend.glfw.c.GLFW_TRUE) {
seizer.backend.glfw.c.glfwPollEvents();
gl.clearColor(0.7, 0.5, 0.5, 1.0);
gl.clear(gl.COLOR_BUFFER_BIT);
var window_size: [2]c_int = undefined;
seizer.backend.glfw.c.glfwGetWindowSize(window, &window_size[0], &window_size[1]);
var framebuffer_size: [2]c_int = undefined;
seizer.backend.glfw.c.glfwGetFramebufferSize(window, &framebuffer_size[0], &framebuffer_size[1]);
canvas.begin(.{
.window_size = [2]f32{
@floatFromInt(window_size[0]),
@floatFromInt(window_size[1]),
},
.framebuffer_size = [2]f32{
@floatFromInt(framebuffer_size[0]),
@floatFromInt(framebuffer_size[1]),
},
});
card_tilemap.renderTile(&canvas, 1, .{ 10, 10 }, .{});
// canvas.rect(.{ 10, 10 }, .{ @as(f32, @floatFromInt(card_tilemap.size[0])) / 15.0, @as(f32, @floatFromInt(card_tilemap.size[1])) / 10.0 }, .{
// .texture = card_tilemap.glTexture,
// .uv = .{ .min = .{ 0, 0 }, .max = .{ 1.0 / 15.0, 1.0 / 10.0 } },
// });
_ = canvas.writeText(.{ 50, 50 }, "Hello, world!", .{});
_ = canvas.printText(.{ 50, 100 }, "window_size = {}, {}\nframebuffer_size = {}, {}", .{ window_size[0], window_size[1], framebuffer_size[0], framebuffer_size[1] }, .{});
canvas.end();
seizer.backend.glfw.c.glfwSwapBuffers(window);
}
}
fn glfw_framebuffer_size_callback(window: ?*seizer.backend.glfw.c.GLFWwindow, width: c_int, height: c_int) callconv(.C) void {
_ = window;
gl.viewport(
0,
0,
@intCast(width),
@intCast(height),
);
}
const seizer = @import("seizer");
const gl = seizer.gl;
const std = @import("std");