diff options
author | Elias Fleckenstein <eliasfleckenstein@web.de> | 2021-06-11 21:11:37 +0200 |
---|---|---|
committer | Elias Fleckenstein <eliasfleckenstein@web.de> | 2021-06-11 21:11:37 +0200 |
commit | 30c560e271499cb461372a6798e53bf122a7495e (patch) | |
tree | 8d3022047c8b83d5a95e14c1fa488b0c8702be52 | |
parent | 14d315712d372932b27a118171865118a6b415c7 (diff) | |
download | dungeon_game-30c560e271499cb461372a6798e53bf122a7495e.tar.xz |
Add inventory and cherries (collectable food)
-rw-r--r-- | plugins/cherry/Makefile | 4 | ||||
-rw-r--r-- | plugins/cherry/cherry.c | 71 | ||||
-rw-r--r-- | plugins/cherry/dependencies.txt | 3 | ||||
-rw-r--r-- | plugins/game/game.c | 33 | ||||
-rw-r--r-- | plugins/game/game.h | 8 | ||||
-rw-r--r-- | plugins/inventory/Makefile | 4 | ||||
-rw-r--r-- | plugins/inventory/dependencies.txt | 1 | ||||
-rw-r--r-- | plugins/inventory/inventory.c | 203 | ||||
-rw-r--r-- | plugins/inventory/inventory.h | 30 |
9 files changed, 341 insertions, 16 deletions
diff --git a/plugins/cherry/Makefile b/plugins/cherry/Makefile new file mode 100644 index 0000000..edb1f44 --- /dev/null +++ b/plugins/cherry/Makefile @@ -0,0 +1,4 @@ +plugins/cherry/cherry.so: plugins/cherry/cherry.c plugins/game/game.h plugins/score/score.h plugins/inventory/inventory.h + cc -g -shared -fpic -o plugins/cherry/cherry.so plugins/cherry/cherry.c + +PLUGINS := ${PLUGINS} plugins/cherry/cherry.so diff --git a/plugins/cherry/cherry.c b/plugins/cherry/cherry.c new file mode 100644 index 0000000..072aec0 --- /dev/null +++ b/plugins/cherry/cherry.c @@ -0,0 +1,71 @@ +#include <stddef.h> +#include <stdlib.h> +#include "../game/game.h" +#include "../score/score.h" +#include "../inventory/inventory.h" + +static struct entity cherry_entity; + +static bool use_cherry(struct itemstack *stack) +{ + (void) stack; + + add_health(&player, 2); + return true; +} + +static struct item cherry_item = { + .name = "Cherry", + .stackable = true, + + .on_use = &use_cherry, + .on_destroy = NULL, +}; + +static void cherry_step(struct entity *self, struct entity_step_data stepdata) +{ + if (stepdata.dx == 0 && stepdata.dy == 0) { + add_score(2); + inventory_add(&player_inventory, (struct itemstack) { + .item = &cherry_item, + .count = 1, + .meta = NULL, + }); + self->remove = true; + } +} + +static void spawn_cherry(int x, int y) +{ + spawn(cherry_entity, x, y, NULL); +} + +__attribute__((constructor)) static void init() +{ + cherry_entity = (struct entity) { + .name = "cherry", + .x = 0, + .y = 0, + .color = get_color("#FF2A53"), + .texture = "🍒", + .remove = false, + .meta = NULL, + .health = 1, + .max_health = 1, + .collide_with_entities = false, + + .on_step = &cherry_step, + .on_collide = NULL, + .on_collide_with_entity = NULL, + .on_spawn = NULL, + .on_remove = NULL, + .on_death = NULL, + .on_damage = NULL, + }; + + register_air_function((struct generator_function) { + .chance = 100, + .callback = &spawn_cherry, + }); +} + diff --git a/plugins/cherry/dependencies.txt b/plugins/cherry/dependencies.txt new file mode 100644 index 0000000..4952514 --- /dev/null +++ b/plugins/cherry/dependencies.txt @@ -0,0 +1,3 @@ +game +score +inventory diff --git a/plugins/game/game.c b/plugins/game/game.c index 40bfa51..8dacf4a 100644 --- a/plugins/game/game.c +++ b/plugins/game/game.c @@ -1,7 +1,5 @@ #include <stdio.h> -#include <stdbool.h> #include <stdlib.h> -#include <stddef.h> #include <unistd.h> #include <assert.h> #include <ctype.h> @@ -10,8 +8,8 @@ #include <termios.h> #include <math.h> #include <pthread.h> +#include <string.h> #include "game.h" -#define MAKEBUF(type) type *buf = malloc(sizeof(type)); *buf = arg; /* Shared variables */ @@ -119,6 +117,14 @@ int min(int a, int b) return a < b ? a : b; } +void *make_buffer(void *ptr, size_t size) +{ + void *buf = malloc(size); + memcpy(buf, ptr, size); + + return buf; +} + /* Game-related utility functions */ void quit() @@ -216,24 +222,22 @@ void add_health(struct entity *entity, int health) /* Register callback functions */ -void register_air_function(struct generator_function arg) +void register_air_function(struct generator_function func) { - MAKEBUF(struct generator_function); - air_functions = add_element(air_functions, buf); + air_functions = add_element(air_functions, make_buffer(&func, sizeof(struct generator_function))); } -void register_input_handler(unsigned char c, struct input_handler arg) +void register_input_handler(unsigned char c, struct input_handler handler) { if (input_handlers[c]) return; - MAKEBUF(struct input_handler); - input_handlers[c] = buf; + input_handlers[c] = make_buffer(&handler, sizeof(struct input_handler)); } -void register_render_component(void (*arg)(struct winsize ws)) +void register_render_component(void (*callback)(struct winsize ws)) { - render_components = add_element(render_components, arg); + render_components = add_element(render_components, callback); }; /* Player */ @@ -254,9 +258,12 @@ static void mapgen_set_air(int x, int y) { if (is_outside(x, y)) return; + if (map[x][y].material == &air) return; + map[x][y] = (struct node) {&air}; + for (struct list *ptr = air_functions; ptr != NULL; ptr = ptr->next) { struct generator_function *func = ptr->element; @@ -456,8 +463,6 @@ static void *input_thread(void *unused) void game() { - srand(time(0)); - struct sigaction sa; sa.sa_handler = &handle_interrupt; sigaction(SIGINT, &sa, NULL); @@ -553,6 +558,8 @@ void game() __attribute__ ((constructor)) static void init() { + srand(time(0)); + wall = (struct material) { .solid = true, .color = get_color("#5B2F00"), diff --git a/plugins/game/game.h b/plugins/game/game.h index f4cd53b..11d39ba 100644 --- a/plugins/game/game.h +++ b/plugins/game/game.h @@ -3,6 +3,7 @@ #include <stdbool.h> #include <sys/ioctl.h> +#include <stddef.h> #define MAP_HEIGHT 1000 #define MAP_WIDTH 1000 #define LIGHT 10 @@ -102,6 +103,7 @@ struct list *add_element(struct list *list, void *element); int clamp(int v, int max, int min); int max(int a, int b); int min(int a, int b); +void *make_buffer(void *ptr, size_t size); void quit(); bool player_dead(); @@ -114,8 +116,8 @@ bool spawn(struct entity def, int x, int y, void *data); bool move(struct entity *entity, int xoff, int yoff); void add_health(struct entity *entity, int health); -void register_air_function(struct generator_function arg); -void register_input_handler(unsigned char c, struct input_handler arg); -void register_render_component(void (*arg)(struct winsize ws)); +void register_air_function(struct generator_function func); +void register_input_handler(unsigned char c, struct input_handler handler); +void register_render_component(void (*callback)(struct winsize ws)); #endif diff --git a/plugins/inventory/Makefile b/plugins/inventory/Makefile new file mode 100644 index 0000000..a665b55 --- /dev/null +++ b/plugins/inventory/Makefile @@ -0,0 +1,4 @@ +plugins/inventory/inventory.so: plugins/inventory/inventory.c plugins/inventory/inventory.h plugins/game/game.h + cc -g -shared -fpic -o plugins/inventory/inventory.so plugins/inventory/inventory.c + +PLUGINS := ${PLUGINS} plugins/inventory/inventory.so diff --git a/plugins/inventory/dependencies.txt b/plugins/inventory/dependencies.txt new file mode 100644 index 0000000..dc22e61 --- /dev/null +++ b/plugins/inventory/dependencies.txt @@ -0,0 +1 @@ +game diff --git a/plugins/inventory/inventory.c b/plugins/inventory/inventory.c new file mode 100644 index 0000000..c3b533d --- /dev/null +++ b/plugins/inventory/inventory.c @@ -0,0 +1,203 @@ +#include <stdio.h> +#include <stdlib.h> +#include "../inventory/inventory.h" + +static struct color gray; +static struct color darkgray; + +static bool use_item(struct itemstack *stack) +{ + (void) stack; + return true; +} + +struct inventory player_inventory = {NULL}; + +static int selected_index = 0; + +void inventory_add(struct inventory *self, struct itemstack stack) +{ + struct list **ptr = &self->stacks; + + if (stack.item->stackable) { + for (; *ptr != NULL; ptr = &(*ptr)->next) { + struct itemstack *other = (*ptr)->element; + if (other->item == stack.item) { + other->count += stack.count; + return; + } + } + } + + *ptr = add_element(*ptr, make_buffer(&stack, sizeof(struct itemstack))); +} + +/* + +bool inventory_remove(struct inventory *self, struct itemstack *stack) +{ + stack.count = -stack.count; + + for (struct list **ptr = &self->stacks; *ptr != NULL; ) { + struct itemstack *other = (*ptr)->element; + + if (other->item == stack.item) { + stack.count += other->count; + + if (stack.count > 0) { + other->count = stack.count; + return true; + } else { + struct list *next = ptr->next; + + other->count = 0; + + if (other->item->on_destroy) + other->item->on_destroy(other); + + free(other); + free(*ptr); + + *ptr = next; + continue; + } + } + + ptr = &(*ptr)->next; + } + + return false; +} + +*/ + +static void decrease_item_count(struct list **ptr, struct itemstack *stack) +{ + stack->count--; + + if (stack->count == 0) { + struct list *next = (*ptr)->next; + + if (stack->item->on_destroy) + stack->item->on_destroy(stack); + + free(stack); + free(*ptr); + + *ptr = next; + } +} + +bool inventory_remove(struct inventory *self, struct item *item) +{ + for (struct list **ptr = &self->stacks; *ptr != NULL; ptr = &(*ptr)->next) { + struct itemstack *stack = (*ptr)->element; + + if (stack->item == item) { + decrease_item_count(ptr, stack); + + return true; + } + } + + return false; +} + +static void handle_enter() +{ + int i = 0; + + for (struct list **ptr = &player_inventory.stacks; *ptr != NULL; ptr = &(*ptr)->next, i++) { + if (i == selected_index) { + struct itemstack *stack = (*ptr)->element; + + if (stack->item->on_use && stack->item->on_use(stack)) + decrease_item_count(ptr, stack); + + return; + } + } +} + +static void handle_arrow() +{ + char c = fgetc(stdin); + if (c == '[') { + char dir = fgetc(stdin); + + int count = 0; + + for (struct list *ptr = player_inventory.stacks; ptr != NULL; ptr = ptr->next) + count++; + + if (count == 0) + return; + + switch (dir) { + case 'A': + selected_index--; + + if (selected_index < 0) + selected_index = count - 1; + break; + case 'B': + selected_index++; + + if (selected_index >= count) + selected_index = 0; + + break; + } + } else { + ungetc(c, stdin); + } +} + +static void render_inventory(struct winsize ws) +{ + printf("\e[3;0H"); + + printf(" \e[1mInventory\e[21m\n"); + + set_color(gray, false); + + int i = 0; + for (struct list *ptr = player_inventory.stacks; ptr != NULL; ptr = ptr->next, i++) { + struct itemstack *stack = ptr->element; + + if (i == selected_index) { + printf(" \e[39m→ "); + set_color(gray, false); + } else { + printf(" "); + } + + printf("%s", stack->item->name); + + if (stack->count > 1) { + set_color(darkgray, false); + printf(" (x%u)", stack->count); + set_color(gray, false); + } + + printf("\n"); + } +} + +__attribute__ ((constructor)) static void init() +{ + gray = get_color("#9E9E9E"); + darkgray = get_color("#555555"); + + register_render_component(&render_inventory); + + register_input_handler('\033', (struct input_handler) { + .run_if_dead = false, + .callback = &handle_arrow, + }); + + register_input_handler('\n', (struct input_handler) { + .run_if_dead = false, + .callback = &handle_enter, + }); +} diff --git a/plugins/inventory/inventory.h b/plugins/inventory/inventory.h new file mode 100644 index 0000000..4b13f94 --- /dev/null +++ b/plugins/inventory/inventory.h @@ -0,0 +1,30 @@ +#ifndef _INVENTORY_H_ +#define _INVENTORY_H_ +#include "../game/game.h" + +struct itemstack +{ + struct item *item; + int count; + void *meta; +}; + +struct item +{ + char *name; + bool stackable; + + bool (*on_use)(struct itemstack *stack); + void (*on_destroy)(struct itemstack *stack); +}; + +struct inventory +{ + struct list *stacks; +}; + +void inventory_add(struct inventory *self, struct itemstack stack); +bool inventory_remove(struct inventory *self, struct item *item); + +extern struct inventory player_inventory; +#endif |