diff options
| author | 2019-08-19 15:53:22 -0400 | |
|---|---|---|
| committer | 2019-08-19 15:53:22 -0400 | |
| commit | d64514659c38c672e65ffccd6f44a64143a4dbfd (patch) | |
| tree | e1704f5b1d0c7784991da6c18d6b520ec1e08e65 | |
| parent | 9298c0795c9ffba2fa804290df3792c437d3c500 (diff) | |
| download | cetris-d64514659c38c672e65ffccd6f44a64143a4dbfd.tar.gz cetris-d64514659c38c672e65ffccd6f44a64143a4dbfd.tar.bz2 cetris-d64514659c38c672e65ffccd6f44a64143a4dbfd.zip | |
remove das code and simplify some other stuff
| -rw-r--r-- | core/cetris.c | 560 | ||||
| -rw-r--r-- | core/cetris.h (renamed from core/include/cetris.h) | 28 | ||||
| -rw-r--r-- | core/include/input.h | 9 | ||||
| -rw-r--r-- | core/include/matrix.h | 14 | ||||
| -rw-r--r-- | core/include/types.h | 29 | ||||
| -rw-r--r-- | core/meson.build | 4 | ||||
| -rw-r--r-- | core/src/cetris.c | 300 | ||||
| -rw-r--r-- | core/src/input.c | 51 | ||||
| -rw-r--r-- | core/src/matrix.c | 278 | ||||
| -rw-r--r-- | core/test.c (renamed from core/src/test.c) | 0 | ||||
| -rw-r--r-- | core/test.h (renamed from core/include/test.h) | 0 | ||||
| -rw-r--r-- | core/types.h | 10 | ||||
| -rw-r--r-- | frontends/curses/curses_ui.c | 16 | ||||
| -rw-r--r-- | frontends/curses/meson.build | 1 | ||||
| -rw-r--r-- | frontends/gl/main.c | 29 | ||||
| -rw-r--r-- | frontends/gl/res/play_field.png | bin | 0 -> 814 bytes | |||
| -rw-r--r-- | frontends/gl/res/play_field_shake_1.png | bin | 0 -> 9007 bytes | |||
| -rw-r--r-- | frontends/gl/res/play_field_shake_2.png | bin | 0 -> 10769 bytes | |||
| -rw-r--r-- | frontends/gl/res/play_field_shake_3.png | bin | 0 -> 9551 bytes | |||
| -rw-r--r-- | frontends/gl/res/play_field_shake_4.png | bin | 0 -> 9954 bytes | |||
| -rw-r--r-- | meson.build | 2 |
21 files changed, 618 insertions, 713 deletions
diff --git a/core/cetris.c b/core/cetris.c new file mode 100644 index 0000000..5387ff1 --- /dev/null +++ b/core/cetris.c @@ -0,0 +1,560 @@ +#include <time.h>
+#include <string.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <stdbool.h>
+
+#include "cetris.h"
+
+#ifdef BUILD_TESTS
+#include "test.h"
+#endif
+
+/* PROTOTYPES */
+
+static void next_piece(cetris_game* g);
+static void update_board(cetris_game* g);
+static void lock_current(cetris_game* g);
+static void move_current(cetris_game* g, input_t move);
+static void hard_drop(cetris_game* g);
+static void rotate_matrix(cetris_game* g, bool clockwise);
+static void set_matrix(cetris_game* g, piece_matrix* m);
+static i8 check_matrix(cetris_game* g, piece_matrix* m);
+static void init_piece_queue(cetris_game* g);
+static void shuffle_queue(cetris_game* g);
+static void next_piece(cetris_game* g);
+static void lock_current(cetris_game* g);
+static void make_ghosts(cetris_game* g);
+static void update_board(cetris_game* g);
+static void add_score(cetris_game* g, u8 lines);
+static void reset_tetrimino(tetrimino* t);
+
+/* SRS WALL KICK VALUES */
+
+// https://tetris.wiki/SRS
+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] = {
+ { {0, 0}, {-2, 0}, {1, 0}, {-2,-1}, {1,2} }, // 0->R
+ { {0, 0}, {2, 0}, {-1, 0}, {2,1}, {-1,-2} }, // R->0
+ { {0, 0}, {-1, 0}, {2, 0}, {-1,2}, {2,-1} }, // R->2
+ { {0, 0}, {1, 0}, {-2, 0}, {1,-2}, {-2,1} }, // 2->R
+ { {0, 0}, {2, 0}, {-1, 0}, {2,1}, {-1,-2} }, // 2->L
+ { {0, 0}, {-2, 0}, {1, 0}, {-2,-1}, {1,2} }, // L->2
+ { {0, 0}, {1, 0}, {-2, 0}, {1,-2}, {-2,1} }, // L->0
+ { {0, 0}, {-1, 0}, {2, 0}, {-1,2}, {2,-1} } // 0->L
+};
+
+/* DEFAULT MATRIX FOR EACH POSSIBLE TETRIMINO */
+
+static const piece_matrix default_matrices[7] = {
+ {
+ { 0, 0, 0, 0 },
+ { 0, 1, 1, 0 },
+ { 0, 1, 1, 0 },
+ { 0, 0, 0, 0 }
+ },
+
+ {
+ { 0, 0, 0, 0 },
+ { 1, 1, 1, 1 },
+ { 0, 0, 0, 0 },
+ { 0, 0, 0, 0 }
+ },
+
+ {
+ { 0, 0, 0, 0 },
+ { 0, 1, 1, 0 },
+ { 1, 1, 0, 0 },
+ { 0, 0, 0, 0 }
+ },
+
+ {
+ { 0, 0, 0, 0 },
+ { 1, 1, 0, 0 },
+ { 0, 1, 1, 0 },
+ { 0, 0, 0, 0 }
+ },
+
+ {
+ { 0, 0, 0, 0 },
+ { 0, 0, 1, 0 },
+ { 1, 1, 1, 0 },
+ { 0, 0, 0, 0 }
+ },
+
+ {
+ { 0, 0, 0, 0 },
+ { 1, 0, 0, 0 },
+ { 1, 1, 1, 0 },
+ { 0, 0, 0, 0 }
+ },
+
+ {
+ { 0, 0, 0, 0 },
+ { 0, 1, 0, 0 },
+ { 1, 1, 1, 0 },
+ { 0, 0, 0, 0 }
+ }
+};
+
+static const vec2 basic_movements[5] = {
+ {0, 0}, {0, 1}, {0, 1}, {1, 0}, {-1, 0} // NONE, DOWN, USER_DOWN, RIGHT, LEFT
+};
+
+// https://tetris.fandom.com/wiki/Tetris_Worlds
+// TODO: Make this more accurate
+static const u32 level_drop_delay[20] = {
+ 60, 48, 37, 28, 21, 16, 11, 8, 6, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1
+};
+
+/* GAME FUNCTIONS */
+
+void init_game(cetris_game* g) {
+
+ /* check for config errors */
+ assert(CETRIS_NEXT_PIECE_DELAY >= CETRIS_LINE_CLEAR_DELAY);
+
+ srand(time(NULL));
+
+#ifdef BUILD_TESTS
+ apply_test_board(g, TSPIN_NO_LINES);
+#endif
+
+ memset(g, 0, sizeof(cetris_game));
+
+ g->level = CETRIS_STARTING_LEVEL;
+
+ init_piece_queue(g);
+ shuffle_queue(g);
+
+ next_piece(g);
+}
+
+void init_piece_queue(cetris_game* g) {
+ for (u8 i = 0; i < 7; i++) {
+ g->piece_queue[i].t = i;
+ g->piece_queue[i].c = i + 1;
+ memcpy(g->piece_queue[i].m, default_matrices[i], sizeof(piece_matrix));
+ 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;
+
+ /* Pieces should spawn so that on the first down
+ * 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;
+ }
+}
+
+void shuffle_queue(cetris_game* g) {
+ for (u8 i = 0; i < 7; i++) {
+ tetrimino t = g->piece_queue[i];
+ u8 rand_index = rand() % 7;
+ g->piece_queue[i] = g->piece_queue[rand_index];
+ g->piece_queue[rand_index] = t;
+ }
+}
+
+void update_game_tick(cetris_game* g) {
+ if (g->game_over) return;
+
+ g->tick++;
+
+ if (g->next_piece_tick && g->tick >= g->next_piece_tick) {
+ next_piece(g);
+ }
+
+ if (g->next_piece_tick) return;
+
+ bool did_move = false;
+ if (g->tick >= g->next_drop_tick || !g->next_drop_tick) {
+ if (g->next_drop_tick) {
+ move_current(g, DOWN);
+ did_move = true;
+ }
+
+ if (g->level <= 20) {
+ g->next_drop_tick = g->tick + level_drop_delay[g->level - 1];
+ } else {
+ g->next_drop_tick = g->tick + level_drop_delay[19];
+ }
+ }
+
+ /* lock piece if it was hovering for CETRIS_LOCK_DELAY */
+ 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) {
+ lock_current(g);
+ did_move = true;
+ }
+ g->current.pos.y--;
+ g->current.lock_tick = 0;
+ }
+
+ if (did_move) update_board(g);
+}
+
+void next_piece(cetris_game* g) {
+ g->next_drop_tick = 0;
+ g->next_piece_tick = 0;
+
+ g->current = g->piece_queue[g->current_index];
+ if (check_matrix(g, &g->current.m) <= 0) {
+ g->game_over = true;
+ }
+ g->current_index++;
+
+ if (!g->game_over) {
+ move_current(g, DOWN);
+ }
+
+ if (g->current_index >= 7) {
+ g->current_index = 0;
+ shuffle_queue(g);
+ }
+
+ update_board(g);
+}
+
+void lock_current(cetris_game* g) {
+ g->current.locked = true;
+ for (u8 x = 0; x < CETRIS_BOARD_X; x++) {
+ for (u8 y = 0; y < CETRIS_BOARD_Y; y++) {
+ if (g->board[x][y].occupied) g->board[x][y].constant = 1;
+ }
+ }
+ update_board(g);
+}
+
+void make_ghosts(cetris_game* g) {
+ u8 orig_y = g->current.pos.y;
+ while (true) {
+ g->current.pos.y++;
+ if (check_matrix(g, &g->current.m) <= 0) {
+ g->current.ghost_y = g->current.pos.y - 1;
+ g->current.pos.y = orig_y;
+ break;
+ }
+ }
+}
+
+void update_board(cetris_game* g) {
+ if (g->game_over) return;
+
+ u8 lines_cleared = 0;
+ for (u8 y = 0; y < CETRIS_BOARD_Y; y++) {
+ bool clear_line = true;
+ for (u8 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].occupied || g->board[0][y].remove_tick > 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) {
+ for (i8 s = y - 1; s >= 0; s--) {
+ for (u8 x = 0; x < CETRIS_BOARD_X; x++) {
+ g->board[x][s + 1] = g->board[x][s];
+ }
+ }
+ }
+ if (clear_line) {
+ g->board[0][y].remove_tick = g->tick + CETRIS_LINE_CLEAR_DELAY;
+ lines_cleared++;
+ }
+ }
+
+ make_ghosts(g);
+ set_matrix(g, &g->current.m);
+
+ assert(lines_cleared <= 4);
+
+ if (g->current.locked && !g->next_piece_tick) {
+ if (lines_cleared > 0) {
+ g->next_piece_tick = g->tick + CETRIS_NEXT_PIECE_DELAY;
+ } else {
+ next_piece(g);
+ }
+ }
+
+ if (lines_cleared > 0 || g->tspin || g->mini_tspin) {
+ add_score(g, lines_cleared);
+ if (lines_cleared > 0) {
+ g->lines += lines_cleared;
+ if (g->lines >= (g->level * 10)) g->level++;
+ }
+ }
+}
+
+/* SCORE FUNCTIONS */
+
+void add_score(cetris_game* g, u8 lines) {
+ if (!g->tspin && !g->mini_tspin) {
+ switch (lines) {
+ case 1: g->score += 100 * g->level; break;
+ case 2: g->score += 300 * g->level; break;
+ case 3: g->score += 500 * g->level; break;
+ case 4: g->score += 800 * g->level; break;
+ }
+ } else if (g->tspin) {
+ switch (lines) {
+ case 0: g->score += 400 * g->level; break;
+ case 1: g->score += 800 * g->level; break;
+ case 2: g->score += 1200 * g->level; break;
+ case 3: g->score += 1600 * g->level; break;
+ }
+ g->tspin = false;
+ } else if (g->mini_tspin) {
+ switch (lines) {
+ case 0: g->score += 100 * g->level; break;
+ case 1: g->score += 200 * g->level; break;
+ case 2: g->score += 400 * g->level; break;
+ }
+ g->mini_tspin = false;
+ }
+}
+
+/* MOVEMENT FUNCTIONS */
+
+void move_piece(cetris_game* g, input_t move) {
+ switch (move) {
+ case LEFT:
+ case RIGHT:
+ case DOWN:
+ case USER_DOWN:
+ move_current(g, move);
+ break;
+ case HARD_DROP:
+ hard_drop(g);
+ break;
+ case ROTATE_CW:
+ rotate_matrix(g, 1);
+ break;
+ case ROTATE_CCW:
+ rotate_matrix(g, 0);
+ break;
+ }
+}
+
+void reset_tetrimino(tetrimino* t) {
+ t->r = INIT;
+ t->pos.x = 3;
+ t->pos.y = (t->t == I) ? 17 : 16;
+ t->ghost_y = 0;
+}
+
+void hold_piece(cetris_game* g) {
+ if (g->piece_held) {
+ tetrimino tmp = g->current;
+ g->current = g->held;
+ g->held = tmp;
+ } else {
+ g->held = g->current;
+ reset_tetrimino(&g->held);
+ g->piece_held = true;
+ next_piece(g);
+ }
+ update_board(g);
+}
+
+void move_current(cetris_game* g, input_t move) {
+ if (g->game_over || g->next_piece_tick) return;
+
+ g->current.pos.y += basic_movements[move].y;
+ g->current.pos.x += basic_movements[move].x;
+
+ i8 check = check_matrix(g, &g->current.m);
+ if (check <= 0) {
+ g->current.pos.y -= basic_movements[move].y;
+ g->current.pos.x -= basic_movements[move].x;
+
+ if (move == USER_DOWN) g->score++;
+ if (move == DOWN && check == -1 && !g->current.lock_tick) {
+ g->current.lock_tick = g->tick + CETRIS_LOCK_DELAY;
+ }
+ }
+
+ update_board(g);
+}
+
+i8 check_matrix(cetris_game* g, piece_matrix* m) {
+ for (i8 y = 0; y < 4; y++) {
+ for (i8 x = 0; x < 4; x++) {
+ vec2 r = (vec2){x + g->current.pos.x, y + g->current.pos.y};
+ if (r.y < 0) continue;
+ if ((*m)[y][x]) {
+ if (r.x >= CETRIS_BOARD_X || r.x < 0) 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) return -1;
+ }
+ }
+ }
+ return 1;
+}
+
+void set_matrix(cetris_game* g, piece_matrix* m) {
+ for (i8 y = 0; y < 4; y++) {
+ for (i8 x = 0; x < 4; x++) {
+ vec2 r = (vec2){x + g->current.pos.x, y + g->current.pos.y};
+ if ((*m)[y][x]) {
+ if (r.y >= 0) {
+ g->board[r.x][r.y].occupied = true;
+ g->board[r.x][r.y].c = g->current.c;
+ }
+ 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;
+ }
+ }
+ }
+}
+
+void hard_drop(cetris_game* g) {
+ if (g->game_over || g->next_piece_tick) return;
+
+ bool drop = false;
+ u8 drop_count = 0;
+ while (!drop) {
+ g->current.pos.y++;
+ drop_count++;
+ if (check_matrix(g, &g->current.m) <= 0) {
+ g->current.pos.y--;
+ drop_count--;
+ drop = true;
+ }
+ }
+
+ g->score += 2 * drop_count; // 2 score for each hard-drop'd cell
+
+ update_board(g);
+ lock_current(g);
+}
+
+void rotate_matrix(cetris_game* g, bool clockwise) {
+ if (g->game_over || g->next_piece_tick) return;
+ if (g->current.t == O) return;
+
+ rstate next = 0;
+ u8 wall_kick = 0;
+ switch (g->current.r) {
+ case INIT:
+ if (clockwise) {
+ next = ONCE_RIGHT;
+ wall_kick = 0;
+ } else {
+ next = ONCE_LEFT;
+ wall_kick = 7;
+ } break;
+ case ONCE_RIGHT:
+ if (clockwise) {
+ next = TWICE;
+ wall_kick = 2;
+ } else {
+ next = INIT;
+ wall_kick = 1;
+ } break;
+ case ONCE_LEFT:
+ if (clockwise) {
+ next = INIT;
+ wall_kick = 6;
+ } else {
+ next = TWICE;
+ wall_kick = 5;
+ } break;
+ case TWICE:
+ if (clockwise) {
+ next = ONCE_LEFT;
+ wall_kick = 4;
+ } else {
+ next = ONCE_RIGHT;
+ wall_kick = 3;
+ } break;
+ }
+
+ piece_matrix m;
+ memset(m, 0, sizeof(piece_matrix));
+
+ for (u8 x = 0; x < 4; x++) {
+ for (u8 y = 0; y < 4; y++) {
+ if (g->current.m[y][x]) {
+ u8 new_x = (clockwise) ? 1 - (y - 2) : 1 + (y - 2);
+ u8 new_y = (clockwise) ? 2 + (x - 1) : 2 - (x - 1);
+
+ if (g->current.t == I) {
+ if (clockwise) {
+ new_y--;
+ } else {
+ new_x++;
+ }
+ }
+
+ m[new_y][new_x] = 1;
+ }
+ }
+ }
+
+ vec2 kick;
+ bool set_current = false;
+ bool did_kick = false;
+ for (u8 i = 0; i < 5; i++) {
+ if (g->current.t == 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;
+
+ if (check_matrix(g, &m) > 0) {
+ set_current = true;
+ if (i > 0) did_kick = true;
+ break;
+ } else {
+ g->current.pos.x -= kick.x;
+ g->current.pos.y -= kick.y;
+ }
+ }
+
+ if (set_current) {
+
+ /* check for tspin */
+ if (g->current.t == T) {
+ bool did_tspin = true;
+ for (u8 i = 1; i < 5; i++) {
+ g->current.pos.x += basic_movements[i].x;
+ g->current.pos.y += basic_movements[i].y;
+
+ if (check_matrix(g, &m) == 1) did_tspin = false;
+
+ g->current.pos.x -= basic_movements[i].x;
+ g->current.pos.y -= basic_movements[i].y;
+ }
+
+ if (did_tspin) {
+ if (did_kick) g->mini_tspin = true;
+ else g->tspin = true;
+ }
+ }
+
+ g->current.r = next;
+ memcpy(g->current.m, m, sizeof(piece_matrix));
+ update_board(g);
+ }
+}
diff --git a/core/include/cetris.h b/core/cetris.h index 4a1c1fa..0232e4a 100644 --- a/core/include/cetris.h +++ b/core/cetris.h @@ -20,6 +20,8 @@ #define CETRIS_STARTING_LEVEL 1
+typedef u8 piece_matrix[4][4];
+
typedef enum {
O, I, S, Z, L, J, T
} type;
@@ -74,17 +76,11 @@ typedef struct { bool piece_held;
u8 current_index;
- /* input_manager */
- bool held_moves[7];
- input_t prev_das_move;
- u8 das_repeat;
- u32 das_move_tick;
- u32 down_move_tick;
-
/* internal game tick */
u32 tick;
u32 next_drop_tick;
u32 next_piece_tick;
+ u32 down_move_tick;
/* progress trackers */
u32 lines;
@@ -99,14 +95,18 @@ typedef struct { u32 score;
} cetris_game;
-void next_piece(cetris_game* g);
-void update_board(cetris_game* g);
-void lock_current(cetris_game* g);
-
-/* API PROTOTYPES FUNCTIONS */
+typedef enum {
+ DOWN = 1,
+ USER_DOWN = 2,
+ RIGHT = 3,
+ LEFT = 4,
+ ROTATE_CCW = 5,
+ ROTATE_CW = 6,
+ HARD_DROP = 7
+} input_t;
+/* API FUNCTIONS */
void init_game(cetris_game* g);
void update_game_tick(cetris_game* g);
-void move_piece(cetris_game* g, input_t move, bool hold);
+void move_piece(cetris_game* g, input_t move);
void hold_piece(cetris_game* g);
-void stop_holding(cetris_game* g, input_t move);
diff --git a/core/include/input.h b/core/include/input.h deleted file mode 100644 index 95cb2aa..0000000 --- a/core/include/input.h +++ /dev/null @@ -1,9 +0,0 @@ -#pragma once
-
-#include <stdint.h>
-#include <stdbool.h>
-
-#include "cetris.h"
-
-bool handle_inputs(cetris_game *g);
-void clear_held_key(cetris_game *g);
diff --git a/core/include/matrix.h b/core/include/matrix.h deleted file mode 100644 index eb9e272..0000000 --- a/core/include/matrix.h +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once
-
-#include <stdint.h>
-
-#include "types.h"
-#include "cetris.h"
-
-extern const piece_matrix default_matrices[7];
-
-void move_current(cetris_game* g, input_t move);
-void hard_drop(cetris_game* g);
-void rotate_matrix(cetris_game* g, bool clockwise);
-void set_matrix(cetris_game* g, piece_matrix* m);
-i8 check_matrix(cetris_game* g, piece_matrix* m);
diff --git a/core/include/types.h b/core/include/types.h deleted file mode 100644 index 3471f3c..0000000 --- a/core/include/types.h +++ /dev/null @@ -1,29 +0,0 @@ -#pragma once
-
-#include <stdint.h>
-
-#define u8 uint8_t
-#define u16 uint16_t
-#define u32 uint32_t
-#define u64 uint64_t
-#define i8 int8_t
-#define i16 int16_t
-#define i32 int32_t
-#define i64 int64_t
-
-typedef struct {
- i8 x;
- i8 y;
-} vec2;
-
-typedef u8 piece_matrix[4][4];
-
-typedef enum {
- DOWN = 1,
- USER_DOWN = 2,
- RIGHT = 3,
- LEFT = 4,
- ROTATE_CCW = 5,
- ROTATE_CW = 6,
- HARD_DROP = 7
-} input_t;
diff --git a/core/meson.build b/core/meson.build index c1134c6..92f20c5 100644 --- a/core/meson.build +++ b/core/meson.build @@ -1,7 +1,7 @@ -src = ['src/cetris.c', 'src/input.c', 'src/matrix.c']
+src = ['cetris.c']
if get_option('debug') == true
- src += 'src/test.c'
+ src += 'test.c'
endif
cetris_lib = static_library('cetris', src,
diff --git a/core/src/cetris.c b/core/src/cetris.c deleted file mode 100644 index d8eda2f..0000000 --- a/core/src/cetris.c +++ /dev/null @@ -1,300 +0,0 @@ -#include <time.h>
-#include <string.h>
-#include <stdlib.h>
-#include <assert.h>
-#include <stdbool.h>
-
-#include "cetris.h"
-#include "types.h"
-#include "matrix.h"
-#include "input.h"
-
-#ifdef BUILD_TESTS
-#include "test.h"
-#endif
-
-/* FUNCTION PROTOTYPES */
-
-static void init_piece_queue(cetris_game* g);
-static void shuffle_queue(cetris_game* g);
-static void add_score(cetris_game* g, u8 lines);
-
-/* LEVEL DROP SPEED VALUES */
-
-// https://tetris.fandom.com/wiki/Tetris_Worlds
-// TODO: Make this more accurate
-static const u32 level_drop_delay[20] = {
- 60, 48, 37, 28, 21, 16, 11, 8, 6, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1
-};
-
-/* GAME FUNCTIONS */
-
-void init_game(cetris_game* g) {
-
- /* check for config errors */
- assert(CETRIS_NEXT_PIECE_DELAY >= CETRIS_LINE_CLEAR_DELAY);
-
- srand(time(NULL));
-
-#ifdef BUILD_TESTS
- apply_test_board(g, TSPIN_NO_LINES);
-#endif
-
- memset(g, 0, sizeof(cetris_game));
-
- g->level = CETRIS_STARTING_LEVEL;
-
- init_piece_queue(g);
- shuffle_queue(g);
-
- next_piece(g);
-}
-
-void init_piece_queue(cetris_game* g) {
- for (u8 i = 0; i < 7; i++) {
- g->piece_queue[i].t = i;
- g->piece_queue[i].c = i + 1;
- memcpy(g->piece_queue[i].m, default_matrices[i], sizeof(piece_matrix));
- 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;
-
- /* Pieces should spawn so that on the first down
- * 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;
- }
-}
-
-void shuffle_queue(cetris_game* g) {
- for (u8 i = 0; i < 7; i++) {
- tetrimino t = g->piece_queue[i];
- u8 rand_index = rand() % 7;
- g->piece_queue[i] = g->piece_queue[rand_index];
- g->piece_queue[rand_index] = t;
- }
-}
-
-void update_game_tick(cetris_game* g) {
- if (g->game_over) return;
-
- g->tick++;
-
- if (g->next_piece_tick && g->tick >= g->next_piece_tick) {
- next_piece(g);
- }
-
- if (g->next_piece_tick) return;
-
- bool did_move = false;
- if (g->tick >= g->next_drop_tick || !g->next_drop_tick) {
- if (g->next_drop_tick) {
- move_current(g, DOWN);
- did_move = true;
- }
-
- if (g->level <= 20) {
- g->next_drop_tick = g->tick + level_drop_delay[g->level - 1];
- } else {
- g->next_drop_tick = g->tick + level_drop_delay[19];
- }
- }
-
- /* lock piece if it was hovering for CETRIS_LOCK_DELAY */
- 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) {
- lock_current(g);
- did_move = true;
- }
- g->current.pos.y--;
- g->current.lock_tick = 0;
- }
-
- if (handle_inputs(g)) {
- did_move = true;
- }
-
- if (did_move) update_board(g);
-}
-
-void next_piece(cetris_game* g) {
- g->next_drop_tick = 0;
- g->next_piece_tick = 0;
-
- g->current = g->piece_queue[g->current_index];
- if (check_matrix(g, &g->current.m) <= 0) {
- g->game_over = true;
- }
- g->current_index++;
-
- if (!g->game_over) {
- move_current(g, DOWN);
- }
-
- if (g->current_index >= 7) {
- g->current_index = 0;
- shuffle_queue(g);
- }
-
- update_board(g);
-}
-
-void lock_current(cetris_game* g) {
- g->current.locked = true;
- for (u8 x = 0; x < CETRIS_BOARD_X; x++) {
- for (u8 y = 0; y < CETRIS_BOARD_Y; y++) {
- if (g->board[x][y].occupied) g->board[x][y].constant = 1;
- }
- }
- update_board(g);
-}
-
-void make_ghosts(cetris_game* g) {
- u8 orig_y = g->current.pos.y;
- while (true) {
- g->current.pos.y++;
- if (check_matrix(g, &g->current.m) <= 0) {
- g->current.ghost_y = g->current.pos.y - 1;
- g->current.pos.y = orig_y;
- break;
- }
- }
-}
-
-void update_board(cetris_game* g) {
- if (g->game_over) return;
-
- u8 lines_cleared = 0;
- for (u8 y = 0; y < CETRIS_BOARD_Y; y++) {
- bool clear_line = true;
- for (u8 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].occupied || g->board[0][y].remove_tick > 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) {
- for (i8 s = y - 1; s >= 0; s--) {
- for (u8 x = 0; x < CETRIS_BOARD_X; x++) {
- g->board[x][s + 1] = g->board[x][s];
- }
- }
- }
- if (clear_line) {
- g->board[0][y].remove_tick = g->tick + CETRIS_LINE_CLEAR_DELAY;
- lines_cleared++;
- }
- }
-
- make_ghosts(g);
- set_matrix(g, &g->current.m);
-
- assert(lines_cleared <= 4);
-
- if (g->current.locked && !g->next_piece_tick) {
- if (lines_cleared > 0) {
- g->next_piece_tick = g->tick + CETRIS_NEXT_PIECE_DELAY;
- } else {
- next_piece(g);
- }
- }
-
- if (lines_cleared > 0 || g->tspin || g->mini_tspin) {
- add_score(g, lines_cleared);
- if (lines_cleared > 0) {
- g->lines += lines_cleared;
- if (g->lines >= (g->level * 10)) g->level++;
- }
- }
-}
-
-/* SCORE FUNCTIONS */
-
-void add_score(cetris_game* g, u8 lines) {
- if (!g->tspin && !g->mini_tspin) {
- switch (lines) {
- case 1: g->score += 100 * g->level; break;
- case 2: g->score += 300 * g->level; break;
- case 3: g->score += 500 * g->level; break;
- case 4: g->score += 800 * g->level; break;
- }
- } else if (g->tspin) {
- switch (lines) {
- case 0: g->score += 400 * g->level; break;
- case 1: g->score += 800 * g->level; break;
- case 2: g->score += 1200 * g->level; break;
- case 3: g->score += 1600 * g->level; break;
- }
- g->tspin = false;
- } else if (g->mini_tspin) {
- switch (lines) {
- case 0: g->score += 100 * g->level; break;
- case 1: g->score += 200 * g->level; break;
- case 2: g->score += 400 * g->level; break;
- }
- g->mini_tspin = false;
- }
-}
-
-/* MOVEMENT FUNCTIONS */
-
-void move_piece(cetris_game* g, input_t move, bool hold) {
- if (!g->held_moves[move]) {
- switch (move) {
- case LEFT:
- case RIGHT:
- case DOWN:
- case USER_DOWN:
- move_current(g, move);
- break;
- case HARD_DROP:
- hard_drop(g);
- break;
- case ROTATE_CW:
- rotate_matrix(g, 1);
- break;
- case ROTATE_CCW:
- rotate_matrix(g, 0);
- break;
- }
- }
- if (hold) g->held_moves[move] = true;
-}
-
-void stop_holding(cetris_game* g, input_t move) {
- g->held_moves[move] = false;
- if (move == RIGHT || move == LEFT) {
- g->das_move_tick = 0;
- g->das_repeat = 0;
- } else if (move == USER_DOWN) g->down_move_tick = 0;
-}
-
-void reset_tetrimino(tetrimino* t) {
- t->r = INIT;
- t->pos.x = 3;
- t->pos.y = (t->t == I) ? 17 : 16;
- t->ghost_y = 0;
-}
-
-void hold_piece(cetris_game* g) {
- if (g->piece_held) {
- tetrimino tmp = g->current;
- g->current = g->held;
- g->held = tmp;
- } else {
- g->held = g->current;
- reset_tetrimino(&g->held);
- g->piece_held = true;
- next_piece(g);
- }
- update_board(g);
-}
-
-
diff --git a/core/src/input.c b/core/src/input.c deleted file mode 100644 index 65dead1..0000000 --- a/core/src/input.c +++ /dev/null @@ -1,51 +0,0 @@ -#include <stdint.h>
-
-#include "input.h"
-
-#include "types.h"
-#include "matrix.h"
-#include "cetris.h"
-
-bool handle_inputs(cetris_game* g) {
- if ((g->held_moves[RIGHT] || g->held_moves[LEFT]) && !g->das_move_tick) {
- if (g->das_repeat == 0) {
- g->das_move_tick = g->tick + CETRIS_DAS_DELAY;
- } else if (g->das_repeat > 0) {
- g->das_move_tick = g->tick + CETRIS_DAS_PERIOD;
- }
- }
-
- if (g->held_moves[USER_DOWN] && !g->down_move_tick) {
- g->down_move_tick = g->tick + CETRIS_DROP_PERIOD;
- }
-
- bool did_move = false;
- if (g->das_move_tick && g->tick >= g->das_move_tick) {
- if (g->held_moves[RIGHT]) {
- if (g->prev_das_move == RIGHT || g->das_repeat == 0) g->das_repeat++;
- else g->das_repeat = 0;
- move_current(g, RIGHT);
- g->prev_das_move = RIGHT;
- }
-
- if (g->held_moves[LEFT]) {
- if (g->prev_das_move == LEFT || g->das_repeat == 0) g->das_repeat++;
- else g->das_repeat = 0;
- move_current(g, LEFT);
- g->prev_das_move = LEFT;
- }
-
- g->das_move_tick = 0;
- did_move = true;
- }
-
- if (g->down_move_tick && g->tick >= g->down_move_tick) {
- if (g->held_moves[USER_DOWN]) {
- move_current(g, USER_DOWN);
- did_move = true;
- }
-
- g->down_move_tick = 0;
- }
- return did_move;
-}
diff --git a/core/src/matrix.c b/core/src/matrix.c deleted file mode 100644 index d4597a7..0000000 --- a/core/src/matrix.c +++ /dev/null @@ -1,278 +0,0 @@ -#include <string.h>
-
-#include "matrix.h"
-#include "types.h"
-#include "cetris.h"
-
-/* SRS WALL KICK VALUES */
-
-// https://tetris.wiki/SRS
-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] = {
- { {0, 0}, {-2, 0}, {1, 0}, {-2,-1}, {1,2} }, // 0->R
- { {0, 0}, {2, 0}, {-1, 0}, {2,1}, {-1,-2} }, // R->0
- { {0, 0}, {-1, 0}, {2, 0}, {-1,2}, {2,-1} }, // R->2
- { {0, 0}, {1, 0}, {-2, 0}, {1,-2}, {-2,1} }, // 2->R
- { {0, 0}, {2, 0}, {-1, 0}, {2,1}, {-1,-2} }, // 2->L
- { {0, 0}, {-2, 0}, {1, 0}, {-2,-1}, {1,2} }, // L->2
- { {0, 0}, {1, 0}, {-2, 0}, {1,-2}, {-2,1} }, // L->0
- { {0, 0}, {-1, 0}, {2, 0}, {-1,2}, {2,-1} } // 0->L
-};
-
-/* DEFAULT MATRIX FOR EACH POSSIBLE TETRIMINO */
-
-const piece_matrix default_matrices[7] = {
- {
- { 0, 0, 0, 0 },
- { 0, 1, 1, 0 },
- { 0, 1, 1, 0 },
- { 0, 0, 0, 0 }
- },
-
- {
- { 0, 0, 0, 0 },
- { 1, 1, 1, 1 },
- { 0, 0, 0, 0 },
- { 0, 0, 0, 0 }
- },
-
- {
- { 0, 0, 0, 0 },
- { 0, 1, 1, 0 },
- { 1, 1, 0, 0 },
- { 0, 0, 0, 0 }
- },
-
- {
- { 0, 0, 0, 0 },
- { 1, 1, 0, 0 },
- { 0, 1, 1, 0 },
- { 0, 0, 0, 0 }
- },
-
- {
- { 0, 0, 0, 0 },
- { 0, 0, 1, 0 },
- { 1, 1, 1, 0 },
- { 0, 0, 0, 0 }
- },
-
- {
- { 0, 0, 0, 0 },
- { 1, 0, 0, 0 },
- { 1, 1, 1, 0 },
- { 0, 0, 0, 0 }
- },
-
- {
- { 0, 0, 0, 0 },
- { 0, 1, 0, 0 },
- { 1, 1, 1, 0 },
- { 0, 0, 0, 0 }
- }
-};
-
-/* MATRIX MODIFICATION */
-
-const vec2 basic_movements[5] = {
- {0, 0}, {0, 1}, {0, 1}, {1, 0}, {-1, 0} // NONE, DOWN, USER_DOWN, RIGHT, LEFT
-};
-
-void move_current(cetris_game* g, input_t move) {
- if (g->game_over || g->next_piece_tick) return;
-
- g->current.pos.y += basic_movements[move].y;
- g->current.pos.x += basic_movements[move].x;
-
- i8 check = check_matrix(g, &g->current.m);
- if (check <= 0) {
- g->current.pos.y -= basic_movements[move].y;
- g->current.pos.x -= basic_movements[move].x;
-
- if (move == USER_DOWN) g->score++;
- if (move == DOWN && check == -1 && !g->current.lock_tick) {
- g->current.lock_tick = g->tick + CETRIS_LOCK_DELAY;
- }
- }
-
- update_board(g);
-}
-
-i8 check_matrix(cetris_game* g, piece_matrix* m) {
- for (i8 y = 0; y < 4; y++) {
- for (i8 x = 0; x < 4; x++) {
- vec2 r = (vec2){x + g->current.pos.x, y + g->current.pos.y};
- if (r.y < 0) continue;
- if ((*m)[y][x]) {
- if (r.x >= CETRIS_BOARD_X || r.x < 0) 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) return -1;
- }
- }
- }
- return 1;
-}
-
-void set_matrix(cetris_game* g, piece_matrix* m) {
- for (i8 y = 0; y < 4; y++) {
- for (i8 x = 0; x < 4; x++) {
- vec2 r = (vec2){x + g->current.pos.x, y + g->current.pos.y};
- if ((*m)[y][x]) {
- if (r.y >= 0) {
- g->board[r.x][r.y].occupied = true;
- g->board[r.x][r.y].c = g->current.c;
- }
- 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;
- }
- }
- }
- }
- }
-}
-
-void hard_drop(cetris_game* g) {
- if (g->game_over || g->next_piece_tick) return;
-
- bool drop = false;
- u8 drop_count = 0;
- while (!drop) {
- g->current.pos.y++;
- drop_count++;
- if (check_matrix(g, &g->current.m) <= 0) {
- g->current.pos.y--;
- drop_count--;
- drop = true;
- }
- }
-
- g->score += 2 * drop_count; // 2 score for each hard-drop'd cell
-
- update_board(g);
- lock_current(g);
-}
-
-void rotate_matrix(cetris_game* g, bool clockwise) {
- if (g->game_over || g->next_piece_tick) return;
- if (g->current.t == O) return;
-
- rstate next = 0;
- u8 wall_kick = 0;
- switch (g->current.r) {
- case INIT:
- if (clockwise) {
- next = ONCE_RIGHT;
- wall_kick = 0;
- } else {
- next = ONCE_LEFT;
- wall_kick = 7;
- } break;
- case ONCE_RIGHT:
- if (clockwise) {
- next = TWICE;
- wall_kick = 2;
- } else {
- next = INIT;
- wall_kick = 1;
- } break;
- case ONCE_LEFT:
- if (clockwise) {
- next = INIT;
- wall_kick = 6;
- } else {
- next = TWICE;
- wall_kick = 5;
- } break;
- case TWICE:
- if (clockwise) {
- next = ONCE_LEFT;
- wall_kick = 4;
- } else {
- next = ONCE_RIGHT;
- wall_kick = 3;
- } break;
- }
-
- piece_matrix m;
- memset(m, 0, sizeof(piece_matrix));
-
- for (u8 x = 0; x < 4; x++) {
- for (u8 y = 0; y < 4; y++) {
- if (g->current.m[y][x]) {
- u8 new_x = (clockwise) ? 1 - (y - 2) : 1 + (y - 2);
- u8 new_y = (clockwise) ? 2 + (x - 1) : 2 - (x - 1);
-
- if (g->current.t == I) {
- if (clockwise) {
- new_y--;
- } else {
- new_x++;
- }
- }
-
- m[new_y][new_x] = 1;
- }
- }
- }
-
- vec2 kick;
- bool set_current = false;
- bool did_kick = false;
- for (u8 i = 0; i < 5; i++) {
- if (g->current.t == 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;
-
- if (check_matrix(g, &m) > 0) {
- set_current = true;
- if (i > 0) did_kick = true;
- break;
- } else {
- g->current.pos.x -= kick.x;
- g->current.pos.y -= kick.y;
- }
- }
-
- if (set_current) {
-
- /* check for tspin */
- if (g->current.t == T) {
- bool did_tspin = true;
- for (u8 i = 1; i < 5; i++) {
- g->current.pos.x += basic_movements[i].x;
- g->current.pos.y += basic_movements[i].y;
-
- if (check_matrix(g, &m) == 1) did_tspin = false;
-
- g->current.pos.x -= basic_movements[i].x;
- g->current.pos.y -= basic_movements[i].y;
- }
-
- if (did_tspin) {
- if (did_kick) g->mini_tspin = true;
- else g->tspin = true;
- }
- }
-
- g->current.r = next;
- memcpy(g->current.m, m, sizeof(piece_matrix));
- update_board(g);
- }
-}
diff --git a/core/src/test.c b/core/test.c index bad50d8..bad50d8 100644 --- a/core/src/test.c +++ b/core/test.c diff --git a/core/include/test.h b/core/test.h index 4b8622e..4b8622e 100644 --- a/core/include/test.h +++ b/core/test.h diff --git a/core/types.h b/core/types.h new file mode 100644 index 0000000..cf36792 --- /dev/null +++ b/core/types.h @@ -0,0 +1,10 @@ +#define u8 uint8_t +#define u32 uint32_t +#define u64 uint64_t +#define i8 int8_t +#define i32 int32_t + +typedef struct { + i8 x; + i8 y; +} vec2; diff --git a/frontends/curses/curses_ui.c b/frontends/curses/curses_ui.c index fb58e4d..8456438 100644 --- a/frontends/curses/curses_ui.c +++ b/frontends/curses/curses_ui.c @@ -47,12 +47,12 @@ " \\--------------------/"
#else
#define BLOCK "[]"
-#define PLAY_FIELD_STR " ┏━━━━━━━━━━━━━━━━━━━━┓ ┏━━━━━━━━━━━━━━━┓ \n"\
+#define PLAY_FIELD_STR " ┏━━━━━━━━━━━━━━━━━━━━┓ ┏━━━━━score━━━━━┓ \n"\
" ┃ ┃ ┃ ┃ \n"\
" ┃ ┃ ┗━━━━━━━━━━━━━━━┛ \n"\
" ┃ ┃ \n"\
" ┃ ┃ \n"\
- " ┃ ┃ ┏━━━━━━━━━━━┓ \n"\
+ " ┃ ┃ ┏━━━queue━━━┓ \n"\
" ┃ ┃ ┃ ┃ \n"\
" ┃ ┃ ┃ ┃ \n"\
" ┃ ┃ ┃ ┃ \n"\
@@ -212,19 +212,19 @@ int main(void) { if (is_paused) continue; // dont allow input if paused
switch (keys[i]) {
case KEY_LEFT:
- move_piece(&game, LEFT, false); break;
+ move_piece(&game, LEFT); break;
case KEY_RIGHT:
- move_piece(&game, RIGHT, false); break;
+ move_piece(&game, RIGHT); break;
case KEY_DOWN:
- move_piece(&game, DOWN, false); break;
+ move_piece(&game, USER_DOWN); break;
case KEY_UP:
case 'x':
- move_piece(&game, ROTATE_CW, false); break;
+ move_piece(&game, ROTATE_CW); break;
case '^':
case 'z':
- move_piece(&game, ROTATE_CCW, false); break;
+ move_piece(&game, ROTATE_CCW); break;
case ' ':
- move_piece(&game, HARD_DROP, false); break;
+ move_piece(&game, HARD_DROP); break;
case KEY_SLEFT:
case 'c':
hold_piece(&game); break;
diff --git a/frontends/curses/meson.build b/frontends/curses/meson.build index 8dd1d00..b254239 100644 --- a/frontends/curses/meson.build +++ b/frontends/curses/meson.build @@ -8,6 +8,7 @@ if host_machine.system() == 'windows' deps += compiler.find_library('pdcurses', dirs: meson.current_source_dir() + '/win')
else
deps += dependency('ncursesw')
+ deps += dependency('tinfow')
deps += dependency('threads')
endif
diff --git a/frontends/gl/main.c b/frontends/gl/main.c index 01da0c9..87cbd19 100644 --- a/frontends/gl/main.c +++ b/frontends/gl/main.c @@ -64,12 +64,12 @@ rbg_color colors[8] = { {0.255f,0.220f,0.0f} // Yellow
};
-struct block_drawable {
+typedef struct {
GLuint vao;
GLuint vbo;
GLuint ebo;
GLuint texture;
-};
+} drawable;
void framebuffer_size_callback(GLFWwindow* window, int width, int height) {
glViewport(0, 0, width, height);
@@ -113,7 +113,7 @@ void load_fragment_shader(GLuint program) { glDeleteShader(fragment_shader);
}
-void create_block(struct block_drawable *b) {
+void create_static_2d(drawable *b, int w, int h, char* texture_file) {
glGenVertexArrays(1, &b->vao);
glGenBuffers(1, &b->vbo);
glGenBuffers(1, &b->ebo);
@@ -124,6 +124,9 @@ void create_block(struct block_drawable *b) { glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, b->vbo);
+
+ GLfloat rect[32];
+ memcpy(&rect, &default_rect, sizeof(GLfloat) * 32);
glBufferData(GL_ARRAY_BUFFER, 32 * sizeof(GLfloat), default_rect, GL_DYNAMIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (void*)0);
@@ -135,10 +138,18 @@ void create_block(struct block_drawable *b) { glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (void*)(6 * sizeof(GLfloat)));
glEnableVertexAttribArray(2);
- load_texture("block.jpg", b->texture);
+ load_texture(texture_file, b->texture);
+}
+
+void calc_size(GLfloat *rect, int x, int y) {
+ rect[0] = rect[8] = (x + 1.0f) / 10.0f;
+ rect[1] = rect[25] = (((y) * -1.0f) + 1.0f) / 20.0f;
+ rect[9] = rect[17] = rect[1] - .05f;
+ rect[16] = rect[24] = rect[0] - .1f;
}
-void update_block(struct block_drawable *b, int x, int y, int color) {
+
+void update_block(drawable *b, int x, int y, int color) {
GLfloat block[32];
memcpy(block, default_rect, sizeof(GLfloat) * 32);
@@ -185,8 +196,12 @@ int main(void) { load_vertex_shader(shader_program);
glLinkProgram(shader_program);
- struct block_drawable block;
- create_block(&block);
+ drawable block;
+ create_static_2d(&block, 124, 124, "block.jpg");
+
+ drawable play_field;
+
+
cetris_game cetris;
init_game(&cetris);
diff --git a/frontends/gl/res/play_field.png b/frontends/gl/res/play_field.png Binary files differnew file mode 100644 index 0000000..dee673b --- /dev/null +++ b/frontends/gl/res/play_field.png diff --git a/frontends/gl/res/play_field_shake_1.png b/frontends/gl/res/play_field_shake_1.png Binary files differnew file mode 100644 index 0000000..4bbd0fb --- /dev/null +++ b/frontends/gl/res/play_field_shake_1.png diff --git a/frontends/gl/res/play_field_shake_2.png b/frontends/gl/res/play_field_shake_2.png Binary files differnew file mode 100644 index 0000000..a5d5c20 --- /dev/null +++ b/frontends/gl/res/play_field_shake_2.png diff --git a/frontends/gl/res/play_field_shake_3.png b/frontends/gl/res/play_field_shake_3.png Binary files differnew file mode 100644 index 0000000..e26c21e --- /dev/null +++ b/frontends/gl/res/play_field_shake_3.png diff --git a/frontends/gl/res/play_field_shake_4.png b/frontends/gl/res/play_field_shake_4.png Binary files differnew file mode 100644 index 0000000..399ecb8 --- /dev/null +++ b/frontends/gl/res/play_field_shake_4.png diff --git a/meson.build b/meson.build index d91a012..12d9788 100644 --- a/meson.build +++ b/meson.build @@ -12,7 +12,7 @@ if get_option('debug') == true endif
endif
-cetris_inc = include_directories('core/include')
+cetris_inc = include_directories('core')
subdir('core')
if get_option('curses-frontend') == true
|