pvjc25/a4/world.c
2025-05-02 19:35:19 +02:00

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;
}