187 lines
5.7 KiB
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;
|
|
}
|