diff options
author | scratko <m@scratko.xyz> | 2024-04-17 17:00:48 +0300 |
---|---|---|
committer | scratko <m@scratko.xyz> | 2024-04-17 18:33:03 +0300 |
commit | ef3844bf2128fa82f20c5995d1fca66fadba2ce3 (patch) | |
tree | 905048a285a8cd8fd6a070ce3b6c075e9681e59a | |
parent | 194f71c150eb9ee696acca17176092e8b0ce6e4f (diff) | |
download | pacman-ef3844bf2128fa82f20c5995d1fca66fadba2ce3.tar.gz pacman-ef3844bf2128fa82f20c5995d1fca66fadba2ce3.tar.bz2 pacman-ef3844bf2128fa82f20c5995d1fca66fadba2ce3.zip |
Added colors
Changed the number of pacman's lives.
Fixed clear_or_revert_symbol().
Target hit display.
Changed ghost initialization.
Clearing ghost positions is moved to the function.
Added flag in struct ghost_type (reached_pacman).
Changed catching stage.
Now eating an energizer resets the counter.
-rw-r--r-- | Makefile | 2 | ||||
-rw-r--r-- | color_palette.c | 69 | ||||
-rw-r--r-- | color_palette.h | 15 | ||||
-rw-r--r-- | field.c | 112 | ||||
-rw-r--r-- | field.h | 10 | ||||
-rw-r--r-- | ghosts.c | 46 | ||||
-rw-r--r-- | ghosts.h | 7 | ||||
-rw-r--r-- | pac.c | 5 | ||||
-rw-r--r-- | pac.h | 2 | ||||
-rw-r--r-- | pacman.c | 72 |
10 files changed, 266 insertions, 74 deletions
@@ -1,4 +1,4 @@ -SRCMODULES = field.c ghosts.c pac.c queue.c pacman.c +SRCMODULES = field.c ghosts.c pac.c queue.c color_palette.c pacman.c OBJMODULES = $(SRCMODULES:.c=.o) CC = gcc CFLAGS = -Wall -g -c -D DEBUG diff --git a/color_palette.c b/color_palette.c new file mode 100644 index 0000000..e839e8b --- /dev/null +++ b/color_palette.c @@ -0,0 +1,69 @@ +#include "color_palette.h" +#include <ncurses.h> + +void set_pairs() +{ + init_pair(2, COLOR_BLUE, COLOR_BLUE); + init_pair(3, COLOR_YELLOW, COLOR_BLACK); + init_pair(4, COLOR_MAGENTA, COLOR_MAGENTA); + init_pair(5, COLOR_YELLOW, COLOR_BLACK); + init_pair(6, COLOR_RED, COLOR_BLACK); + init_pair(7, COLOR_BLUE, COLOR_BLACK); + init_pair(8, COLOR_MAGENTA, COLOR_BLACK); +} + +void paint_field_element(int element) +{ + int color; + switch(element) { + case block: + color = COLOR_PAIR(2); + break; + case coin: + color = COLOR_PAIR(3) | A_BOLD; + break; + case door: + color = COLOR_PAIR(4); + break; + } + attrset(color); +} + +void paint_stats() +{ + attrset(COLOR_PAIR(5)); +} + +void paint_ghost(enum ghost_color color, int blink) +{ + int attr; + switch(color) { + case red: + attr = COLOR_PAIR(6); + break; + case pink: + attr = COLOR_PAIR(8); + break; + case blue: + attr = COLOR_PAIR(7); + break; + case orange: + attr = COLOR_PAIR(3); + } + attrset(attr); +} + +void paint_pac() +{ + attrset(COLOR_PAIR(3) | A_BOLD); +} + +void paint_hit() +{ + attrset(COLOR_PAIR(6)); +} + +void reset_attr() +{ + attrset(A_NORMAL); +} diff --git a/color_palette.h b/color_palette.h new file mode 100644 index 0000000..81ccce8 --- /dev/null +++ b/color_palette.h @@ -0,0 +1,15 @@ +#ifndef COLOR_PALETTE_H_SENTRY +#define COLOR_PALETTE_H_SENTRY + +#include "field.h" +#include "ghosts.h" + +void set_pairs(); +void paint_field_element(int element); +void paint_stats(); +void paint_ghost(enum ghost_color color, int blink); +void paint_pac(); +void paint_hit(); +void reset_attr(); + +#endif @@ -3,6 +3,7 @@ #include "queue.h" #include <ncurses.h> #include <stdlib.h> +#include "color_palette.h" static const char field_sample[field_height][field_width] = { {"////////////////////////////"}, @@ -34,7 +35,7 @@ static const char field_sample[field_height][field_width] = { {"/.//////////.//.//////////./"}, {"/1..........2..2..........1/"}, {"////////////////////////////"}, - {" C C C Score: "} + {" C C Score: "} }; static void copy_field(game_space field) @@ -107,6 +108,7 @@ void print_field(game_space field) symbol = field[i][j]; move(i, j); if(is_coin_symbol(symbol, j, i) && field_has_coin(j, i)) { + paint_field_element(coin); symbol == energizer ? addch('*') : addch('.'); continue; } @@ -114,23 +116,31 @@ void print_field(game_space field) case one_path: case two_paths: case yellow_block: + reset_attr(); addch(' '); break; case block: - addch('/'); + paint_field_element(block); + addch(' '); break; +#if 0 case energizer: addch('*'); break; +#endif case door: - addch('#'); + paint_field_element(door); + addch(' '); break; case ' ': + reset_attr(); addch(' '); break; } - if(i == field_height-1) + if(i == field_height-1) { + symbol != ' ' ? paint_stats() : reset_attr(); addch(symbol); + } refresh(); } } @@ -139,6 +149,8 @@ void print_field(game_space field) void display_character(int y, int x, enum select_character symbol) { move(y, x); + if(symbol == pac_char) + paint_pac(); addch(symbol); refresh(); } @@ -148,11 +160,15 @@ void display_ghosts_on_field(struct ghost_type *red_ghost, struct ghost_type *blue_ghost, struct ghost_type *orange_ghost) { + paint_ghost(red_ghost->color, red_ghost->frightened_status); display_character(red_ghost->position.y, red_ghost->position.x, ghost_char); + paint_ghost(pink_ghost->color, pink_ghost->frightened_status); display_character(pink_ghost->position.y, pink_ghost->position.x, ghost_char); + paint_ghost(blue_ghost->color, blue_ghost->frightened_status); display_character(blue_ghost->position.y, blue_ghost->position.x, ghost_char); + paint_ghost(orange_ghost->color, orange_ghost->frightened_status); display_character(orange_ghost->position.y, orange_ghost->position.x, ghost_char); } @@ -160,13 +176,14 @@ void display_ghosts_on_field(struct ghost_type *red_ghost, void display_score(int value) { move(field_height-1, 25); + paint_stats(); printw("%d", value); refresh(); } void clear_or_revert_symbol(const game_space field, struct coordinates position, enum select_character character, - struct queue *eaten_coins) + const struct queue *eaten_coins) { int x, y; x = position.x; @@ -174,40 +191,44 @@ void clear_or_revert_symbol(const game_space field, struct coordinates position, int symbol = field[y][x]; move(y, x); if(character == ghost_char) { + if(is_coin_symbol(symbol, x, y) && field_has_coin(x, y) && + !queue_consists_point(eaten_coins, position)) { + if(symbol == energizer && field_has_energizer(field, x, y)) { + paint_field_element(coin); + addch('*'); + } else { + paint_field_element(coin); + addch('.'); + } + refresh(); + return; + } switch(symbol) { case one_path: case two_paths: case three_paths: - if(field_has_coin(x, y)) - queue_consists_point(eaten_coins, position) ? - addch(' ') : addch('.'); - else - addch(' '); - break; case yellow_block: - if(yellow_block_contains_coin(x, y)) - queue_consists_point(eaten_coins, position) ? - addch(' ') : addch('.'); - else - addch(' '); + reset_attr(); + addch(' '); + break; + case coin: + reset_attr(); + addch(' '); break; case door: + paint_field_element(door); addch('#'); break; - case energizer: - field_has_energizer(field, x, y) ? addch('*') : addch(' '); - break; - case coin: - queue_consists_point(eaten_coins, position) ? - addch(' ') : addch('.'); - break; case ' ': + reset_attr(); addch(' '); break; } } - else if(character == pac_char) + else if(character == pac_char) { + reset_attr(); addch(' '); + } refresh(); } @@ -288,25 +309,54 @@ int is_equal_points(struct coordinates first_point, struct coordinates void erase_life(int value) { enum { - two_lives_left = 2, one_life_left = 1, no_lives_left = 0, gap = 2, - three_lives_x = 5 + two_lives_x = 3 }; int x, y; y = field_height - 1; switch(value) { - case two_lives_left: - x = three_lives_x; - break; case one_life_left: - x = three_lives_x - gap; + x = two_lives_x; break; case no_lives_left: - x = three_lives_x - gap * 2; + x = two_lives_x - gap; } move(y, x); + reset_attr(); + addch(' '); + refresh(); +} + +void display_hit(struct coordinates pac_position, + const struct ghost_type *red_ghost, + const struct ghost_type *pink_ghost, + const struct ghost_type *blue_ghost, + const struct ghost_type *orange_ghost) +{ + struct coordinates ghost_position; + if(red_ghost->reached_pacman) + ghost_position = red_ghost->position; + else if(pink_ghost->reached_pacman) + ghost_position = pink_ghost->position; + else if(blue_ghost->reached_pacman) + ghost_position = blue_ghost->position; + else + ghost_position = orange_ghost->position; + reset_attr(); + move(ghost_position.y, ghost_position.x); + addch(' '); + paint_hit(); + move(pac_position.y, pac_position.x); + addch('X'); + refresh(); +} + +void erase_hit(struct coordinates point) +{ + move(point.y, point.x); + reset_attr(); addch(' '); refresh(); } @@ -45,12 +45,17 @@ void display_ghosts_on_field(struct ghost_type *red_ghost, struct ghost_type *blue_ghost, struct ghost_type *orange_ghost); void display_score(int value); +struct coordinates; +void display_hit(struct coordinates pac_position, + const struct ghost_type *red_ghost, + const struct ghost_type *pink_ghost, + const struct ghost_type *blue_ghost, + const struct ghost_type *orange_ghost); struct queue; -struct coordinates; void clear_or_revert_symbol(game_space field, struct coordinates position, enum select_character character, - struct queue *eaten_coins); + const struct queue *eaten_coins); enum intersection_type get_intersection(const game_space field, struct ghost_type *ghost); @@ -75,5 +80,6 @@ int is_equal_points(struct coordinates first_point, struct coordinates void clear_field(game_space field); void erase_life(int value); +void erase_hit(struct coordinates point); #endif @@ -17,13 +17,8 @@ void initialize_ghost(struct ghost_type *ghost, enum ghost_color color) ghost->home_position.y = red_home_y; ghost->home_position.x = red_home_x; ghost->color = red; - ghost->frightened_status = 0; - ghost->direction = none; ghost->prison_params.position.x = red_prison_x; ghost->prison_params.position.y = red_prison_y; - ghost->prison_params.prison_counter = 0; - ghost->prison_params.active = 0; - ghost->capture_info.status = 0; break; case pink: ghost->position.y = pink_y; @@ -31,13 +26,8 @@ void initialize_ghost(struct ghost_type *ghost, enum ghost_color color) ghost->home_position.y = pink_home_y; ghost->home_position.x = pink_home_x; ghost->color = pink; - ghost->frightened_status = 0; - ghost->direction = none; ghost->prison_params.position.x = pink_prison_x; ghost->prison_params.position.y = pink_prison_y; - ghost->prison_params.prison_counter = 0; - ghost->prison_params.active = 0; - ghost->capture_info.status = 0; break; case blue: ghost->position.y = blue_y; @@ -45,13 +35,8 @@ void initialize_ghost(struct ghost_type *ghost, enum ghost_color color) ghost->home_position.y = blue_home_y; ghost->home_position.x = blue_home_x; ghost->color = blue; - ghost->frightened_status = 0; - ghost->direction = none; ghost->prison_params.position.x = blue_prison_x; ghost->prison_params.position.y = blue_prison_y; - ghost->prison_params.prison_counter = 0; - ghost->prison_params.active = 0; - ghost->capture_info.status = 0; break; case orange: ghost->position.y = orange_y; @@ -59,15 +44,16 @@ void initialize_ghost(struct ghost_type *ghost, enum ghost_color color) ghost->home_position.y = orange_home_y; ghost->home_position.x = orange_home_x; ghost->color = orange; - ghost->frightened_status = 0; - ghost->direction = none; ghost->prison_params.position.x = orange_prison_x; ghost->prison_params.position.y = orange_prison_y; + break; + } + ghost->frightened_status = 0; + ghost->direction = none; ghost->prison_params.prison_counter = 0; ghost->prison_params.active = 0; ghost->capture_info.status = 0; - break; - } + ghost->reached_pacman = 0; } void pull_out_ghosts(int *get_out_stage, @@ -114,12 +100,11 @@ static void change_position(struct ghost_type *ghost, change_point_if_outside_tunnel(&ghost->position); } -void make_ghost_moves(game_space field, - struct ghost_type *red_ghost, - struct ghost_type *pink_ghost, - struct ghost_type *blue_ghost, - struct ghost_type *orange_ghost, - struct queue *eaten_coins) +void clear_ghost_positions(game_space field, const struct queue *eaten_coins, + const struct ghost_type *red_ghost, + const struct ghost_type *pink_ghost, + const struct ghost_type *blue_ghost, + const struct ghost_type *orange_ghost) { clear_or_revert_symbol(field, red_ghost->position, ghost_char, eaten_coins); clear_or_revert_symbol(field, pink_ghost->position, ghost_char, @@ -128,6 +113,17 @@ void make_ghost_moves(game_space field, eaten_coins); clear_or_revert_symbol(field, orange_ghost->position, ghost_char, eaten_coins); +} + +void make_ghost_moves(game_space field, + struct ghost_type *red_ghost, + struct ghost_type *pink_ghost, + struct ghost_type *blue_ghost, + struct ghost_type *orange_ghost, + struct queue *eaten_coins) +{ + clear_ghost_positions(field, eaten_coins, red_ghost, pink_ghost, blue_ghost, + orange_ghost); change_position(red_ghost, red_ghost->direction); change_position(pink_ghost, pink_ghost->direction); change_position(blue_ghost, blue_ghost->direction); @@ -63,6 +63,7 @@ struct ghost_type { enum movement_direction direction; struct prison prison_params; struct capture capture_info; + int reached_pacman; }; void initialize_ghost(struct ghost_type *ghost, enum ghost_color color); @@ -74,6 +75,12 @@ void pull_out_ghosts(int *get_out_stage, struct ghost_type *orange_ghost); struct queue; +void clear_ghost_positions(game_space field, const struct queue *eaten_coins, + const struct ghost_type *red_ghost, + const struct ghost_type *pink_ghost, + const struct ghost_type *blue_ghost, + const struct ghost_type *orange_ghost); + void make_ghost_moves(game_space field, struct ghost_type *red_ghost, struct ghost_type *pink_ghost, @@ -140,9 +140,12 @@ void catch_pac(struct pacman *pac) { --pac->lives; erase_life(pac->lives); - if(pac->lives >= 1) { + pac->direction = none; +#if 0 + if(pac->lives >= 0) { pac->position.y = pac_y; pac->position.x = pac_x; pac->direction = none; } +#endif } @@ -4,7 +4,7 @@ #include "ghosts.h" enum { - max_live = 3, + max_live = 2, pac_y = 22, pac_x = 14 }; @@ -2,6 +2,7 @@ #include "ghosts.h" #include "pac.h" #include "queue.h" +#include "color_palette.h" #include <ncurses.h> #include <stdlib.h> #include <unistd.h> @@ -9,12 +10,12 @@ enum { timeout_duration = 0, - sleep_duration = 190000, + sleep_duration = 120000, key_escape = 27, max_get_out_stage = 6, chase_move_limit = 70, scatter_move_limit = 35, - frightened_move_limit = 30, + frightened_move_limit = 50, phase_limit = 4, prison_limit = 30, max_score = 243 @@ -361,13 +362,14 @@ static void catching_stage(game_space field, if(mode_params->current_mode == frightened) catch_ghost(field, current_ghost); else { + current_ghost->reached_pacman = 1; catch_pac(pac); - if(pac->lives) - initialize_ghosts(red_ghost, pink_ghost, blue_ghost, - orange_ghost); - initialize_modes(mode_params); - usleep(sleep_duration); return; +#if 0 + initialize_ghosts(red_ghost, pink_ghost, blue_ghost, + orange_ghost); + return; +#endif } } if(current_ghost->capture_info.status) @@ -375,9 +377,19 @@ static void catching_stage(game_space field, } } +static int ghost_caught_pacman(struct ghost_type red_ghost, + struct ghost_type pink_ghost, + struct ghost_type blue_ghost, + struct ghost_type orange_ghost) +{ + return red_ghost.reached_pacman || pink_ghost.reached_pacman || + blue_ghost.reached_pacman || orange_ghost.reached_pacman; +} + static void final_stage(struct game_params_type *game_options, int win) { int key; + reset_attr(); if(win) { move(17, 10); printw("YOU WIN"); @@ -415,6 +427,7 @@ int main() srand(time(NULL)); initscr(); start_color(); + set_pairs(); cbreak(); noecho(); curs_set(0); @@ -438,6 +451,8 @@ int main() mode_params.current_mode = frightened; mode_params.reverse_direction = 1; pac.is_energizer_eaten = 0; + /* if frightened mode is activated already */ + mode_params.frightened_count = 0; } /* * ghosts @@ -469,17 +484,23 @@ int main() /* * displaying characters and score */ + display_score(pac.score); display_ghosts_on_field(&red_ghost, &pink_ghost, &blue_ghost, &orange_ghost); - display_character(pac.position.y, pac.position.x, pac_char); - display_score(pac.score); - + if(ghost_caught_pacman(red_ghost, pink_ghost, blue_ghost, + orange_ghost)) { + display_hit(pac.position, &red_ghost, &pink_ghost, &blue_ghost, + &orange_ghost); + usleep(sleep_duration*5); + } else + display_character(pac.position.y, pac.position.x, pac_char); usleep(sleep_duration); prison_leaving_stage(field, &red_ghost, &pink_ghost, &blue_ghost, &orange_ghost); #ifdef DEBUG move(0, 50); + reset_attr(); if(mode_params.current_mode == chase) printw("CHASE %d ", mode_params.chase_count); else if(mode_params.current_mode == scatter) @@ -487,11 +508,20 @@ int main() else if(mode_params.current_mode == frightened) printw("FRIGHTENED %d ", mode_params.frightened_count); move(1, 50); - printw("LIVES: %d", pac.lives); + printw("LIVES: %d ", pac.lives); + move(2, 50); + printw("%d %d ", orange_ghost.position.x, orange_ghost.position.y); + move(3, 50); + printw("%d %d ", pac.position.x, pac.position.y); refresh(); #endif - if(!pac.lives || pac.score == max_score ) { - final_stage(&game_options, !pac.lives ? 0 : 1); + if(pac.lives < 0 || pac.score == max_score ) { +#if 0 + if(pac.lives < 0) + display_ghosts_on_field(&red_ghost, &pink_ghost, &blue_ghost, + &orange_ghost); +#endif + final_stage(&game_options, pac.lives < 0 ? 0 : 1); if(game_options.exit) break; else { @@ -502,6 +532,22 @@ int main() &orange_ghost); usleep(sleep_duration); } + continue; + } + if(ghost_caught_pacman(red_ghost, pink_ghost, blue_ghost, + orange_ghost)) { + erase_hit(pac.position); + clear_ghost_positions(field, &eaten_coins, &red_ghost, &pink_ghost, + &blue_ghost, &orange_ghost); + pac.position.x = pac_x; + pac.position.y = pac_y; + initialize_ghosts(&red_ghost, &pink_ghost, &blue_ghost, + &orange_ghost); + initialize_modes(&mode_params); + display_ghosts_on_field(&red_ghost, &pink_ghost, &blue_ghost, + &orange_ghost); + display_character(pac.position.y, pac.position.x, pac_char); + usleep(sleep_duration); } } clear_field_and_queue(field, &eaten_coins); |