X-Git-Url: http://git.mutantstargoat.com/user/nuclear/?p=ansitris;a=blobdiff_plain;f=src%2Fgame.c;h=1ab330bcc7888dbf67030e7e3a350fc34fe7cce5;hp=f1622aaf8f3264c0ab93e57955a629b26b692ce7;hb=89a2e7ae300a4cabbb308b5ec2b83ee539fdd07c;hpb=f71c261ce691d78fccb3f377ae5299edbf0e0062 diff --git a/src/game.c b/src/game.c index f1622aa..1ab330b 100644 --- a/src/game.c +++ b/src/game.c @@ -1,4 +1,7 @@ #include +#include +#include +#include #include #include "game.h" #include "pieces.h" @@ -21,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 */ @@ -32,41 +37,80 @@ 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 void wrchar(uint16_t c); + +static int pos[2], next_pos[2]; +static int cur_piece = -1; +static int cur_rot, prev_rot; + +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; ansi_clearscr(); + ansi_cursor(0); /* 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; @@ -77,25 +121,243 @@ void cleanup_game(void) ansi_reset(); } -void proc_input(void) +long update(long msec) { - int c = fgetc(stdin); + static long prev_tick; + long dt; + + dt = msec - prev_tick; + + /* fall */ + while(dt >= tick_interval) { + 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; + return 0; + } + } else { + cur_piece = rand() % NUM_PIECES; + prev_rot = cur_rot = 0; + fprintf(stderr, "spawn: %d\n", cur_piece); + pos[0] = piece_spawnpos[cur_piece][0]; + next_pos[0] = pos[0] + 1; + pos[1] = next_pos[1] = PF_COLS / 2 + piece_spawnpos[cur_piece][1]; + } + + dt -= tick_interval; + prev_tick = msec; + } + + 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); + prev_rot = cur_rot; + } + return tick_interval - dt; +} + + +#define C0 0x9b +#define SS3 0x8f + +static void runesc(int csi, char *buf) +{ + if(csi != C0) return; + + if(buf[1] == 0) { + switch(buf[0]) { + case 'A': + game_input('w'); /* up */ + break; + case 'B': + game_input('s'); /* down */ + break; + case 'C': + game_input('d'); /* right */ + break; + case 'D': + game_input('a'); /* left */ + break; + default: + break; + } + } +} + +void game_input(int c) +{ + static int esc, csi; + static int esctop; + static char escbuf[64]; + + if(esc) { + esc = 0; + if(c == 27) { + quit = 1; + return; + } + + switch(c) { + case '[': + csi = C0; + return; + case 'O': + csi = SS3; + return; + default: + break; + } + } + + if(csi) { + if(c < 0x20 || c >= 0x80) { + csi = 0; + esctop = 0; + } + + escbuf[esctop++] = c; + + if(c >= 0x40) { + int prevcsi = csi; + escbuf[esctop] = 0; + csi = 0; + esctop = 0; + runesc(prevcsi, escbuf); + } + return; + } switch(c) { case 27: + esc = 1; + break; + + case C0: + esc = 1; + csi = C0; + break; + + case 'q': quit = 1; break; + case 'a': + next_pos[1] = pos[1] - 1; + if(collision(cur_piece, next_pos)) { + next_pos[1] = pos[1]; + } + break; + + case 'd': + 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; + default: + fprintf(stderr, "unhandled input: %x\n", c); break; } } -static void wrchar(uint16_t c) +static int collision(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++; + + 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; + } + + if(use_bell) { + putchar('\a'); + fflush(stdout); + } +} + +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++; + + if(y < 0) continue; + + ansi_setcursor(y, x * 2); + wrtile(tile); + } + fflush(stdout); +} + +static void drawbg(void) +{ + int i, j; + int *sptr = scr; + + for(i=0; i> 8; + int i; + + for(i=0; i<2; i++) { + uint16_t c = tiles[tileid][i]; + unsigned char cc = c & 0xff; + unsigned char ca = c >> 8; - ansi_ibmchar(cc, ca); - ansi_ibmchar(cc, ca); + ansi_ibmchar(cc, ca); + } }