summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Opalach <andrew@akon.city> 2019-10-23 19:53:39 -0400
committerAndrew Opalach <andrew@akon.city> 2019-10-23 19:53:39 -0400
commit6fa5bc504edfa4299b0b5d46d299cb5741654243 (patch)
treefbebaed7215f0d6b5069d97e4dd199538cf394d9
parentce7bc0b52aa8db24eb417786763be843efcd640b (diff)
downloadcetris-6fa5bc504edfa4299b0b5d46d299cb5741654243.tar.gz
cetris-6fa5bc504edfa4299b0b5d46d299cb5741654243.tar.bz2
cetris-6fa5bc504edfa4299b0b5d46d299cb5741654243.zip
optimize cpu usage
-rw-r--r--frontends/curses/curses_ui.c42
-rw-r--r--lib/cetris.h104
2 files changed, 71 insertions, 75 deletions
diff --git a/frontends/curses/curses_ui.c b/frontends/curses/curses_ui.c
index f3ebaa8..9b458dc 100644
--- a/frontends/curses/curses_ui.c
+++ b/frontends/curses/curses_ui.c
@@ -84,7 +84,7 @@ void curses_init() {
curs_set(0);
noecho();
keypad(stdscr, TRUE);
- nodelay(stdscr, true);
+ timeout(16);
#ifdef _WIN32 // only resize manually on windows
resize_term(WIN_LINE, WIN_COL);
@@ -122,15 +122,32 @@ void *game_loop(void) {
void draw_board() {
mvaddstr(0, 0, PLAY_FIELD_STR);
- for (int x = 0; x < CETRIS_BOARD_X; x++) {
- for (int y = CETRIS_BOARD_VISABLE; y < CETRIS_BOARD_Y; y++) {
- int draw_y = y - CETRIS_BOARD_VISABLE + Y_OFFSET;
- int draw_x = x * 2 + X_OFFSET;
- if (game.board[x][y] & SLOT_GHOST) {
- attron(A_DIM);
+
+ for (int y = 0; y < 4; y++) {
+ for (int x = 0; x < 4; x++) {
+ if ((game.current.m[y]>>(3 - x))&1) {
+ int draw_x = X_OFFSET + ((x + game.current.pos.x) * 2);
+ int draw_y = Y_OFFSET + (y + game.current.pos.y) - CETRIS_BOARD_VISABLE;
+ int ghost_y = Y_OFFSET + (y + game.current.ghost_y) - CETRIS_BOARD_VISABLE;
+ attron(COLOR_PAIR(game.current.t) | A_BOLD);
mvaddstr(draw_y, draw_x, BLOCK);
+
+ if ((default_matrices[game.piece_queue[game.current_index]][y]>>(3 - x))&1) {
+ mvaddstr(6 + y, (x * 2) + 36, BLOCK);
+ }
+
+ attroff(COLOR_PAIR(game.current.t) | A_BOLD);
+ attron(A_DIM);
+ mvaddstr(ghost_y, draw_x, BLOCK);
attroff(A_DIM);
}
+ }
+ }
+
+ for (int x = 0; x < CETRIS_BOARD_X; x++) {
+ for (int y = game.highest_line; y < CETRIS_BOARD_Y; y++) {
+ int draw_y = y - CETRIS_BOARD_VISABLE + Y_OFFSET;
+ int draw_x = x * 2 + X_OFFSET;
if (game.board[x][y] & SLOT_OCCUPIED) {
attron(COLOR_PAIR(game.board[x][y] >> 5) | A_BOLD);
if (game.line_remove_tick[y]) {
@@ -144,17 +161,6 @@ void draw_board() {
}
}
- int index = game.current_index;
- attron(COLOR_PAIR(game.piece_queue[index]));
- for (int x = 0; x < 4; x++) {
- for (int y = 0; y < 4; y++) {
- if ((default_matrices[game.piece_queue[index]][y]>>(3 - x))&1) {
- mvaddstr(6 + y, (x * 2) + 36, BLOCK);
- }
- }
- }
- attroff(COLOR_PAIR(game.piece_queue[index]));
-
attron(A_BOLD);
char score[50];
diff --git a/lib/cetris.h b/lib/cetris.h
index 5a6081b..cc4659c 100644
--- a/lib/cetris.h
+++ b/lib/cetris.h
@@ -47,7 +47,6 @@ enum {
enum {
SLOT_OCCUPIED = 1,
SLOT_GHOST = 1 << 1,
- SLOT_CONSTANT = 1 << 2
};
enum {
@@ -80,6 +79,7 @@ typedef enum {
typedef struct {
/* playfield represented by a 2d array */
uint8_t board[CETRIS_BOARD_X][CETRIS_BOARD_Y];
+ int8_t highest_line;
/* constant queue of all 7 possible tetrimino */
uint8_t piece_queue[7];
@@ -122,15 +122,15 @@ const piece_matrix default_matrices[7] = {
/* SRS WALL KICK VALUES */
// https://tetris.wiki/SRS
-static const vec2 srs_wall_kicks[8][4] = {
- {{-1, 0}, {-1, 1}, {0, -2}, {-1, -2}}, // 0->R
- {{1, 0}, {1, -1}, {0, 2}, {1, 2}}, // R->0
- {{1, 0}, {1, -1}, {0, 2}, {1, 2}}, // R->2
- {{-1, 0}, {-1, 1}, {0, -2}, {-1, -2}}, // 2->R
- {{1, 0}, {1, 1}, {0, -2}, {1, -2}}, // 2->L
- {{-1, 0}, {-1, -1}, {0, 2}, {-1, 2}}, // L->2
- {{-1, 0}, {-1, -1}, {0, 2}, {-1, 2}}, // L->0
- {{1, 0}, {1, 1}, {0, -2}, {1, -2}} // 0->L
+static const vec2 srs_wall_kicks[8][5] = {
+ {{0, 0}, {-1, 0}, {-1, 1}, {0, -2}, {-1, -2}}, // 0->R
+ {{0, 0}, {1, 0}, {1, -1}, {0, 2}, {1, 2}}, // R->0
+ {{0, 0}, {1, 0}, {1, -1}, {0, 2}, {1, 2}}, // R->2
+ {{0, 0}, {-1, 0}, {-1, 1}, {0, -2}, {-1, -2}}, // 2->R
+ {{0, 0}, {1, 0}, {1, 1}, {0, -2}, {1, -2}}, // 2->L
+ {{0, 0}, {-1, 0}, {-1, -1}, {0, 2}, {-1, 2}}, // L->2
+ {{0, 0}, {-1, 0}, {-1, -1}, {0, 2}, {-1, 2}}, // L->0
+ {{0, 0}, {1, 0}, {1, 1}, {0, -2}, {1, -2}} // 0->L
};
static const vec2 srs_wall_kicks_i[8][5] = {
@@ -203,8 +203,7 @@ static int check_matrix(cetris_game *g, piece_matrix *m) {
return 0;
if (r.y >= CETRIS_BOARD_Y)
return -1;
- if ((g->board[r.x][r.y] & SLOT_OCCUPIED)
- && (g->board[r.x][r.y] & SLOT_CONSTANT))
+ if (g->board[r.x][r.y] & SLOT_OCCUPIED)
return -1;
}
}
@@ -281,7 +280,7 @@ static void add_score(cetris_game *g, int lines) {
}
static void make_ghosts(cetris_game *g) {
- int orig_y = g->current.pos.y;
+ int8_t orig_y = g->current.pos.y;
while (check_matrix(g, &g->current.m) > 0) {
g->current.pos.y++;
}
@@ -289,13 +288,6 @@ static void make_ghosts(cetris_game *g) {
g->current.pos.y = orig_y;
}
-static void reset_tetrimino(tetrimino *t) {
- t->r = INIT;
- t->pos.x = 3;
- t->pos.y = (t->t == MINO_I) ? 17 : 16;
- t->ghost_y = 0;
-}
-
static void move_current(cetris_game *g, input_t move) {
if (g->game_over || g->next_piece_tick)
return;
@@ -346,12 +338,19 @@ static void next_piece(cetris_game *g) {
static void lock_current(cetris_game *g) {
g->current.locked = true;
- for (int x = 0; x < CETRIS_BOARD_X; x++) {
- for (int y = 0; y < CETRIS_BOARD_Y; y++) {
- if (g->board[x][y] & SLOT_OCCUPIED)
- g->board[x][y] |= SLOT_CONSTANT;
+ for (int y = 0; y < 4; y++) {
+ for (int x = 0; x < 4; x++) {
+ if ((g->current.m[y]>>(3 - x))&1) {
+ g->board[g->current.pos.x + x][g->current.pos.y + y] |= SLOT_OCCUPIED;
+ g->board[g->current.pos.x + x][g->current.pos.y + y] |= g->current.t << 5;
+ }
}
}
+
+ if (g->current.pos.y < g->highest_line) {
+ g->highest_line = g->current.pos.y;
+ }
+
update_board(g);
}
@@ -369,8 +368,8 @@ static void hard_drop(cetris_game *g) {
g->score += 2 * drop_count; // 2 score for each hard-drop'd cell
- update_board(g);
lock_current(g);
+ update_board(g);
}
static void rotate_matrix(cetris_game *g, piece_matrix *m, bool clockwise) {
@@ -411,33 +410,27 @@ static void rotate_piece(cetris_game *g, bool clockwise) {
rotate_matrix(g, &m, clockwise);
+ vec2 kick;
bool set_current = false;
- if (check_matrix(g, &m) > 0) {
- set_current = true;
- }
-
bool did_kick = false;
- if (!set_current) {
- vec2 kick;
- for (int i = 0; i < 4; i++) {
- if (g->current.t == MINO_I) {
- kick = srs_wall_kicks_i[wall_kick][i];
- } else {
- kick = srs_wall_kicks[wall_kick][i];
- }
+ for (int i = 0; i < 4; i++) {
+ if (g->current.t == MINO_I) {
+ kick = srs_wall_kicks_i[wall_kick][i];
+ } else {
+ kick = srs_wall_kicks[wall_kick][i];
+ }
- g->current.pos.x += kick.x;
- g->current.pos.y += kick.y;
+ g->current.pos.x += kick.x;
+ g->current.pos.y += kick.y;
- if (check_matrix(g, &m) > 0) {
- set_current = true;
- break;
- } else {
- g->current.pos.x -= kick.x;
- g->current.pos.y -= kick.y;
- }
+ if (check_matrix(g, &m) > 0) {
+ set_current = true;
+ if (i > 0) did_kick = true;
+ break;
}
- did_kick = true;
+
+ g->current.pos.x -= kick.x;
+ g->current.pos.y -= kick.y;
}
if (set_current) {
@@ -472,13 +465,9 @@ void update_board(cetris_game *g) {
return;
int lines_cleared = 0;
- for (int y = 0; y < CETRIS_BOARD_Y; y++) {
+ for (int y = g->highest_line; y < CETRIS_BOARD_Y; y++) {
bool clear_line = true;
for (int x = 0; x < CETRIS_BOARD_X; x++) {
- if (!(g->board[x][y] & SLOT_CONSTANT)) {
- g->board[x][y] = 0;
- }
-
if (!(g->board[x][y] & SLOT_OCCUPIED)
|| g->line_remove_tick[y] > 0) {
clear_line = false;
@@ -500,7 +489,7 @@ void update_board(cetris_game *g) {
}
make_ghosts(g);
- set_matrix(g, &g->current.m);
+ //set_matrix(g, &g->current.m);
assert(lines_cleared <= 4);
@@ -528,8 +517,7 @@ CETRIS_EXPORT void hold_piece(cetris_game *g) {
g->current = g->held;
g->held = tmp;
} else {
- g->held = g->current;
- reset_tetrimino(&g->held);
+ set_piece(g->current.t, &g->held);
g->piece_held = true;
next_piece(g);
}
@@ -570,6 +558,7 @@ CETRIS_EXPORT void init_game(cetris_game *g) {
memset(g, 0, sizeof(cetris_game));
g->level = CETRIS_STARTING_LEVEL;
+ g->highest_line = CETRIS_BOARD_Y;
init_queue(g);
shuffle_queue(g);
@@ -608,11 +597,12 @@ CETRIS_EXPORT void update_game_tick(cetris_game *g) {
if (!g->next_piece_tick && g->current.lock_tick &&
g->current.lock_tick <= g->tick) {
g->current.pos.y++;
- if (check_matrix(g, &g->current.m) <= 0) {
+ int8_t res = check_matrix(g, &g->current.m);
+ g->current.pos.y--;
+ if (res <= 0) {
lock_current(g);
did_move = true;
}
- g->current.pos.y--;
g->current.lock_tick = 0;
}