@@ 15,6 15,7 @@ type texture = struct {
type gamestate = enum {
SPAWN,
FALL,
+ CLEAR,
};
type state = struct {
@@ 23,6 24,7 @@ type state = struct {
render: *sdl2::renderer,
piece: texture,
scene: texture,
+ clear: texture,
input: input,
board: board,
@@ 32,6 34,7 @@ type state = struct {
speed: u32,
faster: bool,
lastcolor: color,
+ clearframe: int,
};
export fn main() void = {
@@ 63,16 66,14 @@ fn run() (void | sdl2::error) = {
render = render,
piece = load_texture(render, "assets/piece.png")?,
scene = load_texture(render, "assets/concert.png")?,
+ clear = load_texture(render, "assets/clear.png")?,
board = board {
offs_x = 88,
offs_y = 74,
...
},
rand = random::init(seed),
- state = gamestate::SPAWN,
speed = 250,
- next = sdl2::get_ticks() + 250,
- lastcolor = color::EMPTY,
...
};
defer sdl2::destroy_texture(state.piece.tex);
@@ 96,7 97,7 @@ fn run() (void | sdl2::error) = {
sdl2::game_controller_close(c);
};
- do_spawn(&state);
+ do_spawn(&state, sdl2::get_ticks());
for (state.run) {
update(&state)?;
@@ 114,10 115,33 @@ fn draw(state: *state) (void | sdl2::error) = {
w = 640,
h = 480,
})?;
+
draw_board(state, &state.board)?;
+
+ switch (state.state) {
+ case gamestate::CLEAR =>
+ draw_clear(state);
+ case => void; // No special drawing required
+ };
+
sdl2::render_present(state.render);
};
+fn draw_clear(state: *state) void = {
+ // TODO: Expand me
+ sdl2::render_copy(state.render, state.clear.tex, &sdl2::rect{
+ x = state.clearframe * 4,
+ y = 0,
+ w = 4,
+ h = 4,
+ }, &sdl2::rect{
+ x = 0,
+ y = 0,
+ w = 8,
+ h = 8,
+ })?;
+};
+
fn load_texture(render: *sdl2::renderer, path: str) (texture | sdl2::error) = {
const tex = image::load_texture(render, path)?;
let width = 0, height = 0;
@@ 59,19 59,16 @@ fn update(state: *state) (void | sdl2::error) = {
if (state.next <= now) {
switch (state.state) {
case gamestate::SPAWN =>
- do_spawn(state);
+ do_spawn(state, now);
case gamestate::FALL =>
- do_fall(state);
- };
- if (state.faster) {
- state.next = now + 100;
- } else {
- state.next = now + state.speed;
+ do_fall(state, now);
+ case gamestate::CLEAR =>
+ do_clear(state, now);
};
};
};
-fn do_spawn(state: *state) void = {
+fn do_spawn(state: *state, now: u32) void = {
let next = random::next(&state.rand): size % len(tetrominoes);
let col = color::EMPTY;
for (true) {
@@ 100,9 97,10 @@ fn do_spawn(state: *state) void = {
state.board.active_y = -height;
state.board.active_x = BOARD_WIDTH / 2 - width / 2;
state.state = gamestate::FALL;
+ schedule_tick(state, now);
};
-fn do_fall(state: *state) void = {
+fn do_fall(state: *state, now: u32) void = {
let height = 0;
activesize(state, null, &height);
const active = &state.board.active[state.board.active_i];
@@ 110,7 108,21 @@ fn do_fall(state: *state) void = {
state.board.active_y += 1;
} else {
commit(state);
- state.state = gamestate::SPAWN;
+ };
+ schedule_tick(state, now);
+};
+
+fn do_clear(state: *state, now: u32) void = {
+ state.clearframe += 1;
+ state.clearframe %= 12;
+ state.next = now + (state.speed / 6);
+};
+
+fn schedule_tick(state: *state, now: u32) void = {
+ if (state.faster) {
+ state.next = now + 100;
+ } else {
+ state.next = now + state.speed;
};
};
@@ 130,6 142,22 @@ fn commit(state: *state) void = {
board[board_ix] = active[active_ix];
};
};
+
+ static let clearbuf: [TETROMINO_HEIGHT]int = [0...];
+ let clear = clearbuf[..0];
+ state.state = gamestate::SPAWN;
+ for (let y = active_y; y < BOARD_HEIGHT; y += 1)
+ for (let x = 0, sum = 0; x < BOARD_WIDTH; x += 1) {
+ const board_ix = y * BOARD_WIDTH + x;
+ const cell = state.board.cells[board_ix];
+ if (cell != 0) {
+ sum += 1;
+ };
+ if (sum == BOARD_WIDTH) {
+ state.state = gamestate::CLEAR;
+ static append(clear, y);
+ };
+ };
};
fn move_left(state: *state) void = {