summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Opalach <andrew@akon.city> 2019-10-22 12:56:52 -0400
committerAndrew Opalach <andrew@akon.city> 2019-10-22 12:56:52 -0400
commitdc753ff2db5234dcfbac0eea4250e68d4455aef0 (patch)
tree7cd006ae5aae623f3fd09e7d2578992b225311cf
parent9fd2ebced8d3af6ad43323a2196e6638f7e6ecf5 (diff)
downloadcetris-dc753ff2db5234dcfbac0eea4250e68d4455aef0.tar.gz
cetris-dc753ff2db5234dcfbac0eea4250e68d4455aef0.tar.bz2
cetris-dc753ff2db5234dcfbac0eea4250e68d4455aef0.zip
greatly imporve memory usage of a game instance (5704 -> 788 bytes)
-rw-r--r--frontends/curses/curses_ui.c31
-rw-r--r--frontends/gl/main.c8
-rw-r--r--lib/cetris.h110
-rw-r--r--lib/test.h6
-rw-r--r--meson.build6
-rw-r--r--meson_options.txt2
-rw-r--r--test/memory_test.c13
-rw-r--r--test/meson.build5
8 files changed, 99 insertions, 82 deletions
diff --git a/frontends/curses/curses_ui.c b/frontends/curses/curses_ui.c
index 5776af3..94b6141 100644
--- a/frontends/curses/curses_ui.c
+++ b/frontends/curses/curses_ui.c
@@ -91,14 +91,13 @@ void curses_init() {
#endif
start_color();
- init_pair(COLOR_NONE, COLOR_BLACK, COLOR_BLACK);
- init_pair(COLOR_O, COLOR_YELLOW, COLOR_BLACK);
- init_pair(COLOR_Z, COLOR_RED, COLOR_BLACK);
- init_pair(COLOR_S, COLOR_GREEN, COLOR_BLACK);
- init_pair(COLOR_T, COLOR_MAGENTA, COLOR_BLACK);
- init_pair(COLOR_L, COLOR_WHITE, COLOR_BLACK); // should be orange
- init_pair(COLOR_I, COLOR_CYAN, COLOR_BLACK);
- init_pair(COLOR_J, COLOR_BLUE, COLOR_BLACK);
+ init_pair(MINO_O, COLOR_YELLOW, COLOR_BLACK);
+ init_pair(MINO_Z, COLOR_RED, COLOR_BLACK);
+ init_pair(MINO_S, COLOR_GREEN, COLOR_BLACK);
+ init_pair(MINO_T, COLOR_MAGENTA, COLOR_BLACK);
+ init_pair(MINO_L, COLOR_WHITE, COLOR_BLACK); // should be orange
+ init_pair(MINO_I, COLOR_CYAN, COLOR_BLACK);
+ init_pair(MINO_J, COLOR_BLUE, COLOR_BLACK);
clear();
}
@@ -127,30 +126,30 @@ void draw_board() {
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].ghost) {
+ if (game.board[x][y] & SLOT_GHOST) {
attron(A_DIM);
mvaddstr(draw_y, draw_x, BLOCK);
attroff(A_DIM);
}
- if (game.board[x][y].occupied) {
- attron(COLOR_PAIR(game.board[x][y].c) | A_BOLD);
- if (game.board[0][y].remove_tick) {
+ if (game.board[x][y] & SLOT_OCCUPIED) {
+ attron(COLOR_PAIR(game.board[x][y] >> 5) | A_BOLD);
+ if (game.line_remove_tick[y]) {
if (game.tick % 2 == 0) {
mvaddstr(draw_y, draw_x, BLOCK);
}
} else {
mvaddstr(draw_y, draw_x, BLOCK);
}
- attroff(COLOR_PAIR(game.board[x][y].c) | A_BOLD);
+ attroff(COLOR_PAIR(game.board[x][y] >> 5) | A_BOLD);
}
}
int index = game.current_index;
- attron(COLOR_PAIR(game.piece_queue[index].c));
+ attron(COLOR_PAIR(game.piece_queue[index].t));
for (int x = 0; x < 4; x++) {
for (int y = 0; y < 4; y++) {
if (game.piece_queue[index].m[y][x]) {
- if (game.piece_queue[index].t == I || game.piece_queue[index].t == O) {
+ if (game.piece_queue[index].t == MINO_I || game.piece_queue[index].t == MINO_O) {
mvaddstr(6 + y, (x * 2) + 36, BLOCK);
} else {
mvaddstr(6 + y, (x * 2) + 37, BLOCK);
@@ -158,7 +157,7 @@ void draw_board() {
}
}
}
- attroff(COLOR_PAIR(game.piece_queue[index].c));
+ attroff(COLOR_PAIR(game.piece_queue[index].t));
attron(A_BOLD);
diff --git a/frontends/gl/main.c b/frontends/gl/main.c
index a9edd35..c1c6c2d 100644
--- a/frontends/gl/main.c
+++ b/frontends/gl/main.c
@@ -56,8 +56,8 @@ GLuint indices[] = {
1, 2, 3 // second triangle
};
-rbg_color colors[8] = {
- {0.0f, 0.0f, 0.0f}, // Black
+rbg_color colors[7] = {
+ //{0.0f, 0.0f, 0.0f}, // Black
{0.127f,0.219f,0.255f}, // Aqua
{0.61f,0.153f,0.112f}, // Olive
{0.177f,0.13f,0.201f}, // Purple
@@ -236,8 +236,8 @@ int main(void) {
glBindVertexArray(block.vao);
for (int x = 0; x < CETRIS_BOARD_X; x++) {
for (int y = 0; y < CETRIS_BOARD_Y; y++) {
- if (cetris.board[x][y].occupied) {
- update_block(&block, x, y, cetris.board[x][y].c);
+ if (cetris.board[x][y].flags & SLOT_OCCUPIED) {
+ update_block(&block, x, y, cetris.board[x][y].color);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
}
}
diff --git a/lib/cetris.h b/lib/cetris.h
index b867977..fb3ab1f 100644
--- a/lib/cetris.h
+++ b/lib/cetris.h
@@ -28,46 +28,40 @@
#define CETRIS_STARTING_LEVEL 1
typedef struct {
- int x;
- int y;
+ int8_t x;
+ int8_t y;
} vec2;
-typedef int piece_matrix[4][4];
+typedef uint8_t piece_matrix[4][4];
-typedef enum { O, I, S, Z, L, J, T } type;
+enum {
+ MINO_O,
+ MINO_I,
+ MINO_S,
+ MINO_Z,
+ MINO_L,
+ MINO_J,
+ MINO_T
+};
-typedef enum {
- COLOR_NONE,
- COLOR_O, // yellow
- COLOR_I, // cyan
- COLOR_S, // green
- COLOR_Z, // red
- COLOR_L, // orange
- COLOR_J, // blue
- COLOR_T // purple
-} color;
+enum {
+ SLOT_OCCUPIED = 1,
+ SLOT_GHOST = 1 << 1,
+ SLOT_CONSTANT = 1 << 2
+};
typedef enum { INIT, ONCE_RIGHT, ONCE_LEFT, TWICE } srs_state;
typedef struct {
- type t;
- srs_state r;
- color c;
+ uint8_t t;
vec2 pos;
+ srs_state r;
piece_matrix m;
- int ghost_y;
- int lock_tick;
+ uint8_t ghost_y;
+ uint16_t lock_tick;
bool locked;
} tetrimino;
-typedef struct {
- bool occupied;
- bool ghost;
- bool constant;
- int remove_tick;
- color c;
-} slot;
-
typedef enum {
DOWN = 1,
USER_DOWN = 2,
@@ -80,7 +74,7 @@ typedef enum {
typedef struct {
/* playfield represented by a 2d array */
- slot board[CETRIS_BOARD_X][CETRIS_BOARD_Y];
+ uint8_t board[CETRIS_BOARD_X][CETRIS_BOARD_Y];
/* constant queue of all 7 possible tetrimino */
tetrimino piece_queue[7];
@@ -89,17 +83,18 @@ typedef struct {
tetrimino current;
tetrimino held;
bool piece_held;
- int current_index;
+ uint8_t current_index;
/* internal game tick */
- int tick;
- int next_drop_tick;
- int next_piece_tick;
- int down_move_tick;
+ uint16_t tick;
+ uint16_t next_drop_tick;
+ uint16_t next_piece_tick;
+ uint16_t down_move_tick;
+ uint16_t line_remove_tick[CETRIS_BOARD_Y];
/* progress trackers */
- int lines;
- int level;
+ uint8_t lines;
+ uint8_t level;
bool game_over;
/* scoring flags */
@@ -107,7 +102,7 @@ typedef struct {
bool mini_tspin;
/* score counter */
- int score;
+ uint16_t score;
} cetris_game;
static piece_matrix default_matrices[7] = {
@@ -171,10 +166,8 @@ CETRIS_EXPORT void hold_piece(cetris_game *g);
static void init_piece_queue(cetris_game *g) {
for (int i = 0; i < 7; i++) {
g->piece_queue[i].t = i;
- g->piece_queue[i].c = i + 1;
g->piece_queue[i].r = INIT;
g->piece_queue[i].lock_tick = 0;
- //g->piece_queue[i].locked = false;
g->piece_queue[i].ghost_y = 0;
memcpy(g->piece_queue[i].m, default_matrices[i], sizeof(piece_matrix));
@@ -182,7 +175,7 @@ static void init_piece_queue(cetris_game *g) {
* tick the bottom row will show. Values here are adjusted
* for the default 4x4 matricies for each piece */
g->piece_queue[i].pos.x = 3;
- g->piece_queue[i].pos.y = (i == I) ? 17 : 16;
+ g->piece_queue[i].pos.y = (i == MINO_I) ? 17 : 16;
}
}
@@ -206,7 +199,8 @@ 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].occupied && g->board[r.x][r.y].constant)
+ if ((g->board[r.x][r.y] & SLOT_OCCUPIED)
+ && (g->board[r.x][r.y] & SLOT_CONSTANT))
return -1;
}
}
@@ -220,14 +214,14 @@ static void set_matrix(cetris_game *g, piece_matrix *m) {
if ((*m)[y][x]) {
vec2 r = (vec2){x + g->current.pos.x, y + g->current.pos.y};
if (r.y >= 0) {
- if (!g->board[r.x][r.y].occupied) {
- g->board[r.x][r.y].occupied = true;
- g->board[r.x][r.y].c = g->current.c;
+ if (!(g->board[r.x][r.y] & SLOT_OCCUPIED)) {
+ g->board[r.x][r.y] |= SLOT_OCCUPIED;
+ g->board[r.x][r.y] |= g->current.t << 5;
}
}
if (g->current.ghost_y + y >= 0)
if (r.y != (g->current.ghost_y + y))
- g->board[r.x][g->current.ghost_y + y].ghost = true;
+ g->board[r.x][g->current.ghost_y + y] |= SLOT_GHOST;
}
}
}
@@ -294,7 +288,7 @@ static void make_ghosts(cetris_game *g) {
static void reset_tetrimino(tetrimino *t) {
t->r = INIT;
t->pos.x = 3;
- t->pos.y = (t->t == I) ? 17 : 16;
+ t->pos.y = (t->t == MINO_I) ? 17 : 16;
t->ghost_y = 0;
}
@@ -349,8 +343,8 @@ 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].occupied)
- g->board[x][y].constant = 1;
+ if (g->board[x][y] & SLOT_OCCUPIED)
+ g->board[x][y] |= SLOT_CONSTANT;
}
}
update_board(g);
@@ -381,7 +375,7 @@ static void rotate_matrix(cetris_game *g, piece_matrix *m, bool clockwise) {
int new_x = (clockwise) ? 1 - (y - 2) : 1 + (y - 2);
int new_y = (clockwise) ? 2 + (x - 1) : 2 - (x - 1);
- if (g->current.t == I) {
+ if (g->current.t == MINO_I) {
if (clockwise)
new_y--;
else
@@ -397,7 +391,7 @@ static void rotate_matrix(cetris_game *g, piece_matrix *m, bool clockwise) {
static void rotate_piece(cetris_game *g, bool clockwise) {
if (g->game_over || g->next_piece_tick)
return;
- if (g->current.t == O)
+ if (g->current.t == MINO_O)
return;
srs_state next = 0;
@@ -450,7 +444,7 @@ static void rotate_piece(cetris_game *g, bool clockwise) {
bool set_current = false;
bool did_kick = false;
for (int i = 0; i < 5; i++) {
- if (g->current.t == I) {
+ if (g->current.t == MINO_I) {
kick = srs_wall_kicks_i[wall_kick][i];
} else {
kick = srs_wall_kicks[wall_kick][i];
@@ -473,7 +467,7 @@ static void rotate_piece(cetris_game *g, bool clockwise) {
if (set_current) {
/* check for tspin */
- if (g->current.t == T) {
+ if (g->current.t == MINO_T) {
bool did_tspin = true;
for (int i = 1; i < 5; i++) {
g->current.pos.x += basic_movements[i].x;
@@ -508,16 +502,18 @@ void update_board(cetris_game *g) {
for (int y = 0; y < CETRIS_BOARD_Y; y++) {
bool clear_line = true;
for (int x = 0; x < CETRIS_BOARD_X; x++) {
- if (!g->board[x][y].constant) {
- memset(&g->board[x][y], 0, sizeof(slot));
+ if (!(g->board[x][y] & SLOT_CONSTANT)) {
+ g->board[x][y] = 0;
}
- if (!g->board[x][y].occupied || g->board[0][y].remove_tick > 0) {
+ if (!(g->board[x][y] & SLOT_OCCUPIED)
+ || g->line_remove_tick[y] > 0) {
clear_line = false;
}
}
// remove tick only tracked on first block of line
- if (g->board[0][y].remove_tick && g->board[0][y].remove_tick <= g->tick) {
+ if (g->line_remove_tick[y] && g->line_remove_tick[y] <= g->tick) {
+ g->line_remove_tick[y] = 0;
for (int s = y - 1; s >= 0; s--) {
for (int x = 0; x < CETRIS_BOARD_X; x++) {
g->board[x][s + 1] = g->board[x][s];
@@ -525,7 +521,7 @@ void update_board(cetris_game *g) {
}
}
if (clear_line) {
- g->board[0][y].remove_tick = g->tick + CETRIS_LINE_CLEAR_DELAY;
+ g->line_remove_tick[y] = g->tick + CETRIS_LINE_CLEAR_DELAY;
lines_cleared++;
}
}
@@ -597,7 +593,7 @@ CETRIS_EXPORT void init_game(cetris_game *g) {
srand(time(NULL));
#ifdef BUILD_TESTS
- apply_test_board(g, TSPIN_NO_LINES);
+ //apply_test_board(g, TSPIN_NO_LINES);
#endif
memset(g, 0, sizeof(cetris_game));
diff --git a/lib/test.h b/lib/test.h
index 3e41971..cc7d44a 100644
--- a/lib/test.h
+++ b/lib/test.h
@@ -5,7 +5,7 @@ typedef enum {
TSPIN_NO_LINES
} test;
-u8 tspin_board[20][10] = {
+int tspin_board[20][10] = {
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
@@ -28,7 +28,7 @@ u8 tspin_board[20][10] = {
{ 1, 1, 1, 1, 1, 1, 1, 1, 1, 0 }
};
-u8 tspin_no_lines_board[20][10] = {
+int tspin_no_lines_board[20][10] = {
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
@@ -51,6 +51,7 @@ u8 tspin_no_lines_board[20][10] = {
{ 1, 1, 1, 1, 1, 1, 1, 1, 1, 0 }
};
+/*
void apply_test_board(cetris_game* g, test t) {
u8 (*board)[20][10];
switch (t) {
@@ -73,3 +74,4 @@ void apply_test_board(cetris_game* g, test t) {
}
}
}
+*/
diff --git a/meson.build b/meson.build
index 1140d1f..5bcff0f 100644
--- a/meson.build
+++ b/meson.build
@@ -4,15 +4,17 @@ project('cetris', 'c',
compiler = meson.get_compiler('c')
+cetris_inc = include_directories('lib')
+
if get_option('debug') == true
if host_machine.system() == 'windows'
add_global_arguments('/DBUILD_TESTS', language : 'c')
else
add_global_arguments('-DBUILD_TESTS', language : 'c')
endif
-endif
-cetris_inc = include_directories('lib')
+ subdir('test')
+endif
if get_option('curses-frontend') == true
subdir('frontends/curses')
diff --git a/meson_options.txt b/meson_options.txt
index 43b497a..b57b6ff 100644
--- a/meson_options.txt
+++ b/meson_options.txt
@@ -1,2 +1,2 @@
option('curses-frontend', type : 'boolean', value : true)
-option('gl-frontend', type : 'boolean', value : true)
+option('gl-frontend', type : 'boolean', value : false)
diff --git a/test/memory_test.c b/test/memory_test.c
new file mode 100644
index 0000000..7a61f6a
--- /dev/null
+++ b/test/memory_test.c
@@ -0,0 +1,13 @@
+#include <stdio.h>
+
+#include "cetris.h"
+
+int main(void) {
+ cetris_game game;
+
+ init_game(&game);
+
+ printf("memory usage of game instance: %li\n", sizeof(game));
+
+ return 0;
+}
diff --git a/test/meson.build b/test/meson.build
new file mode 100644
index 0000000..351be02
--- /dev/null
+++ b/test/meson.build
@@ -0,0 +1,5 @@
+mem_test = ['memory_test.c']
+
+executable('mem_test', mem_test,
+ include_directories: cetris_inc,
+ install: false)