X-Git-Url: http://git.mutantstargoat.com/user/nuclear/?p=ansitris;a=blobdiff_plain;f=src%2Fgame.c;h=0adc772e1cb1b5af9ba2fec4eda30b2399c178ed;hp=f1622aaf8f3264c0ab93e57955a629b26b692ce7;hb=bbe47075b6b56c7c6eb14b968a72cfb79d55d7bc;hpb=f71c261ce691d78fccb3f377ae5299edbf0e0062 diff --git a/src/game.c b/src/game.c index f1622aa..0adc772 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,154 @@ 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; + } + } 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(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; +} + +void game_input(int c) +{ switch(c) { case 27: 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: 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; + } +} + +static void draw_piece(int piece, const int *pos, int rot, int mode) { - unsigned char cc = c & 0xff; - unsigned char ca = c >> 8; + int i; + int tile = mode == ERASE_PIECE ? TILE_PF : FIRST_PIECE_TILE + piece; + unsigned char *p = pieces[piece][rot]; - ansi_ibmchar(cc, ca); - ansi_ibmchar(cc, ca); + 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); + } }