From 718ba17bec26648f3b95ab20b03a2f5589b869af Mon Sep 17 00:00:00 2001 From: Oleksandr Hryshchenko Date: Sat, 17 Apr 2021 18:08:52 +0200 Subject: [PATCH] a4 --- a4/master.zip | Bin 0 -> 7522 bytes a4/world-master/.gitignore | 54 ++++++++++ a4/world-master/LICENSE | 29 ++++++ a4/world-master/Makefile | 14 +++ a4/world-master/README.md | 78 +++++++++++++++ a4/world-master/game.c | 150 ++++++++++++++++++++++++++++ a4/world-master/game.h | 33 +++++++ a4/world-master/main.c | 9 ++ a4/world-master/world.c | 198 +++++++++++++++++++++++++++++++++++++ a4/world-master/world.h | 113 +++++++++++++++++++++ 10 files changed, 678 insertions(+) create mode 100644 a4/master.zip create mode 100644 a4/world-master/.gitignore create mode 100644 a4/world-master/LICENSE create mode 100644 a4/world-master/Makefile create mode 100644 a4/world-master/README.md create mode 100644 a4/world-master/game.c create mode 100644 a4/world-master/game.h create mode 100644 a4/world-master/main.c create mode 100644 a4/world-master/world.c create mode 100644 a4/world-master/world.h diff --git a/a4/master.zip b/a4/master.zip new file mode 100644 index 0000000000000000000000000000000000000000..431ecccaedae7da5630ff813281e7627033f6926 GIT binary patch literal 7522 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 +#include +#include +#include "world.h" +#include "game.h" + +// Start is called one in the beginning +void* init_game(){ + // Allocate memory for the state + struct game* st = calloc(1,(sizeof(struct game))); + // Initialize state + for(int i = 0; i < MOUSE_COUNT; i++){ + st->mousex[i] = rand()%15; + st->mousey[i] = rand()%15; + st->mouse_state[i] = 0; + } + st->catx = 0; + st->caty = 0; + st->catx_position = 15; + st->caty_position = 15; + // Store pointer to the state to the world variable + return st; +} + +// Step is called in a loop once in interval. +// It should modify the state and draw it. +int game_event(struct event* event,void* game){ + // Get state pointer + struct game* state = game; + char msg[200]; + sprintf(msg,"%d",event->type); + set_message(msg,10,0); + if ( event->type == EVENT_ESC){ + // Non zero means finish the loop and stop the game. + return 1; + } + // Read game variable and update the eventstate + + // Is mouse caught ? + for (int i = 0; i < MOUSE_COUNT;i++){ + // Ak myška žije + if (state->mouse_state[i] == 0){ + // Ak mačka chytila myš + if (state->mousex[i] == state->catx_position && state->mousey[i] == state->caty_position){ + // Myška domyšila + // Nastavíme jej stav na "zjedená". + state->mouse_state[i] = 1; + } + } + } + //Are there nice left? + for(int i = 0; i < MOUSE_COUNT; i++){ + if(state->mouse_state[i] == 0){ + break; + } + else{ + if(i == MOUSE_COUNT-1){ + clear_screen(); + set_message("HAM", 12, 13); + return 0; + } + } + } + + if(event->type == EVENT_TIMEOUT) { + // Move cat + //state->catx_position += state->catx; + //state->caty_position += state->caty; + int cx = state->catx_position + state->catx; + int cy = state->caty_position + state->caty; + if (cx < 1 || cy < 0 || cx > event->width || cy > event->height){ + /*state->catx_position = cx; + state->caty_position = cy; + if(state->catx_position < 0){ + state->catx_position = 0; + } + else if(state->catx_position >= event->width){ + state->catx_position = event->width-1; + } + else if(state->caty_position < 0){ + state->caty_position = 0; + } + else if(state->caty_position >= event->height){ + state->caty_position = event->height-1; + }*/ + } + else { + state->catx_position = cx; + state->caty_position = cy; + } + + //state->catx_position += state->catx; + //state->caty_position += state->caty; + //state->caty_position += state->caty; + // random mouse movement + int m; + for(int i = 0; i < MOUSE_COUNT; i++){ + m = rand() % 4; + if (m == 0 && state->mousex[i] != 0){ + state->mousex[i] -= 1; + } + else if (m == 1 && state->mousex[i] < event->width){ + state->mousex[i] += 1; + } + else if (m == 2 && state->mousey[i] != 0){ + state->mousey[i] -= 1; + } + else if (m == 3 && state->mousey[i] < event->height){ + state->mousey[i] += 1; + } + } + //Je + } + else if (event->type == EVENT_KEY){ + // Move cat according to keyboard + if ( event->key == KEY_UP && state->caty_position > 0){ + state->catx = 0; + state->caty = -1; + } + else if ( event->key == KEY_DOWN && state->caty_position < event->height){ + state->catx = 0; + state->caty = 1; + } + else if ( event->key == KEY_LEFT && state->catx_position > 0){ + state->catx = -1; + state->caty = 0; + } + else if ( event->key == KEY_RIGHT && state->caty_position < event->width){ + state->catx = +1; + state->caty = 0; + } + } + // Draw world state + // + // Draw cat + clear_screen(); + set_color_cell('c',state->catx_position,state->caty_position,COLOR_YELLOW,COLOR_RED); + set_color_cell('-',state->catx_position-1,state->caty_position,COLOR_YELLOW,COLOR_GREEN); + //set_cell('c',state->catx_position,state->caty_position); + // Draw mouse + + for(int i = 0; i < MOUSE_COUNT; i++){ + if(state->mouse_state[i] != 1){ + set_cell('m', state->mousex[i], state->mousey[i]); + } + } + set_message( state->message,1,0); + return 0; +} + diff --git a/a4/world-master/game.h b/a4/world-master/game.h new file mode 100644 index 0000000..eab87ee --- /dev/null +++ b/a4/world-master/game.h @@ -0,0 +1,33 @@ +#ifndef _GAME_H_INCLUDE_ +#define _GAME_H_INCLUDE_ +#include "world.h" +#define MOUSE_COUNT 5 + +// Set of variables that expresses state of the game. +// +struct game { + // X speed of the cat + int catx; + // Y speed of the cat + int caty; + // X position of the cat + int catx_position; + // Y opsition of the cat + int caty_position; + // X position of the mouse + int mousex [MOUSE_COUNT]; + // Y position of the mouse + int mousey [MOUSE_COUNT]; + //State of each mouse + int mouse_state[MOUSE_COUNT]; + // Funky message + char message[100]; +}; + +// Returns pointer to newly allocated state +void* init_game(); + +// Changes world according to the game state (pressed key, screen size or other event) +int game_event(struct event* event,void* game); + +#endif diff --git a/a4/world-master/main.c b/a4/world-master/main.c new file mode 100644 index 0000000..0446027 --- /dev/null +++ b/a4/world-master/main.c @@ -0,0 +1,9 @@ +#include "game.h" +#include "world.h" +#include + + +int main(int argc, char** argv){ + start_world(init_game,game_event,free); + return 0; +} diff --git a/a4/world-master/world.c b/a4/world-master/world.c new file mode 100644 index 0000000..a45c109 --- /dev/null +++ b/a4/world-master/world.c @@ -0,0 +1,198 @@ +#include "world.h" +#include +#include +#include +#include +#include + +int TIMEOUT; + +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){ + sprintf(msg,"%s:: width %d is out of bounds (0,%d)",source,x,COLS); + abort_game(msg); + } + if (y < 0 || y >= LINES){ + sprintf(msg,"%s:: height %d is out of bounds (0,%d)",source,y,LINES); + abort_game(msg); + } +} + +void clear_screen(){ + // Clear screen + mvaddch(0,0,' '); + int screenchars = LINES*COLS; + for (int j = 1; j < screenchars;j++ ){ + 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 start_world(void* (*init_game)(),int (*world_event)(struct event* event,void* game),void (*destroy_game)(void*)){ + srand(time(NULL)); + int r = 1; + // Speed global variable + TIMEOUT = 100; + if (initscr() == NULL){ + // TODO Which Error? + puts("Curses Error."); + return -1; + } + noecho(); // Nevypisuj vstup na obrazovku + cbreak(); // Zabudni starý vstup + nodelay(stdscr,TRUE); // Nečakaj na stlačenie + keypad(stdscr,TRUE); // Aktivuje šípky + curs_set(FALSE); // Neviditeľný kurzor + /* Get all the mouse events */ + mousemask(ALL_MOUSE_EVENTS, NULL); + MEVENT mouse_event; + if (has_colors()){ // Zistenie či terminál podporuje farby + 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 colors!\n"); + } + void* game = NULL; + if (init_game != NULL){ + game = init_game(); + assert_message(game != NULL,"init_game:: should return non null pointer"); + } + timeout(TIMEOUT); + // Initial step + 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; + clock_t next_timeout = last_timeout + TIMEOUT; + event.time_ms = start_time; + // Start event + r = world_event(&event,game); + refresh(); + while (!r) { + memset(&event,0,sizeof(struct event)); + event.height = LINES; + event.width = COLS; + event.key = getch(); + // No key was pressed + if (event.key == ERR){ + event.type = EVENT_TIMEOUT; + last_timeout = clock(); + next_timeout = last_timeout + TIMEOUT; + } + // Mouse event + else if (event.key == KEY_MOUSE ){ + event.type = EVENT_MOUSE; + 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){ + int k = getch(); + if (k == -1){ + // Esc Was pressed + event.type = EVENT_ESC; + } + else { + // Alt was pressed + event.key = k; + event.alt_key = 1; + } + } + } + // Draw new world + event.time_ms = clock(); + r = world_event(&event,game); + refresh(); + event.time_ms = clock(); + // set new timeout + int nt = next_timeout - event.time_ms; + //printf("%d\n",nt); + if (nt > 0){ + timeout(nt); + } + else { + timeout(TIMEOUT); + next_timeout = event.time_ms + TIMEOUT; + } + } + memset(&event,0,sizeof(struct event)); + event.height = LINES; + event.width = COLS; + event.type = EVENT_END; + event.time_ms = clock(); + world_event(&event,game); + if (destroy_game != NULL){ + destroy_game(game); + } + endwin(); + return r; +}; diff --git a/a4/world-master/world.h b/a4/world-master/world.h new file mode 100644 index 0000000..73be057 --- /dev/null +++ b/a4/world-master/world.h @@ -0,0 +1,113 @@ +#ifndef _WORLD_H_ +#define _WORLD_H_ + +#include + +/** + * World represented as a rectangular matrix of colorful characters. + * + * Point [0,0] is displayed the upper left corner of the screen. + * + */ + +enum event_type { + EVENT_START, + EVENT_TIMEOUT, + EVENT_KEY, + EVENT_MOUSE, + EVENT_RESIZE, + EVENT_ESC, + EVENT_END, +}; + +struct event { + /** + * Last width of the screen. + */ + int width; + /** + * Last height of the screen. + */ + int height; + /** + * Last pressed key or Curses event. + * + * Special event values: + * ERR if timeout, + * KEY_RESIZE if screen resize + * KEY_EVENT, other event, + * KEY_MOUSE, mouse clicked + * + * Key values: + * + * ' ' Space + * KEY_DOWN Arrow down + * KEY_UP Arrow up + * KEY_LEFT Arrow left + * KEY_RIGHT Arrow right + * KEY_A1 Upper left of keypad + * KEY_A3 Upper right of keypad + * KEY_B2 Center of keypad + * KEY_C1 Lower left of keypad + * KEY_C3 Lower right of keypad + * + * KEY_ENTER + * KEY_BACKSPACE + */ + int key; + int alt_key; + enum event_type type; + int mouse_x; + int mouse_y; + int mouse_left; + int mouse_right; + int mouse_middle; + long int time_ms; +}; + +/** + * Sets cell to a state. + * @param event + * @param x coordinate of cell + * @param y coordinate of cell + * @param new state of the cell + */ +void set_cell(int character,int x,int y); + +/** + * COLOR_BLACK 0 + * COLOR_RED 1 + * COLOR_GREEN 2 + * COLOR_YELLOW 3 + * COLOR_BLUE 4 + * COLOR_MAGENTA 5 + * COLOR_CYAN 6 + * COLOR_WHITE 7 + */ + +#define COLOR_COUNT 8 + +void set_color_cell(int character,int x,int y,short front_color,short back_color); + + +/** + * + * @param event + * @param number of commandline arguments + * @param init_world + * @param destroy_world + * + * void init_world(struct event* w); + * Initializes user state. + * Free user state. + * @param event + */ + +int start_world(void* (*init_game)(),int (*world_event)(struct event* event,void* game),void (*destroy_game)(void* game)); + +void game_speed(int value); + +void set_message(const char* message,int x,int y); +void clear_screen(); + +#endif