diff options
| author | 2019-10-22 12:56:52 -0400 | |
|---|---|---|
| committer | 2019-10-22 12:56:52 -0400 | |
| commit | dc753ff2db5234dcfbac0eea4250e68d4455aef0 (patch) | |
| tree | 7cd006ae5aae623f3fd09e7d2578992b225311cf | |
| parent | 9fd2ebced8d3af6ad43323a2196e6638f7e6ecf5 (diff) | |
| download | cetris-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.c | 31 | ||||
| -rw-r--r-- | frontends/gl/main.c | 8 | ||||
| -rw-r--r-- | lib/cetris.h | 110 | ||||
| -rw-r--r-- | lib/test.h | 6 | ||||
| -rw-r--r-- | meson.build | 6 | ||||
| -rw-r--r-- | meson_options.txt | 2 | ||||
| -rw-r--r-- | test/memory_test.c | 13 | ||||
| -rw-r--r-- | test/meson.build | 5 |
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));
@@ -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) |