refresh
This commit is contained in:
parent
8e44e30c67
commit
ea86d13e9f
91
a4/game.c
91
a4/game.c
@ -2,43 +2,92 @@
|
|||||||
#include "world.h"
|
#include "world.h"
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <string.h>
|
||||||
#include <ncurses.h>
|
#include <ncurses.h>
|
||||||
|
|
||||||
|
#define MOUSE_COUNT 5
|
||||||
|
|
||||||
void* init_game(void) {
|
void* init_game(void) {
|
||||||
struct game* obj = calloc(1, sizeof(struct game));
|
struct game* g = calloc(1, sizeof(struct game));
|
||||||
if (!obj) return NULL;
|
if (!g) return NULL;
|
||||||
|
|
||||||
obj->cat_x = 5;
|
g->cat_x = 5;
|
||||||
obj->cat_y = 3;
|
g->cat_y = 5;
|
||||||
obj->mouse_x = 20;
|
|
||||||
obj->mouse_y = 10;
|
|
||||||
obj->cat_dx = 1;
|
|
||||||
obj->cat_dy = 1;
|
|
||||||
snprintf(obj->message, sizeof(obj->message), "Лови меня, если сможешь!");
|
|
||||||
|
|
||||||
return obj;
|
for (int i = 0; i < MOUSE_COUNT; i++) {
|
||||||
|
g->mouse_x[i] = 10 + rand() % (COLS - 12);
|
||||||
|
g->mouse_y[i] = 2 + rand() % (LINES - 4);
|
||||||
|
g->mouse_alive[i] = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
g->caught = 0;
|
||||||
|
snprintf(g->message, sizeof(g->message), "Catch all mice (%d left)", MOUSE_COUNT);
|
||||||
|
return g;
|
||||||
}
|
}
|
||||||
|
|
||||||
int game_event(struct event* e, void* data) {
|
int game_event(struct event* e, void* state) {
|
||||||
struct game* g = (struct game*)data;
|
struct game* g = (struct game*)state;
|
||||||
|
if (!g) return 0;
|
||||||
|
|
||||||
if (e->type == EVENT_KEY) {
|
if (e->type == EVENT_KEY) {
|
||||||
if (e->key == KEY_UP) g->cat_y--;
|
if (e->key == KEY_UP) g->cat_y--;
|
||||||
if (e->key == KEY_DOWN) g->cat_y++;
|
if (e->key == KEY_DOWN) g->cat_y++;
|
||||||
if (e->key == KEY_LEFT) g->cat_x--;
|
if (e->key == KEY_LEFT) g->cat_x--;
|
||||||
if (e->key == KEY_RIGHT) g->cat_x++;
|
if (e->key == KEY_RIGHT) g->cat_x++;
|
||||||
}
|
}
|
||||||
|
|
||||||
g->mouse_x += (rand() % 3) - 1;
|
if (g->cat_x < 1) g->cat_x = 1;
|
||||||
g->mouse_y += (rand() % 3) - 1;
|
if (g->cat_y < 1) g->cat_y = 1;
|
||||||
|
if (g->cat_x >= COLS - 1) g->cat_x = COLS - 2;
|
||||||
|
if (g->cat_y >= LINES - 1) g->cat_y = LINES - 2;
|
||||||
|
|
||||||
if (g->cat_x == g->mouse_x && g->cat_y == g->mouse_y) {
|
for (int i = 0; i < MOUSE_COUNT; i++) {
|
||||||
snprintf(g->message, sizeof(g->message), "Поймал! Финита.");
|
if (!g->mouse_alive[i]) continue;
|
||||||
|
|
||||||
|
g->mouse_x[i] += (rand() % 3) - 1;
|
||||||
|
g->mouse_y[i] += (rand() % 3) - 1;
|
||||||
|
|
||||||
|
if (g->mouse_x[i] < 1) g->mouse_x[i] = 1;
|
||||||
|
if (g->mouse_y[i] < 1) g->mouse_y[i] = 1;
|
||||||
|
if (g->mouse_x[i] >= COLS - 1) g->mouse_x[i] = COLS - 2;
|
||||||
|
if (g->mouse_y[i] >= LINES - 1) g->mouse_y[i] = LINES - 2;
|
||||||
|
|
||||||
|
if (g->mouse_x[i] == g->cat_x && g->mouse_y[i] == g->cat_y) {
|
||||||
|
g->mouse_alive[i] = 0;
|
||||||
|
g->caught++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
clear_screen();
|
clear_screen();
|
||||||
set_cell('C', g->cat_x, g->cat_y);
|
|
||||||
set_cell('M', g->mouse_x, g->mouse_y);
|
box(stdscr, 0, 0);
|
||||||
|
|
||||||
|
set_color_cell('C', g->cat_x, g->cat_y, COLOR_CYAN, COLOR_BLACK);
|
||||||
|
|
||||||
|
for (int i = 0; i < MOUSE_COUNT; i++) {
|
||||||
|
if (g->mouse_alive[i]) {
|
||||||
|
set_color_cell('M', g->mouse_x[i], g->mouse_y[i], COLOR_RED, COLOR_BLACK);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (g->caught == MOUSE_COUNT) {
|
||||||
|
clear_screen();
|
||||||
|
box(stdscr, 0, 0);
|
||||||
|
const char* msg = "Congratulations! You won!";
|
||||||
|
int len = strlen(msg);
|
||||||
|
int cx = (COLS - len) / 2;
|
||||||
|
int cy = LINES / 2;
|
||||||
|
for (int i = 0; i < len; i++) {
|
||||||
|
set_color_cell(msg[i], cx + i, cy, COLOR_YELLOW, COLOR_BLACK);
|
||||||
|
}
|
||||||
|
refresh();
|
||||||
|
napms(4000);
|
||||||
|
endwin();
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
snprintf(g->message, sizeof(g->message), "Caught: %d / %d", g->caught, MOUSE_COUNT);
|
||||||
set_message(g->message, 2, 0);
|
set_message(g->message, 2, 0);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
16
a4/game.h
16
a4/game.h
@ -3,16 +3,20 @@
|
|||||||
|
|
||||||
#include "world.h"
|
#include "world.h"
|
||||||
|
|
||||||
|
#define MOUSE_COUNT 5
|
||||||
|
|
||||||
struct game {
|
struct game {
|
||||||
int cat_dx, cat_dy;
|
int cat_x;
|
||||||
int cat_x, cat_y;
|
int cat_y;
|
||||||
int mouse_x, mouse_y;
|
int mouse_x[MOUSE_COUNT];
|
||||||
int cat_dx_position, cat_dy_position;
|
int mouse_y[MOUSE_COUNT];
|
||||||
|
int mouse_alive[MOUSE_COUNT];
|
||||||
|
int caught;
|
||||||
char message[100];
|
char message[100];
|
||||||
};
|
};
|
||||||
|
|
||||||
void* init_game(void);
|
void* init_game();
|
||||||
int game_event(struct event* event, void* game);
|
int game_event(struct event* event, void* game);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
169
a4/world.c
169
a4/world.c
@ -7,129 +7,150 @@
|
|||||||
|
|
||||||
int TIMEOUT = 100;
|
int TIMEOUT = 100;
|
||||||
|
|
||||||
void abort_game(const char* message) {
|
void abort_game(const char* msg) {
|
||||||
endwin();
|
endwin();
|
||||||
puts(message);
|
puts(msg);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void check_bounds(const char* source, int x, int y) {
|
void check_bounds(const char* tag, int x, int y) {
|
||||||
char msg[200];
|
char err[256];
|
||||||
if (x < 0 || x >= COLS) {
|
if (x < 0 || x >= COLS) {
|
||||||
snprintf(msg, sizeof(msg), "%s: width %d is out of bounds (0,%d)", source, x, COLS);
|
snprintf(err, sizeof(err), "%s: x=%d out of screen (0,%d)", tag, x, COLS);
|
||||||
abort_game(msg);
|
abort_game(err);
|
||||||
}
|
}
|
||||||
if (y < 0 || y >= LINES) {
|
if (y < 0 || y >= LINES) {
|
||||||
snprintf(msg, sizeof(msg), "%s: height %d is out of bounds (0,%d)", source, y, LINES);
|
snprintf(err, sizeof(err), "%s: y=%d out of screen (0,%d)", tag, y, LINES);
|
||||||
abort_game(msg);
|
abort_game(err);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void clear_screen() {
|
void clear_screen() {
|
||||||
mvaddch(0, 0, ' ');
|
mvaddch(0, 0, ' ');
|
||||||
int screenchars = LINES * COLS;
|
for (int p = 1; p < COLS * LINES; p++) {
|
||||||
for (int i = 1; i < screenchars; i++) {
|
|
||||||
addch(' ');
|
addch(' ');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void game_speed(int value) {
|
void game_speed(int v) {
|
||||||
if (value < 0) {
|
if (v < 0) abort_game("negative speed?");
|
||||||
abort_game("world_seed:: cannot be negative\n");
|
TIMEOUT = v;
|
||||||
}
|
|
||||||
TIMEOUT = value;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void set_message(const char* message, int x, int y) {
|
void set_message(const char* msg, int x, int y) {
|
||||||
int l = strlen(message);
|
int n = strlen(msg);
|
||||||
for (int i = 0; i < l; i++) {
|
for (int i = 0; i < n; i++) {
|
||||||
check_bounds("set_message", x + i, y);
|
check_bounds("set_message", x + i, y);
|
||||||
set_cell(message[i], x + i, y);
|
set_cell(msg[i], x + i, y);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void assert_message(int event, const char* message) {
|
void assert_message(int ok, const char* msg) {
|
||||||
if (event == 0) {
|
if (!ok) abort_game(msg);
|
||||||
abort_game(message);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void set_cell(int character, int x, int y) {
|
void set_cell(int c, int x, int y) {
|
||||||
check_bounds("set_cell", x, y);
|
check_bounds("set_cell", x, y);
|
||||||
set_color_cell(character, x, y, COLOR_WHITE, COLOR_BLACK);
|
set_color_cell(c, x, y, COLOR_WHITE, COLOR_BLACK);
|
||||||
}
|
}
|
||||||
|
|
||||||
void set_color_cell(int character, int x, int y, short front_color, short back_color) {
|
void set_color_cell(int c, int x, int y, short fg, short bg) {
|
||||||
check_bounds("set_color_cell", x, y);
|
check_bounds("set_color_cell", x, y);
|
||||||
if (has_colors()) {
|
if (has_colors()) {
|
||||||
int pair = COLOR_COUNT * front_color + back_color;
|
int pair = COLOR_COUNT * fg + bg;
|
||||||
attron(COLOR_PAIR(pair));
|
attron(COLOR_PAIR(pair));
|
||||||
mvaddch(y, x, character);
|
mvaddch(y, x, c);
|
||||||
attroff(COLOR_PAIR(pair));
|
attroff(COLOR_PAIR(pair));
|
||||||
} else {
|
} else {
|
||||||
mvaddch(y, x, character);
|
mvaddch(y, x, c);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int world_run(void* (*init_game)(), int (*world_event)(struct event* event, void* game)) {
|
int world_run(void* (*init_game)(), int (*world_event)(struct event* e, void* g)) {
|
||||||
void* game = init_game();
|
void* game = init_game();
|
||||||
if (!game) {
|
if (!game) return -1;
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
timeout(TIMEOUT);
|
timeout(TIMEOUT);
|
||||||
struct event event;
|
|
||||||
memset(&event, 0, sizeof(struct event));
|
struct event ev;
|
||||||
event.height = LINES;
|
memset(&ev, 0, sizeof(ev));
|
||||||
event.width = COLS;
|
ev.height = LINES;
|
||||||
event.type = EVENT_START;
|
ev.width = COLS;
|
||||||
clock_t start_time = clock();
|
ev.type = EVENT_START;
|
||||||
clock_t last_timeout = start_time;
|
ev.time_ms = clock();
|
||||||
event.time_ms = start_time;
|
|
||||||
|
world_event(&ev, game);
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
memset(&event, 0, sizeof(struct event));
|
memset(&ev, 0, sizeof(ev));
|
||||||
event.height = LINES;
|
ev.height = LINES;
|
||||||
event.width = COLS;
|
ev.width = COLS;
|
||||||
event.type = EVENT_START;
|
ev.key = getch();
|
||||||
event.time_ms = clock();
|
|
||||||
|
|
||||||
world_event(&event, game);
|
if (ev.key == ERR) {
|
||||||
|
ev.type = EVENT_TIMEOUT;
|
||||||
if (event.key == ERR) {
|
} else if (ev.key == KEY_MOUSE) {
|
||||||
event.type = EVENT_TIMEOUT;
|
ev.type = EVENT_MOUSE;
|
||||||
last_timeout = clock();
|
MEVENT m;
|
||||||
event.time_ms = last_timeout + TIMEOUT;
|
if (getmouse(&m) == OK) {
|
||||||
} else if (event.key == KEY_MOUSE) {
|
ev.mouse_x = m.x;
|
||||||
event.type = EVENT_MOUSE;
|
ev.mouse_y = m.y;
|
||||||
MEVENT mouse_event;
|
if (m.bstate & BUTTON1_PRESSED) ev.mouse_left = 1;
|
||||||
if (getmouse(&mouse_event) == OK) {
|
if (m.bstate & BUTTON2_PRESSED) ev.mouse_middle = 1;
|
||||||
event.mouse_x = mouse_event.x;
|
if (m.bstate & BUTTON3_PRESSED) ev.mouse_right = 1;
|
||||||
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) {
|
} else if (ev.key == KEY_RESIZE) {
|
||||||
event.type = EVENT_RESIZE;
|
ev.type = EVENT_RESIZE;
|
||||||
} else {
|
} else {
|
||||||
event.type = EVENT_KEY;
|
ev.type = EVENT_KEY;
|
||||||
if (event.key == 27) { // ESC key
|
if (ev.key == 27) {
|
||||||
event.type = EVENT_ESC;
|
ev.type = EVENT_ESC;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
event.time_ms = clock();
|
ev.time_ms = clock();
|
||||||
world_event(&event, game);
|
world_event(&ev, game);
|
||||||
timeout(TIMEOUT);
|
timeout(TIMEOUT);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int start_world(void* (*init_game)(),
|
||||||
|
int (*world_event)(struct event*, void*),
|
||||||
|
void (*destroy_game)(void*)) {
|
||||||
|
initscr();
|
||||||
|
if (initscr() == NULL) {
|
||||||
|
puts("initscr failed");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
noecho();
|
||||||
|
cbreak();
|
||||||
|
keypad(stdscr, TRUE);
|
||||||
|
nodelay(stdscr, TRUE);
|
||||||
|
curs_set(0);
|
||||||
|
mousemask(ALL_MOUSE_EVENTS, NULL);
|
||||||
|
|
||||||
|
if (has_colors()) {
|
||||||
|
start_color();
|
||||||
|
for (int i = 0; i < COLOR_COUNT; i++) {
|
||||||
|
for (int j = 0; j < COLOR_COUNT; j++) {
|
||||||
|
init_pair(i * COLOR_COUNT + j, i, j);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
puts("No color support.");
|
||||||
|
}
|
||||||
|
|
||||||
|
int res = world_run(init_game, world_event);
|
||||||
|
|
||||||
|
if (destroy_game) {
|
||||||
|
void* g = init_game();
|
||||||
|
destroy_game(g);
|
||||||
|
}
|
||||||
|
|
||||||
|
endwin();
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user