2022-06-28 12:42:28 +00:00
|
|
|
const std = @import("std");
|
|
|
|
const SDL = @import("sdl2");
|
|
|
|
|
2022-07-12 14:20:15 +00:00
|
|
|
const Grid = @import("Grid.zig");
|
|
|
|
const Piece = @import("Piece.zig");
|
|
|
|
const Bag = @import("Bag.zig");
|
|
|
|
const Timer = @import("Timer.zig");
|
2022-07-13 20:59:54 +00:00
|
|
|
const State = @import("flow.zig").State;
|
2022-07-20 17:31:18 +00:00
|
|
|
const Action = @import("Action.zig");
|
2022-06-28 12:42:28 +00:00
|
|
|
|
2022-07-05 18:26:57 +00:00
|
|
|
const renderer = @import("renderer.zig");
|
2022-06-28 12:42:28 +00:00
|
|
|
const movement = @import("movement.zig");
|
|
|
|
|
|
|
|
const Self = @This();
|
|
|
|
|
2022-07-20 17:31:18 +00:00
|
|
|
// Codes to access action list
|
|
|
|
pub const ActionCode = enum(usize) {
|
|
|
|
right = 0,
|
|
|
|
left = 1,
|
|
|
|
down = 2,
|
|
|
|
hard = 3,
|
|
|
|
swap = 4,
|
|
|
|
rot_r = 5,
|
|
|
|
rot_l = 6,
|
2022-07-10 16:25:52 +00:00
|
|
|
};
|
|
|
|
|
2022-06-28 12:42:28 +00:00
|
|
|
grid: Grid,
|
|
|
|
grid_cell_size: i32,
|
|
|
|
grid_pos_x: i32,
|
|
|
|
grid_pos_y: i32,
|
|
|
|
|
2022-07-13 20:59:54 +00:00
|
|
|
state: State = State.game,
|
|
|
|
|
2022-06-30 15:38:20 +00:00
|
|
|
bag: Bag,
|
|
|
|
|
2022-07-05 18:26:57 +00:00
|
|
|
held: ?Piece.Type,
|
|
|
|
piece: Piece,
|
|
|
|
shadow: Piece,
|
|
|
|
|
2022-06-28 12:42:28 +00:00
|
|
|
renderer: *SDL.SDL_Renderer,
|
|
|
|
|
2022-07-10 16:25:52 +00:00
|
|
|
action_list: [7]Action = .{
|
2022-07-20 17:31:18 +00:00
|
|
|
Action.init(SDL.SDL_SCANCODE_D, actionRight), // Right
|
|
|
|
Action.init(SDL.SDL_SCANCODE_A, actionLeft), // Left
|
|
|
|
Action.init(SDL.SDL_SCANCODE_S, actionDown), // Down
|
|
|
|
Action.init(SDL.SDL_SCANCODE_W, actionHard), // Instant Drop
|
|
|
|
Action.init(SDL.SDL_SCANCODE_SPACE, actionSwap), // Swap Piece
|
|
|
|
Action.init(SDL.SDL_SCANCODE_RIGHT, actionRotR), // Rotate
|
|
|
|
Action.init(SDL.SDL_SCANCODE_LEFT, actionRotL), // Rotate
|
2022-07-10 16:25:52 +00:00
|
|
|
},
|
2022-06-28 12:42:28 +00:00
|
|
|
|
2022-07-10 16:25:52 +00:00
|
|
|
timer_down: Timer,
|
2022-07-14 13:22:40 +00:00
|
|
|
timer_left_arr: Timer,
|
|
|
|
timer_left_das: Timer,
|
|
|
|
timer_right_arr: Timer,
|
|
|
|
timer_right_das: Timer,
|
2022-07-07 14:49:15 +00:00
|
|
|
|
2022-07-10 16:25:52 +00:00
|
|
|
pub fn init(_renderer: *SDL.SDL_Renderer) Self {
|
2022-06-30 23:49:22 +00:00
|
|
|
var ret = Self{
|
2022-06-28 12:42:28 +00:00
|
|
|
.grid = Grid.init(),
|
2022-07-07 14:49:15 +00:00
|
|
|
.grid_cell_size = undefined,
|
|
|
|
.grid_pos_x = undefined,
|
|
|
|
.grid_pos_y = undefined,
|
2022-06-28 12:42:28 +00:00
|
|
|
|
2022-06-30 15:38:20 +00:00
|
|
|
.bag = Bag.init(),
|
|
|
|
.piece = undefined,
|
2022-07-05 18:26:57 +00:00
|
|
|
.shadow = undefined,
|
2022-06-28 12:42:28 +00:00
|
|
|
.held = null,
|
2022-07-05 18:26:57 +00:00
|
|
|
.renderer = _renderer,
|
2022-07-10 16:25:52 +00:00
|
|
|
|
2022-07-14 13:22:40 +00:00
|
|
|
.timer_down = Timer.init(50),
|
|
|
|
.timer_left_arr = Timer.init(50),
|
|
|
|
.timer_left_das = Timer.init(200),
|
|
|
|
.timer_right_arr = Timer.init(50),
|
|
|
|
.timer_right_das = Timer.init(200),
|
2022-06-28 12:42:28 +00:00
|
|
|
};
|
2022-07-07 14:49:15 +00:00
|
|
|
|
2022-07-10 16:25:52 +00:00
|
|
|
// Calculate positions
|
|
|
|
{
|
|
|
|
var aux_w: i32 = undefined;
|
|
|
|
var aux_h: i32 = undefined;
|
|
|
|
|
|
|
|
_ = SDL.SDL_GetRendererOutputSize(_renderer, &aux_w, &aux_h);
|
2022-07-07 14:49:15 +00:00
|
|
|
|
2022-07-10 16:25:52 +00:00
|
|
|
ret.grid_cell_size = @divFloor(@minimum(aux_w, aux_h), 32);
|
2022-07-07 14:49:15 +00:00
|
|
|
|
2022-07-10 16:25:52 +00:00
|
|
|
ret.grid_pos_x = @divFloor(aux_w, 2) - (ret.grid_cell_size * @divFloor(Grid.ncolumns, 2));
|
|
|
|
ret.grid_pos_y = @divFloor(aux_h, 2) - (ret.grid_cell_size * @divFloor(Grid.nrows + Grid.buffer, 2));
|
|
|
|
}
|
2022-07-07 14:49:15 +00:00
|
|
|
|
2022-07-14 13:22:40 +00:00
|
|
|
// Get a piece from the bag
|
|
|
|
ret.piece = ret.bag.pop();
|
|
|
|
|
2022-06-30 15:38:20 +00:00
|
|
|
return ret;
|
2022-06-28 12:42:28 +00:00
|
|
|
}
|
2022-07-13 20:59:54 +00:00
|
|
|
pub fn tick(self: *Self) State {
|
2022-06-28 16:42:40 +00:00
|
|
|
|
2022-07-10 16:25:52 +00:00
|
|
|
// TIMERS
|
2022-07-14 13:22:40 +00:00
|
|
|
// Dropping a piece
|
2022-07-10 17:44:48 +00:00
|
|
|
if (self.piece.timer_dropped.finished()) {
|
2022-07-12 14:20:15 +00:00
|
|
|
self.piece.timer_dropped.stop();
|
|
|
|
self.piece.dropped = true;
|
2022-07-10 17:44:48 +00:00
|
|
|
}
|
2022-07-14 13:22:40 +00:00
|
|
|
// Repeat Right
|
|
|
|
|
|
|
|
// DAS
|
2022-07-20 17:31:18 +00:00
|
|
|
if (self.action_list[@enumToInt(ActionCode.right)].holding) {
|
2022-07-14 13:22:40 +00:00
|
|
|
if (!self.timer_right_das.started) {
|
|
|
|
self.timer_right_das.start();
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// Stop both
|
|
|
|
self.timer_right_das.stop();
|
|
|
|
self.timer_right_arr.stop();
|
|
|
|
}
|
|
|
|
|
|
|
|
// ARR
|
|
|
|
if (self.timer_right_das.finished()) {
|
|
|
|
if (!self.timer_right_arr.started) {
|
|
|
|
self.timer_right_arr.start();
|
|
|
|
} else if (self.timer_right_arr.finished()) {
|
|
|
|
self.timer_right_arr.stop();
|
2022-07-20 17:31:18 +00:00
|
|
|
self.action_list[@enumToInt(ActionCode.right)].holding = false;
|
2022-07-14 13:22:40 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Repeat Left
|
|
|
|
|
|
|
|
// DAS
|
2022-07-20 17:31:18 +00:00
|
|
|
if (self.action_list[@enumToInt(ActionCode.left)].holding) {
|
2022-07-14 13:22:40 +00:00
|
|
|
if (!self.timer_left_das.started) {
|
|
|
|
self.timer_left_das.start();
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// Stop both
|
|
|
|
self.timer_left_das.stop();
|
|
|
|
self.timer_left_arr.stop();
|
|
|
|
}
|
|
|
|
|
|
|
|
// ARR
|
|
|
|
if (self.timer_left_das.finished()) {
|
|
|
|
if (!self.timer_left_arr.started) {
|
|
|
|
self.timer_left_arr.start();
|
|
|
|
} else if (self.timer_left_arr.finished()) {
|
|
|
|
self.timer_left_arr.stop();
|
2022-07-20 17:31:18 +00:00
|
|
|
self.action_list[@enumToInt(ActionCode.left)].holding = false;
|
2022-07-14 13:22:40 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Repeat Down
|
2022-07-20 17:31:18 +00:00
|
|
|
if (self.action_list[@enumToInt(ActionCode.down)].holding) {
|
2022-07-10 16:25:52 +00:00
|
|
|
if (!self.timer_down.started) {
|
|
|
|
self.timer_down.start();
|
|
|
|
} else if (self.timer_down.finished()) {
|
|
|
|
self.timer_down.stop();
|
2022-07-20 17:31:18 +00:00
|
|
|
self.action_list[@enumToInt(ActionCode.down)].holding = false;
|
2022-07-10 16:25:52 +00:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
self.timer_down.stop();
|
2022-07-05 18:26:57 +00:00
|
|
|
}
|
|
|
|
|
2022-07-10 17:44:48 +00:00
|
|
|
// DROP
|
|
|
|
|
|
|
|
if (self.piece.dropped) {
|
|
|
|
self.grid = movement.drop(self.grid, self.piece);
|
|
|
|
// New Piece
|
|
|
|
self.piece = self.bag.pop();
|
|
|
|
}
|
|
|
|
|
2022-07-10 16:25:52 +00:00
|
|
|
// KEY EVENTS
|
|
|
|
var key_state = SDL.SDL_GetKeyboardState(null);
|
2022-07-05 18:26:57 +00:00
|
|
|
|
2022-07-10 16:25:52 +00:00
|
|
|
for (self.action_list) |*action| {
|
|
|
|
if (key_state[action.*.code] == 1 and !action.*.holding) {
|
|
|
|
action.*.holding = true;
|
|
|
|
action.*.activate = true;
|
|
|
|
}
|
|
|
|
if (key_state[action.*.code] == 0) {
|
|
|
|
action.*.holding = false;
|
|
|
|
}
|
2022-07-05 18:26:57 +00:00
|
|
|
|
2022-07-10 16:25:52 +00:00
|
|
|
// Action
|
|
|
|
if (action.*.activate) {
|
|
|
|
action.*.activate = false;
|
2022-07-20 17:31:18 +00:00
|
|
|
action.*.call(self);
|
2022-07-10 16:25:52 +00:00
|
|
|
}
|
2022-07-05 21:09:59 +00:00
|
|
|
}
|
|
|
|
|
2022-07-05 18:26:57 +00:00
|
|
|
// Update Shadow
|
2022-07-10 16:25:52 +00:00
|
|
|
{
|
|
|
|
self.shadow = movement.shadow(self.grid, self.piece);
|
|
|
|
self.shadow.color.a /= 4;
|
|
|
|
}
|
2022-07-05 18:26:57 +00:00
|
|
|
|
2022-07-12 14:20:15 +00:00
|
|
|
self.grid.clearLines();
|
|
|
|
|
2022-07-05 18:26:57 +00:00
|
|
|
renderer.render(self.*);
|
2022-07-13 20:59:54 +00:00
|
|
|
|
|
|
|
return self.state;
|
2022-07-05 18:26:57 +00:00
|
|
|
}
|
2022-07-10 16:25:52 +00:00
|
|
|
|
|
|
|
// ACTION CALLBACKS
|
|
|
|
|
|
|
|
fn actionDown(self: *Self) void {
|
|
|
|
self.piece = movement.moveDown(self.grid, self.piece);
|
|
|
|
}
|
|
|
|
|
|
|
|
fn actionRight(self: *Self) void {
|
|
|
|
self.piece = movement.moveRight(self.grid, self.piece);
|
|
|
|
}
|
|
|
|
|
|
|
|
fn actionLeft(self: *Self) void {
|
|
|
|
self.piece = movement.moveLeft(self.grid, self.piece);
|
|
|
|
}
|
|
|
|
fn actionHard(self: *Self) void {
|
|
|
|
self.piece = movement.hardDrop(self.grid, self.piece);
|
|
|
|
}
|
|
|
|
fn actionSwap(self: *Self) void {
|
2022-07-05 18:26:57 +00:00
|
|
|
if (self.held) |held_piece| {
|
|
|
|
if (!self.piece.swapped) {
|
|
|
|
self.held = self.piece.piece_type;
|
|
|
|
self.piece = Piece.init(held_piece);
|
|
|
|
self.piece.swapped = true;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
self.held = self.piece.piece_type;
|
|
|
|
self.piece = self.bag.pop();
|
|
|
|
self.piece.swapped = true;
|
|
|
|
}
|
2022-06-28 12:42:28 +00:00
|
|
|
}
|
2022-07-10 16:25:52 +00:00
|
|
|
fn actionRotR(self: *Self) void {
|
|
|
|
self.piece = movement.rotateRight(self.grid, self.piece);
|
|
|
|
}
|
|
|
|
fn actionRotL(self: *Self) void {
|
|
|
|
self.piece = movement.rotateLeft(self.grid, self.piece);
|
|
|
|
}
|