From bbe47075b6b56c7c6eb14b968a72cfb79d55d7bc Mon Sep 17 00:00:00 2001 From: John Tsiombikas Date: Mon, 11 Feb 2019 02:48:25 +0200 Subject: [PATCH] almost done. no line completion, scoring, and next-piece display yet --- src/game.c | 193 ++++++++++++++++++++++++++++++++++++++++++++++++---------- src/pieces.h | 10 ++- 2 files changed, 170 insertions(+), 33 deletions(-) diff --git a/src/game.c b/src/game.c index e8b47f3..0adc772 100644 --- a/src/game.c +++ b/src/game.c @@ -1,5 +1,7 @@ #include +#include #include +#include #include #include "game.h" #include "pieces.h" @@ -22,6 +24,8 @@ enum { G_CDOT = 0xf8 }; +enum { ERASE_PIECE, DRAW_PIECE }; + enum { BLACK, BLUE, GREEN, CYAN, RED, MAGENTA, YELLOW, WHITE }; /* dimensions of the whole screen */ @@ -33,19 +37,58 @@ enum { BLACK, BLUE, GREEN, CYAN, RED, MAGENTA, YELLOW, WHITE }; #define PF_COLS 10 /* offset of the playfield from the left side of the screen */ #define PF_XOFFS 2 +#define PF_YOFFS 0 #define CHAR(c, fg, bg) \ ((uint16_t)(c) | ((uint16_t)(fg) << 12) | ((uint16_t)(bg) << 8)) -uint16_t scr[SCR_COLS * SCR_ROWS]; +int scr[SCR_COLS * SCR_ROWS]; + +static int collision(int piece, const int *pos); +static void stick(int piece, const int *pos); +static void draw_piece(int piece, const int *pos, int rot, int mode); +static void drawbg(void); +static void wrtile(int tileid); + + +static int pos[2], next_pos[2]; +static int cur_piece = -1; +static int cur_rot, prev_rot; -static void wrchar(uint16_t c); +enum { + TILE_BLACK, + TILE_PF, + TILE_PFSEP, + TILE_IPIECE, + TILE_OPIECE, + TILE_JPIECE, + TILE_LPIECE, + TILE_SPIECE, + TILE_TPIECE, + TILE_ZPIECE +}; +#define FIRST_PIECE_TILE TILE_IPIECE + +static uint16_t tiles[][2] = { + { CHAR(' ', BLACK, BLACK), CHAR(' ', BLACK, BLACK) }, /* black tile */ + { CHAR(' ', WHITE, WHITE), CHAR(' ', WHITE, WHITE) }, /* playfield background */ + { CHAR(G_CHECKER, WHITE, BLACK), CHAR(G_CHECKER, WHITE, BLACK) }, /* well separator */ + { CHAR(' ', CYAN, CYAN), CHAR(' ', CYAN, CYAN) }, /* straight */ + { CHAR(' ', BLUE, BLUE), CHAR(' ', BLUE, BLUE) }, /* box */ + { CHAR(' ', GREEN, GREEN), CHAR(' ', GREEN, GREEN) }, /* J */ + { CHAR(' ', YELLOW, YELLOW), CHAR(' ', YELLOW, YELLOW) }, /* L */ + { CHAR(' ', MAGENTA, MAGENTA), CHAR(' ', MAGENTA, MAGENTA) }, /* S */ + { CHAR(' ', RED, BLACK), CHAR(' ', RED, BLACK) }, /* T */ + { CHAR(' ', RED, RED), CHAR(' ', RED, RED) }, /* Z */ +}; int init_game(void) { int i, j; - uint16_t *row = scr; + int *row = scr; + + srand(time(0)); tick_interval = 1000; @@ -54,23 +97,20 @@ int init_game(void) /* fill the screen buffer, and draw */ for(i=0; i PF_ROWS || j < PF_XOFFS - 1 || j > PF_XOFFS + PF_COLS) { - row[j] = CHAR(' ', WHITE, BLACK); + row[j] = TILE_BLACK; } else if((i == PF_ROWS && j >= PF_XOFFS && j < PF_XOFFS + PF_COLS) || j == PF_XOFFS - 1 || j == PF_XOFFS + PF_COLS) { - row[j] = CHAR(G_CHECKER, WHITE, BLACK); + row[j] = TILE_PFSEP; } else { - row[j] = CHAR(' ', BLACK, WHITE); + row[j] = TILE_PF; } - - wrchar(row[j]); } - row += SCR_COLS; } + + drawbg(); fflush(stdout); return 0; @@ -81,9 +121,6 @@ void cleanup_game(void) ansi_reset(); } -static int pos[2] = {0, PF_COLS / 2}; -static int next_pos[2] = {0, PF_COLS / 2}; - long update(long msec) { static long prev_tick; @@ -93,20 +130,30 @@ long update(long msec) /* fall */ while(dt >= tick_interval) { - next_pos[0] = (pos[0] + 1) % PF_ROWS; + if(cur_piece >= 0) { + next_pos[0] = pos[0] + 1; + if(collision(cur_piece, next_pos)) { + next_pos[0] = pos[0]; + fprintf(stderr, "stick at row %d col %d\n", pos[0], pos[1]); + stick(cur_piece, next_pos); + cur_piece = -1; + } + } else { + cur_piece = rand() % NUM_PIECES; + fprintf(stderr, "spawn: %d\n", cur_piece); + pos[0] = next_pos[0] = piece_spawnpos[cur_piece][0]; + pos[1] = next_pos[1] = PF_COLS / 2 + piece_spawnpos[cur_piece][1]; + } + dt -= tick_interval; prev_tick = msec; } - if(memcmp(pos, next_pos, sizeof pos) != 0) { - ansi_setcursor(pos[0], (PF_XOFFS + pos[1]) * 2); - wrchar(CHAR(' ', BLACK, WHITE)); - + if(cur_piece >= 0 && (memcmp(pos, next_pos, sizeof pos) != 0 || cur_rot != prev_rot)) { + draw_piece(cur_piece, pos, prev_rot, ERASE_PIECE); + draw_piece(cur_piece, next_pos, cur_rot, DRAW_PIECE); memcpy(pos, next_pos, sizeof pos); - ansi_setcursor(pos[0], (PF_XOFFS + pos[1]) * 2); - wrchar(CHAR(' ', RED, RED)); - - fflush(stdout); + prev_rot = cur_rot; } return tick_interval - dt; } @@ -119,14 +166,32 @@ void game_input(int c) break; case 'a': - if(pos[1] > 0) { - next_pos[1] = pos[1] - 1; + next_pos[1] = pos[1] - 1; + if(collision(cur_piece, next_pos)) { + next_pos[1] = pos[1]; } break; case 'd': - if(pos[1] < PF_COLS - 1) { - next_pos[1] = pos[1] + 1; + next_pos[1] = pos[1] + 1; + if(collision(cur_piece, next_pos)) { + next_pos[1] = pos[1]; + } + break; + + case 'w': + case ' ': + prev_rot = cur_rot; + cur_rot = (cur_rot + 1) & 3; + if(collision(cur_piece, next_pos)) { + cur_rot = prev_rot; + } + break; + + case 's': + next_pos[0] = pos[0] + 1; + if(collision(cur_piece, next_pos)) { + next_pos[0] = pos[0]; } break; @@ -135,11 +200,75 @@ void game_input(int c) } } -static void wrchar(uint16_t c) +static int collision(int piece, const int *pos) { - unsigned char cc = c & 0xff; - unsigned char ca = c >> 8; + int i; + unsigned char *p = pieces[piece][cur_rot]; + + for(i=0; i<4; i++) { + int x = PF_XOFFS + pos[1] + BLKX(*p); + int y = PF_YOFFS + pos[0] + BLKY(*p); + p++; - ansi_ibmchar(cc, ca); - ansi_ibmchar(cc, ca); + if(scr[y * SCR_COLS + x] != TILE_PF) return 1; + } + + return 0; +} + +static void stick(int piece, const int *pos) +{ + int i; + unsigned char *p = pieces[piece][cur_rot]; + + for(i=0; i<4; i++) { + int x = PF_XOFFS + pos[1] + BLKX(*p); + int y = PF_YOFFS + pos[0] + BLKY(*p); + p++; + + scr[y * SCR_COLS + x] = piece + FIRST_PIECE_TILE; + } +} + +static void draw_piece(int piece, const int *pos, int rot, int mode) +{ + int i; + int tile = mode == ERASE_PIECE ? TILE_PF : FIRST_PIECE_TILE + piece; + unsigned char *p = pieces[piece][rot]; + + for(i=0; i<4; i++) { + int x = PF_XOFFS + pos[1] + BLKX(*p); + int y = PF_YOFFS + pos[0] + BLKY(*p); + p++; + + ansi_setcursor(y, x * 2); + wrtile(tile); + } + fflush(stdout); +} + +static void drawbg(void) +{ + int i, j; + int *sptr = scr; + + for(i=0; i> 8; + + ansi_ibmchar(cc, ca); + } } diff --git a/src/pieces.h b/src/pieces.h index de396ec..e3a5c54 100644 --- a/src/pieces.h +++ b/src/pieces.h @@ -2,8 +2,12 @@ #define PIECES_H_ #define BLK(x, y) ((x) | ((y) << 4)) +#define BLKX(c) ((unsigned char)(c) & 0xf) +#define BLKY(c) ((unsigned char)(c) >> 4) -unsigned char pieces[][4][4] = { +#define NUM_PIECES 7 + +static unsigned char pieces[NUM_PIECES][4][4] = { /* straight piece */ { {BLK(0, 2), BLK(1, 2), BLK(2, 2), BLK(3, 2)}, @@ -55,5 +59,9 @@ unsigned char pieces[][4][4] = { } }; +static int piece_spawnpos[NUM_PIECES][2] = { + {-1, -2}, {-1, -3}, {-1, -2}, {-1, -2}, {-1, -2}, {-1, -2}, {-1, -2} +}; + #endif /* PIECES_H_ */ -- 1.7.10.4