render draw/discard/hand

dev
LeRoyce Pearson 2024-02-25 00:19:34 -07:00
parent 695c4d6280
commit 45bc09b612
1 changed files with 107 additions and 21 deletions

View File

@ -15,6 +15,79 @@ const Card = packed struct(u6) {
rank: u4, rank: u4,
}; };
const GameState = struct {
allocator: std.mem.Allocator,
prng: std.rand.DefaultPrng,
draw_pile: std.ArrayListUnmanaged(Card),
discard_pile: std.ArrayListUnmanaged(Card),
hands: []std.ArrayListUnmanaged(Card),
pub fn init(allocator: std.mem.Allocator, seed: u64, num_players: usize) !@This() {
var draw_pile = std.ArrayListUnmanaged(Card).fromOwnedSlice(try makeStandardDeck(allocator));
errdefer draw_pile.deinit(allocator);
var prng = std.rand.DefaultPrng.init(seed);
prng.random().shuffle(Card, draw_pile.items);
const cards_per_player: usize = switch (num_players) {
1, 2 => 7,
3, 4 => 6,
else => unreachable,
};
const hands = try allocator.alloc(std.ArrayListUnmanaged(Card), num_players);
errdefer allocator.free(hands);
for (hands) |*hand| {
hand.* = try std.ArrayListUnmanaged(Card).initCapacity(allocator, cards_per_player);
for (0..cards_per_player) |_| {
hand.appendAssumeCapacity(draw_pile.pop());
}
}
var discard_pile = try std.ArrayListUnmanaged(Card).initCapacity(allocator, 52);
errdefer discard_pile.deinit(allocator);
// start game with one card in the discard pile
discard_pile.appendAssumeCapacity(draw_pile.pop());
return @This(){
.allocator = allocator,
.prng = prng,
.draw_pile = draw_pile,
.discard_pile = discard_pile,
.hands = hands,
};
}
pub fn deinit(this: *@This()) void {
this.draw_pile.deinit(this.allocator);
this.discard_pile.deinit(this.allocator);
for (this.hands) |*hand| {
hand.deinit(this.allocator);
}
this.allocator.free(this.hands);
}
};
pub fn makeStandardDeck(allocator: std.mem.Allocator) ![]Card {
var deck = try allocator.alloc(Card, 52);
errdefer allocator.free(deck);
var next_index: usize = 0;
for (0..4) |suit| {
for (1..14) |rank| {
deck[next_index] = Card{
.suit = @enumFromInt(suit),
.rank = @intCast(rank),
};
next_index += 1;
}
}
return deck;
}
/// A texture with a regular grid of sprites /// A texture with a regular grid of sprites
const TileSheet = struct { const TileSheet = struct {
texture: seizer.Texture, texture: seizer.Texture,
@ -167,6 +240,10 @@ pub fn main() !void {
var canvas = try seizer.Canvas.init(gpa.allocator(), .{}); var canvas = try seizer.Canvas.init(gpa.allocator(), .{});
defer canvas.deinit(gpa.allocator()); defer canvas.deinit(gpa.allocator());
// game state
var game_state = try GameState.init(gpa.allocator(), std.crypto.random.int(u64), 1);
defer game_state.deinit();
while (seizer.backend.glfw.c.glfwWindowShouldClose(window) != seizer.backend.glfw.c.GLFW_TRUE) { while (seizer.backend.glfw.c.glfwWindowShouldClose(window) != seizer.backend.glfw.c.GLFW_TRUE) {
seizer.backend.glfw.c.glfwPollEvents(); seizer.backend.glfw.c.glfwPollEvents();
@ -209,31 +286,40 @@ pub fn main() !void {
1001...std.math.maxInt(c_int) => card_tilemap_large.?, 1001...std.math.maxInt(c_int) => card_tilemap_large.?,
else => unreachable, else => unreachable,
}; };
for (0..4) |suit| {
for (1..14) |rank| {
const card = Card{ .suit = @enumFromInt(suit), .rank = @intCast(rank) };
const tile_index = deck_sprites.getTileForCard(card);
deck_sprites.tilesheet.renderTile(&canvas, @intCast(tile_index), .{
@floatFromInt(rank * deck_sprites.tilesheet.tile_size[0]),
@floatFromInt(suit * deck_sprites.tilesheet.tile_size[1]),
}, .{});
}
}
deck_sprites.tilesheet.renderTile(&canvas, deck_sprites.blank, .{ const draw_pile_pos = [2]f32{
@floatFromInt(1 * deck_sprites.tilesheet.tile_size[0]), canvas.window_size[0] / 2 - @as(f32, @floatFromInt(deck_sprites.tilesheet.tile_size[0])),
@floatFromInt(5 * deck_sprites.tilesheet.tile_size[1]), canvas.window_size[1] / 2,
}, .{}); };
deck_sprites.tilesheet.renderTile(&canvas, deck_sprites.back, .{ const discard_pile_pos = [2]f32{
@floatFromInt(2 * deck_sprites.tilesheet.tile_size[0]), canvas.window_size[0] / 2 + @as(f32, @floatFromInt(deck_sprites.tilesheet.tile_size[0])),
@floatFromInt(5 * deck_sprites.tilesheet.tile_size[1]), canvas.window_size[1] / 2,
}, .{}); };
const hand_pos = [2]f32{
(canvas.window_size[0] - @as(f32, @floatFromInt(game_state.hands[0].items.len * deck_sprites.tilesheet.tile_size[0]))) / 2,
canvas.window_size[1] - @as(f32, @floatFromInt(deck_sprites.tilesheet.tile_size[1])),
};
for (0..52) |i| { for (game_state.draw_pile.items, 0..) |_, i| {
const oy = -@as(f32, @floatFromInt(i)) * (@as(f32, @floatFromInt(deck_sprites.tilesheet.tile_size[1])) / (52.0 * 4)); const oy = -@as(f32, @floatFromInt(i)) * (@as(f32, @floatFromInt(deck_sprites.tilesheet.tile_size[1])) / (52.0 * 4));
deck_sprites.tilesheet.renderTile(&canvas, deck_sprites.back, .{ deck_sprites.tilesheet.renderTile(&canvas, deck_sprites.back, .{
@floatFromInt(4 * deck_sprites.tilesheet.tile_size[0]), draw_pile_pos[0],
@as(f32, @floatFromInt(5 * deck_sprites.tilesheet.tile_size[1])) + oy, draw_pile_pos[1] + oy,
}, .{});
}
for (game_state.discard_pile.items, 0..) |card, i| {
const oy = -@as(f32, @floatFromInt(i)) * (@as(f32, @floatFromInt(deck_sprites.tilesheet.tile_size[1])) / (52.0 * 4));
deck_sprites.tilesheet.renderTile(&canvas, deck_sprites.getTileForCard(card), .{
discard_pile_pos[0],
discard_pile_pos[1] + oy,
}, .{});
}
for (game_state.hands[0].items, 0..) |card, i| {
deck_sprites.tilesheet.renderTile(&canvas, deck_sprites.getTileForCard(card), .{
hand_pos[0] + @as(f32, @floatFromInt(i)) * @as(f32, @floatFromInt(deck_sprites.tilesheet.tile_size[0])),
hand_pos[1],
}, .{}); }, .{});
} }