printf("\033[%d;%dH", row + 1, col + 1);
}
+void ansi_cursor(int show)
+{
+ printf("\033[?25%c", show ? 'h' : 'l');
+ fflush(stdout);
+}
+
void ansi_ibmchar(unsigned char c, unsigned char attr)
{
char cmd[32];
void ansi_clearscr(void);
void ansi_setcursor(int row, int col);
+void ansi_cursor(int show);
/* convert a PC cga/ega/vga char+attr to an ANSI sequence and write it to stdout */
void ansi_ibmchar(unsigned char c, unsigned char attr);
#include <stdio.h>
+#include <string.h>
#include <inttypes.h>
#include "game.h"
#include "pieces.h"
int i, j;
uint16_t *row = scr;
+ tick_interval = 1000;
+
ansi_clearscr();
+ ansi_cursor(0);
/* fill the screen buffer, and draw */
for(i=0; i<SCR_ROWS; i++) {
ansi_reset();
}
-void proc_input(void)
+static int pos[2] = {0, PF_COLS / 2};
+static int next_pos[2] = {0, PF_COLS / 2};
+
+long update(long msec)
{
- int c = fgetc(stdin);
+ static long prev_tick;
+ long dt;
+
+ dt = msec - prev_tick;
+
+ /* fall */
+ while(dt >= tick_interval) {
+ next_pos[0] = (pos[0] + 1) % PF_ROWS;
+ 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));
+
+ memcpy(pos, next_pos, sizeof pos);
+ ansi_setcursor(pos[0], (PF_XOFFS + pos[1]) * 2);
+ wrchar(CHAR(' ', RED, RED));
+
+ fflush(stdout);
+ }
+ return tick_interval - dt;
+}
+
+void game_input(int c)
+{
switch(c) {
case 27:
quit = 1;
break;
+ case 'a':
+ if(pos[1] > 0) {
+ next_pos[1] = pos[1] - 1;
+ }
+ break;
+
+ case 'd':
+ if(pos[1] < PF_COLS - 1) {
+ next_pos[1] = pos[1] + 1;
+ }
+ break;
+
default:
break;
}
#define GAME_H_
int quit;
+long tick_interval;
int init_game(void);
void cleanup_game(void);
-void proc_input(void);
+long update(long msec);
+void game_input(int c);
#endif /* GAME_H_ */
#include <fcntl.h>
#include <termios.h>
#include <sys/stat.h>
+#include <sys/select.h>
+#include <sys/time.h>
#include "game.h"
int init(void);
void cleanup(void);
+long get_msec(void);
-const char *termfile = "/dev/tty";
-struct termios saved_term;
+static const char *termfile = "/dev/tty";
+static struct termios saved_term;
+static struct timeval tv0;
int main(int argc, char **argv)
{
+ int res, c;
+ long msec, next;
+ struct timeval tv;
+
if(argc > 1) {
termfile = argv[1];
}
return 1;
}
+ gettimeofday(&tv0, 0);
+
+ tv.tv_sec = tick_interval / 1000;
+ tv.tv_usec = (tick_interval % 1000) * 1000;
+
for(;;) {
- proc_input();
- if(quit) break;
+ fd_set rdset;
+ FD_ZERO(&rdset);
+ FD_SET(0, &rdset);
+
+ while((res = select(1, &rdset, 0, 0, &tv)) == -1 && errno == EINTR);
+
+ if(res > 0 && FD_ISSET(0, &rdset)) {
+ while((c = fgetc(stdin)) >= 0) {
+ game_input(c);
+ if(quit) goto end;
+ }
+ }
+
+ msec = get_msec();
+ next = update(msec);
+
+ tv.tv_sec = next / 1000;
+ tv.tv_usec = (next % 1000) * 1000;
}
+end:
cleanup();
return 0;
}
int fd;
struct termios term;
- if((fd = open(termfile, O_RDWR)) == -1) {
+ if((fd = open(termfile, O_RDWR | O_NONBLOCK)) == -1) {
fprintf(stderr, "failed to open terminal device: %s: %s\n", termfile, strerror(errno));
return -1;
}
cleanup_game();
tcsetattr(0, TCSAFLUSH, &saved_term);
}
+
+long get_msec(void)
+{
+ struct timeval tv;
+
+ gettimeofday(&tv, 0);
+
+ return (tv.tv_sec - tv0.tv_sec) * 1000 + (tv.tv_usec - tv0.tv_usec) / 1000;
+}