usg/src/Game/Piece.zig

187 lines
5.7 KiB
Zig

const SDL = @import("sdl2");
const std = @import("std");
const Grid = @import("Grid.zig");
const Timer = @import("../Timer.zig");
const color = @import("../color.zig");
const Self = @This();
pub const Rot = enum {
right,
left,
};
pub const RotStage = enum(i8) {
init,
right,
flip,
left,
};
pub const Type = enum {
o,
i,
l,
j,
s,
z,
t,
};
const ncols = 4;
const nrows = 4;
// Positions relative to a grid
row: i32,
col: i32,
// 4x4 grid indicating piece form
structure: [4][4]bool,
// Rotation Stage
rot_stage: RotStage = RotStage.init,
// Timer to drop the piece
timer_dropped: Timer,
// Should this be dropped and become part of the grid (flag)
dropped: bool = false,
// Has the piece been swapped?
swapped: bool = false,
piece_type: Type,
color: SDL.Color,
pub fn init(piece_type: Type) Self {
return Self{
.row = Grid.buffer - 3,
.col = (Grid.ncolumns / 2) - (ncols / 2),
.piece_type = piece_type,
.timer_dropped = Timer.init(500),
.structure = switch (piece_type) {
Type.o => .{
.{ false, true, true, false },
.{ false, true, true, false },
.{ false, false, false, false },
.{ false, false, false, false },
},
Type.i => .{
.{ false, false, false, false },
.{ true, true, true, true },
.{ false, false, false, false },
.{ false, false, false, false },
},
Type.l => .{
.{ false, false, true, false },
.{ true, true, true, false },
.{ false, false, false, false },
.{ false, false, false, false },
},
Type.j => .{
.{ true, false, false, false },
.{ true, true, true, false },
.{ false, false, false, false },
.{ false, false, false, false },
},
Type.s => .{
.{ false, true, true, false },
.{ true, true, false, false },
.{ false, false, false, false },
.{ false, false, false, false },
},
Type.z => .{
.{ true, true, false, false },
.{ false, true, true, false },
.{ false, false, false, false },
.{ false, false, false, false },
},
Type.t => .{
.{ false, true, false, false },
.{ true, true, true, false },
.{ false, false, false, false },
.{ false, false, false, false },
},
},
.color = switch (piece_type) {
Type.o => color.yellow,
Type.i => color.cyan,
Type.l => color.orange,
Type.j => color.blue,
Type.s => color.green,
Type.z => color.red,
Type.t => color.purple,
},
};
}
pub fn rotate(self: Self, dir: Rot) Self {
if (self.piece_type == Type.o) {
return self;
}
var new_piece = self;
// The "sequences" indicate square coords and are always the same when rotating, so we make all squares follow said rotation
// [Inner/Outer][The sequence (0 -> 1 -> 2 -> 3 -> 0...)][Rows, Cols]
if (self.piece_type == Type.i) {
const sequences = .{ .{ .{ 1, 0 }, .{ 0, 2 }, .{ 2, 3 }, .{ 3, 1 } }, .{ .{ 2, 0 }, .{ 0, 1 }, .{ 1, 3 }, .{ 3, 2 } }, .{ .{ 1, 1 }, .{ 1, 2 }, .{ 2, 2 }, .{ 2, 1 } } };
if (dir == Rot.right) {
// Cicle through rotation stage
new_piece.rot_stage = @intToEnum(RotStage, @mod((@enumToInt(new_piece.rot_stage) + 1), 4));
// Rotate structure CW
inline for (sequences) |seq| {
inline for (seq, 0..) |_, i| {
const refi = @mod((@intCast(i32, i) - 1), 4);
new_piece.structure[seq[i][0]][seq[i][1]] = self.structure[seq[refi][0]][seq[refi][1]];
}
}
} else {
// Cicle through rotation stage
new_piece.rot_stage = @intToEnum(RotStage, @mod((@enumToInt(new_piece.rot_stage) - 1), 4));
// Rotate structure CCW
inline for (sequences) |seq| {
inline for (seq, 0..) |_, i| {
const refi = @mod((@intCast(i32, i) + 1), 4);
new_piece.structure[seq[i][0]][seq[i][1]] = self.structure[seq[refi][0]][seq[refi][1]];
}
}
}
} else {
const sequences = .{ .{ .{ 0, 0 }, .{ 0, 2 }, .{ 2, 2 }, .{ 2, 0 } }, .{ .{ 0, 1 }, .{ 1, 2 }, .{ 2, 1 }, .{ 1, 0 } } };
if (dir == Rot.right) {
// Cicle through rotation stage
new_piece.rot_stage = @intToEnum(RotStage, @mod((@enumToInt(new_piece.rot_stage) + 1), 4));
// Rotate structure CW
inline for (sequences) |seq| {
inline for (seq, 0..) |_, i| {
const refi = @mod((@intCast(i32, i) - 1), 4);
new_piece.structure[seq[i][0]][seq[i][1]] = self.structure[seq[refi][0]][seq[refi][1]];
}
}
} else {
// Cicle through rotation stage
new_piece.rot_stage = @intToEnum(RotStage, @mod((@enumToInt(new_piece.rot_stage) - 1), 4));
// Rotate structure CCW
inline for (sequences) |seq| {
inline for (seq, 0..) |_, i| {
const refi = @mod((@intCast(i32, i) + 1), 4);
new_piece.structure[seq[i][0]][seq[i][1]] = self.structure[seq[refi][0]][seq[refi][1]];
}
}
}
}
//[0,0][0,1][0,2]
//[1,0][1,1][1,2]
//[2,0][2,1][2,2]
return new_piece;
}