136 lines
3.5 KiB
C
136 lines
3.5 KiB
C
#include "world.h"
|
|
#include "game.h"
|
|
#include <ncurses.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <time.h>
|
|
|
|
int TIMEOUT = 100;
|
|
|
|
void abort_game(const char* message) {
|
|
endwin();
|
|
puts(message);
|
|
exit(1);
|
|
}
|
|
|
|
void check_bounds(const char* source, int x, int y) {
|
|
char msg[200];
|
|
if (x < 0 || x >= COLS) {
|
|
snprintf(msg, sizeof(msg), "%s: width %d is out of bounds (0,%d)", source, x, COLS);
|
|
abort_game(msg);
|
|
}
|
|
if (y < 0 || y >= LINES) {
|
|
snprintf(msg, sizeof(msg), "%s: height %d is out of bounds (0,%d)", source, y, LINES);
|
|
abort_game(msg);
|
|
}
|
|
}
|
|
|
|
void clear_screen() {
|
|
mvaddch(0, 0, ' ');
|
|
int screenchars = LINES * COLS;
|
|
for (int i = 1; i < screenchars; i++) {
|
|
addch(' ');
|
|
}
|
|
}
|
|
|
|
void game_speed(int value) {
|
|
if (value < 0) {
|
|
abort_game("world_seed:: cannot be negative\n");
|
|
}
|
|
TIMEOUT = value;
|
|
}
|
|
|
|
void set_message(const char* message, int x, int y) {
|
|
int l = strlen(message);
|
|
for (int i = 0; i < l; i++) {
|
|
check_bounds("set_message", x + i, y);
|
|
set_cell(message[i], x + i, y);
|
|
}
|
|
}
|
|
|
|
void assert_message(int event, const char* message) {
|
|
if (event == 0) {
|
|
abort_game(message);
|
|
}
|
|
}
|
|
|
|
void set_cell(int character, int x, int y) {
|
|
check_bounds("set_cell", x, y);
|
|
set_color_cell(character, x, y, COLOR_WHITE, COLOR_BLACK);
|
|
}
|
|
|
|
void set_color_cell(int character, int x, int y, short front_color, short back_color) {
|
|
check_bounds("set_color_cell", x, y);
|
|
if (has_colors()) {
|
|
int pair = COLOR_COUNT * front_color + back_color;
|
|
attron(COLOR_PAIR(pair));
|
|
mvaddch(y, x, character);
|
|
attroff(COLOR_PAIR(pair));
|
|
} else {
|
|
mvaddch(y, x, character);
|
|
}
|
|
}
|
|
|
|
int world_run(void* (*init_game)(), int (*world_event)(struct event* event, void* game)) {
|
|
void* game = init_game();
|
|
if (!game) {
|
|
return -1;
|
|
}
|
|
|
|
timeout(TIMEOUT);
|
|
struct event event;
|
|
memset(&event, 0, sizeof(struct event));
|
|
event.height = LINES;
|
|
event.width = COLS;
|
|
event.type = EVENT_START;
|
|
clock_t start_time = clock();
|
|
clock_t last_timeout = start_time;
|
|
event.time_ms = start_time;
|
|
|
|
while (1) {
|
|
memset(&event, 0, sizeof(struct event));
|
|
event.height = LINES;
|
|
event.width = COLS;
|
|
event.type = EVENT_START;
|
|
event.time_ms = clock();
|
|
|
|
world_event(&event, game);
|
|
|
|
if (event.key == ERR) {
|
|
event.type = EVENT_TIMEOUT;
|
|
last_timeout = clock();
|
|
event.time_ms = last_timeout + TIMEOUT;
|
|
} else if (event.key == KEY_MOUSE) {
|
|
event.type = EVENT_MOUSE;
|
|
MEVENT mouse_event;
|
|
if (getmouse(&mouse_event) == OK) {
|
|
event.mouse_x = mouse_event.x;
|
|
event.mouse_y = mouse_event.y;
|
|
if (mouse_event.bstate & BUTTON1_PRESSED) {
|
|
event.mouse_left = 1;
|
|
}
|
|
if (mouse_event.bstate & BUTTON2_PRESSED) {
|
|
event.mouse_middle = 1;
|
|
}
|
|
if (mouse_event.bstate & BUTTON3_PRESSED) {
|
|
event.mouse_right = 1;
|
|
}
|
|
}
|
|
} else if (event.key == KEY_RESIZE) {
|
|
event.type = EVENT_RESIZE;
|
|
} else {
|
|
event.type = EVENT_KEY;
|
|
if (event.key == 27) { // ESC key
|
|
event.type = EVENT_ESC;
|
|
}
|
|
}
|
|
|
|
event.time_ms = clock();
|
|
world_event(&event, game);
|
|
timeout(TIMEOUT);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|