Forked from https://github.com/tiehuis/2048-cli.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
163 lines
4.2 KiB
163 lines
4.2 KiB
#include <stdlib.h> |
|
#include <ncurses.h> |
|
#include <unistd.h> |
|
#include "gfx.h" |
|
#include "merge.h" |
|
#include <gettext.h> |
|
#include <locale.h> |
|
|
|
#define NUMBER_OF_COLORS 7 |
|
|
|
#define iterate(n, expression)\ |
|
do {\ |
|
int i;\ |
|
for (i = 0; i < n; ++i) { expression; }\ |
|
} while (0) |
|
|
|
struct gfx_state { |
|
WINDOW *window; |
|
size_t window_height, window_width; |
|
}; |
|
|
|
struct gfx_state* gfx_init(struct gamestate *g) |
|
{ |
|
initscr(); |
|
cbreak(); |
|
keypad(stdscr, true); |
|
noecho(); |
|
curs_set(FALSE); |
|
refresh(); |
|
|
|
struct gfx_state *s = malloc(sizeof(struct gfx_state)); |
|
if (!s) return NULL; |
|
|
|
s->window_height = g->opts->grid_height * (g->print_width + 2) + 3; |
|
s->window_width = g->opts->grid_width * (g->print_width + 2) + 1; |
|
s->window = newwin(s->window_height, s->window_width, 1, 1); |
|
keypad(s->window, TRUE); |
|
|
|
if (g->opts->enable_color && has_colors()) { |
|
start_color(); |
|
|
|
#ifdef INVERT_COLORS |
|
init_pair(1, COLOR_BLACK, COLOR_RED); |
|
init_pair(2, COLOR_BLACK, COLOR_GREEN); |
|
init_pair(3, COLOR_BLACK, COLOR_YELLOW); |
|
init_pair(4, COLOR_BLACK, COLOR_BLUE); |
|
init_pair(5, COLOR_BLACK, COLOR_MAGENTA); |
|
init_pair(6, COLOR_BLACK, COLOR_CYAN); |
|
init_pair(7, COLOR_BLACK, COLOR_WHITE); |
|
#else |
|
init_pair(1, COLOR_RED, COLOR_BLACK); |
|
init_pair(2, COLOR_GREEN, COLOR_BLACK); |
|
init_pair(3, COLOR_YELLOW, COLOR_BLACK); |
|
init_pair(4, COLOR_BLUE, COLOR_BLACK); |
|
init_pair(5, COLOR_MAGENTA, COLOR_BLACK); |
|
init_pair(6, COLOR_CYAN, COLOR_BLACK); |
|
init_pair(7, COLOR_WHITE, COLOR_BLACK); |
|
#endif |
|
} |
|
|
|
return s; |
|
} |
|
|
|
void gfx_draw(struct gfx_state *s, struct gamestate *g) |
|
{ |
|
if (g->score_last) |
|
mvwprintw(s->window, 0, 0, gettext("Score: %d (+%d)\n"), g->score, g->score_last); |
|
else |
|
mvwprintw(s->window, 0, 0, gettext("Score: %d\n"), g->score); |
|
|
|
if (g->score >= g->score_high) |
|
g->score_high = g->score; |
|
|
|
mvwprintw(s->window, 1, 0, gettext(" Hi: %d\n"), g->score_high); |
|
|
|
wattron(s->window, A_DIM); |
|
iterate(g->opts->grid_width * (g->print_width + 2) + 1, waddch(s->window, '-')); |
|
wattroff(s->window, A_DIM); |
|
|
|
int x, y, |
|
xpos = 0, |
|
ypos = 3; |
|
|
|
for (y = 0; y < g->opts->grid_height; ++y, ++ypos, xpos = 0) { |
|
wattron(s->window, A_DIM); |
|
mvwprintw(s->window, ypos, xpos++, "|"); |
|
wattroff(s->window, A_DIM); |
|
|
|
for (x = 0; x < g->opts->grid_width; ++x) { |
|
if (g->grid[x][y]) { |
|
wattron(s->window, COLOR_PAIR(g->grid[x][y] % NUMBER_OF_COLORS + 1)); |
|
mvwprintw(s->window, ypos, xpos, "%-*ld", g->print_width, merge_value(g->grid[x][y])); |
|
mvwprintw(s->window, ypos, xpos + g->print_width, " "); |
|
wattroff(s->window, COLOR_PAIR(g->grid[x][y] % NUMBER_OF_COLORS + 1)); |
|
|
|
wattron(s->window, A_DIM); |
|
mvwprintw(s->window, ypos, xpos + g->print_width + 1, "|"); |
|
wattroff(s->window, A_DIM); |
|
} |
|
else { |
|
wattron(s->window, A_DIM); |
|
iterate(g->print_width + 1, waddch(s->window, ' ')); |
|
waddch(s->window, '|'); |
|
wattroff(s->window, A_DIM); |
|
} |
|
|
|
xpos += (g->print_width + 2); |
|
} |
|
} |
|
|
|
wattron(s->window, A_DIM); |
|
iterate(g->opts->grid_height * (g->print_width + 2) + 1, waddch(s->window, '-')); |
|
wattroff(s->window, A_DIM); |
|
wrefresh(s->window); |
|
|
|
mvwprintw(s->window, 12, 0, "2048"); |
|
mvwprintw(s->window, 13, 0, "----"); |
|
|
|
mvwprintw(s->window, 15, 0, "Use WASD for direction"); |
|
mvwprintw(s->window, 16, 0, "Q to quit."); |
|
} |
|
|
|
int gfx_getch(struct gfx_state *s) |
|
{ |
|
int c = wgetch(s->window); |
|
|
|
/* Flush buffer */ |
|
nodelay(s->window, TRUE); |
|
while (wgetch(s->window) != ERR); |
|
nodelay(s->window, FALSE); |
|
|
|
switch (c) |
|
{ |
|
case KEY_UP: |
|
return INPUT_UP; |
|
break; |
|
case KEY_DOWN: |
|
return INPUT_DOWN; |
|
break; |
|
case KEY_RIGHT: |
|
return INPUT_RIGHT; |
|
break; |
|
case KEY_LEFT: |
|
return INPUT_LEFT; |
|
break; |
|
|
|
default: |
|
return c; |
|
break; |
|
|
|
} |
|
} |
|
|
|
void gfx_sleep(int ms) |
|
{ |
|
usleep(ms * 1000); |
|
} |
|
|
|
void gfx_destroy(struct gfx_state *s) |
|
{ |
|
free(s); |
|
endwin(); |
|
}
|
|
|