aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorElias Fleckenstein <eliasfleckenstein@web.de>2021-06-10 21:28:01 +0200
committerElias Fleckenstein <eliasfleckenstein@web.de>2021-06-10 21:28:01 +0200
commit76d78db55969fa0a3ca92376e5cc9d0b266b4d1e (patch)
tree631273574db6582b3839158308a7f696ee3b7e46
parent149848dbfa136f828b09253f402de59c00a5a1cf (diff)
downloaddungeon_game-76d78db55969fa0a3ca92376e5cc9d0b266b4d1e.tar.xz
Modularize rendering
-rw-r--r--plugins/apple/Makefile2
-rw-r--r--plugins/apple/apple.c1
-rw-r--r--plugins/apple/dependencies.txt1
-rw-r--r--plugins/fireball/Makefile2
-rw-r--r--plugins/game/game.c417
-rw-r--r--plugins/game/game.h39
-rw-r--r--plugins/healthbar/Makefile4
-rw-r--r--plugins/healthbar/dependencies.txt1
-rw-r--r--plugins/healthbar/healthbar.c30
-rw-r--r--plugins/monster/Makefile2
-rw-r--r--plugins/monster/dependencies.txt1
-rw-r--r--plugins/monster/monster.c1
-rw-r--r--plugins/movement/Makefile2
-rw-r--r--plugins/score/Makefile4
-rw-r--r--plugins/score/dependencies.txt1
-rw-r--r--plugins/score/score.c26
-rw-r--r--plugins/score/score.h7
17 files changed, 309 insertions, 232 deletions
diff --git a/plugins/apple/Makefile b/plugins/apple/Makefile
index 33c3303..f90b872 100644
--- a/plugins/apple/Makefile
+++ b/plugins/apple/Makefile
@@ -1,4 +1,4 @@
-plugins/apple/apple.so: plugins/apple/apple.c plugins/game/game.h
+plugins/apple/apple.so: plugins/apple/apple.c plugins/game/game.h plugins/score/score.h
cc -g -shared -fpic -o plugins/apple/apple.so plugins/apple/apple.c
PLUGINS := ${PLUGINS} plugins/apple/apple.so
diff --git a/plugins/apple/apple.c b/plugins/apple/apple.c
index d100e45..19e2e00 100644
--- a/plugins/apple/apple.c
+++ b/plugins/apple/apple.c
@@ -1,6 +1,7 @@
#include <stddef.h>
#include <stdlib.h>
#include "../game/game.h"
+#include "../score/score.h"
static struct entity apple;
diff --git a/plugins/apple/dependencies.txt b/plugins/apple/dependencies.txt
index dc22e61..3914551 100644
--- a/plugins/apple/dependencies.txt
+++ b/plugins/apple/dependencies.txt
@@ -1 +1,2 @@
game
+score
diff --git a/plugins/fireball/Makefile b/plugins/fireball/Makefile
index bc0a277..a7fe4cd 100644
--- a/plugins/fireball/Makefile
+++ b/plugins/fireball/Makefile
@@ -1,4 +1,4 @@
-plugins/fireball/fireball.so: plugins/fireball/fireball.c plugins/game/game.h
+plugins/fireball/fireball.so: plugins/fireball/fireball.c plugins/game/game.h plugins/movement/movement.h
cc -g -shared -fpic -o plugins/fireball/fireball.so plugins/fireball/fireball.c
PLUGINS := ${PLUGINS} plugins/fireball/fireball.so
diff --git a/plugins/game/game.c b/plugins/game/game.c
index 4ba7d52..ad283c8 100644
--- a/plugins/game/game.c
+++ b/plugins/game/game.c
@@ -8,15 +8,12 @@
#include <time.h>
#include <signal.h>
#include <termios.h>
-#include <sys/ioctl.h>
#include <math.h>
#include <pthread.h>
#include "game.h"
+#define MAKEBUF(type) type *buf = malloc(sizeof(type)); *buf = arg;
-bool running = true;
-double damage_overlay = 0.0;
-
-int score = 0;
+/* Shared variables */
struct color black = {0, 0, 0};
@@ -32,16 +29,20 @@ struct list *entities = & (struct list) {
.next = NULL,
};
+/* Private variables */
+
struct entity *entity_collision_map[MAP_WIDTH][MAP_HEIGHT] = {{NULL}};
-struct list *air_functions = NULL;
+static bool running = true;
+static double damage_overlay = 0.0;
+static struct color damage_overlay_color;
-struct input_handler *input_handlers[256] = {NULL};
+static struct list *air_functions = NULL;
+static struct input_handler *input_handlers[256] = {NULL};
+static struct entity *render_entities[LIGHT * 2 + 1][LIGHT * 2 + 1];
+static struct list *render_components = NULL;
-void quit()
-{
- running = false;
-}
+/* Helper functions */
struct color get_color(const char *str)
{
@@ -50,45 +51,105 @@ struct color get_color(const char *str)
return (struct color) {r, g, b};
}
-bool is_outside(int x, int y)
+void set_color(struct color color, bool bg)
{
- return x >= MAP_WIDTH || x < 0 || y >= MAP_HEIGHT || y < 0;
+ printf("\e[%u;2;%u;%u;%um", bg ? 48 : 38, color.r, color.g, color.b);
}
-struct node get_node(int x, int y)
+void light_color(struct color *color, double light)
{
- return is_outside(x, y) ? (struct node) {&outside} : map[x][y];
+ color->r *= light;
+ color->g *= light;
+ color->b *= light;
}
-bool is_solid(int x, int y)
+void mix_color(struct color *color, struct color other, double ratio)
{
- return get_node(x, y).material->solid;
+ double ratio_total = ratio + 1;
+
+ color->r = (color->r + other.r * ratio) / ratio_total;
+ color->g = (color->g + other.g * ratio) / ratio_total;
+ color->b = (color->b + other.b * ratio) / ratio_total;
}
-bool move(struct entity *entity, int xoff, int yoff)
+void dir_to_xy(enum direction dir, int *x, int *y)
{
- int x, y;
+ switch (dir) {
+ case UP:
+ (*y)--;
+ break;
+ case LEFT:
+ (*x)--;
+ break;
+ case DOWN:
+ (*y)++;
+ break;
+ case RIGHT:
+ (*x)++;
+ break;
+ }
+}
- x = entity->x + xoff;
- y = entity->y + yoff;
+struct list *add_element(struct list *list, void *element)
+{
+ struct list **ptr;
- if (is_solid(x, y)) {
- if (entity->on_collide)
- entity->on_collide(entity, x, y);
- return false;
- } else if (entity->collide_with_entities && entity_collision_map[x][y]) {
- if (entity->on_collide_with_entity)
- entity->on_collide_with_entity(entity, entity_collision_map[x][y]);
- return false;
- } else {
- entity_collision_map[entity->x][entity->y] = NULL;
- entity->x = x;
- entity->y = y;
- entity_collision_map[entity->x][entity->y] = entity;
- return true;
- }
+ for (ptr = &list; *ptr != NULL; ptr = &(*ptr)->next)
+ ;
+
+ *ptr = malloc(sizeof(struct list));
+ (*ptr)->element = element;
+ (*ptr)->next = NULL;
+
+ return list;
+}
+
+int clamp(int v, int min, int max)
+{
+ return v < min ? min : v > max ? max : v;
+}
+
+int max(int a, int b)
+{
+ return a > b ? a : b;
+}
+
+int min(int a, int b)
+{
+ return a < b ? a : b;
+}
+
+/* Game-related utility functions */
+
+void quit()
+{
+ running = false;
+}
+
+bool player_dead()
+{
+ return player.health <= 0;
+}
+
+/* Map functions */
+
+struct node get_node(int x, int y)
+{
+ return is_outside(x, y) ? (struct node) {&outside} : map[x][y];
+}
+
+bool is_outside(int x, int y)
+{
+ return x >= MAP_WIDTH || x < 0 || y >= MAP_HEIGHT || y < 0;
+}
+
+bool is_solid(int x, int y)
+{
+ return get_node(x, y).material->solid;
}
+/* Entity functions */
+
bool spawn(struct entity def, int x, int y, void *data)
{
if (is_solid(x, y))
@@ -114,6 +175,30 @@ bool spawn(struct entity def, int x, int y, void *data)
return true;
}
+bool move(struct entity *entity, int xoff, int yoff)
+{
+ int x, y;
+
+ x = entity->x + xoff;
+ y = entity->y + yoff;
+
+ if (is_solid(x, y)) {
+ if (entity->on_collide)
+ entity->on_collide(entity, x, y);
+ return false;
+ } else if (entity->collide_with_entities && entity_collision_map[x][y]) {
+ if (entity->on_collide_with_entity)
+ entity->on_collide_with_entity(entity, entity_collision_map[x][y]);
+ return false;
+ } else {
+ entity_collision_map[entity->x][entity->y] = NULL;
+ entity->x = x;
+ entity->y = y;
+ entity_collision_map[entity->x][entity->y] = entity;
+ return true;
+ }
+}
+
void add_health(struct entity *entity, int health)
{
bool was_alive = entity->health > 0;
@@ -129,71 +214,27 @@ void add_health(struct entity *entity, int health)
entity->on_death(entity);
}
-void add_score(int s)
-{
- score += s;
-}
-
-bool player_dead()
-{
- return player.health <= 0;
-}
-
-struct list *add_element(struct list *list, void *element)
-{
- struct list **ptr;
-
- for (ptr = &list; *ptr != NULL; ptr = &(*ptr)->next)
- ;
-
- *ptr = malloc(sizeof(struct list));
- (*ptr)->element = element;
- (*ptr)->next = NULL;
+/* Register callback functions */
- return list;
-}
-
-void register_air_function(struct generator_function func)
+void register_air_function(struct generator_function arg)
{
- struct generator_function *buf = malloc(sizeof(struct generator_function));
- *buf = func;
-
+ MAKEBUF(struct generator_function);
air_functions = add_element(air_functions, buf);
}
-void register_input_handler(unsigned char c, struct input_handler handler)
+void register_input_handler(unsigned char c, struct input_handler arg)
{
if (input_handlers[c])
return;
- struct input_handler *buf = malloc(sizeof(struct input_handler));
- *buf = handler;
-
+ MAKEBUF(struct input_handler);
input_handlers[c] = buf;
}
-void dir_to_xy(enum direction dir, int *x, int *y)
+void register_render_component(void (*arg)(struct winsize ws))
{
- switch (dir) {
- case UP:
- (*y)--;
- break;
- case LEFT:
- (*x)--;
- break;
- case DOWN:
- (*y)++;
- break;
- case RIGHT:
- (*x)++;
- break;
- }
-}
-
-int clamp(int v, int min, int max)
-{
- return v < min ? min : v > max ? max : v;
-}
+ render_components = add_element(render_components, arg);
+};
/* Player */
@@ -273,27 +314,6 @@ static void generate_corridor_random(int x, int y)
/* Rendering */
-void set_color(struct color color, bool bg)
-{
- printf("\e[%u;2;%u;%u;%um", bg ? 48 : 38, color.r, color.g, color.b);
-}
-
-void light_color(struct color *color, double light)
-{
- color->r *= light;
- color->g *= light;
- color->b *= light;
-}
-
-void mix_color(struct color *color, struct color other, double ratio)
-{
- double ratio_total = ratio + 1;
-
- color->r = (color->r + other.r * ratio) / ratio_total;
- color->g = (color->g + other.g * ratio) / ratio_total;
- color->b = (color->b + other.b * ratio) / ratio_total;
-}
-
static bool render_color(struct color color, double light, bool bg)
{
if (light <= 0.0) {
@@ -301,7 +321,7 @@ static bool render_color(struct color color, double light, bool bg)
return false;
} else {
if (damage_overlay > 0.0)
- mix_color(&color, get_color("#F20000"), damage_overlay * 2.0);
+ mix_color(&color, damage_overlay_color, damage_overlay * 2.0);
light_color(&color, light);
@@ -310,21 +330,14 @@ static bool render_color(struct color color, double light, bool bg)
}
}
-static void render(render_entity_list entity_list)
+static void render_map(struct winsize ws)
{
- printf("\e[2J\e[0;0H");
-
- struct winsize ws;
- ioctl(STDIN_FILENO, TIOCGWINSZ, &ws);
-
int cols = ws.ws_col / 2 - LIGHT * 2;
int rows = ws.ws_row / 2 - LIGHT;
int cols_left = ws.ws_col - cols - (LIGHT * 2 + 1) * 2;
int rows_left = ws.ws_row - rows - (LIGHT * 2 + 1);
- set_color(black, true);
-
for (int i = 0; i < rows; i++)
for (int i = 0; i < ws.ws_col; i++)
printf(" ");
@@ -346,7 +359,8 @@ static void render(render_entity_list entity_list)
render_color(node.material->color, light, true);
- struct entity *entity = entity_list[x + LIGHT][y + LIGHT];
+ struct entity *entity = render_entities[x + LIGHT][y + LIGHT];
+ render_entities[x + LIGHT][y + LIGHT] = NULL;
if (entity && render_color(entity->color, light, false))
printf("%s", entity->texture);
@@ -363,57 +377,40 @@ static void render(render_entity_list entity_list)
for (int i = 0; i < rows_left + 1; i++)
for (int i = 0; i < ws.ws_col; i++)
printf(" ");
+}
- printf("\e[0;0H\e[39m");
-
- printf("\e[32m\e[3mScore:\e[23m %d\e[39m", score);
-
- printf("\e[0;0");
-
- for (int i = 0; i < rows; i++)
- printf("\n");
-
- printf("\t\e[1mInventory\e[22m\n\n");
- printf("\t0x\t\e[3mNothing\e[23m\n");
-
- printf("\e[0;0H");
-
- for (int i = 0; i < ws.ws_row - 2; i++)
- printf("\n");
-
- int hearts_cols = ws.ws_col / 2 - player.max_health;
+static void render()
+{
+ printf("\e[2J");
- for (int i = 0; i < hearts_cols; i++)
- printf(" ");
+ struct winsize ws;
+ ioctl(STDIN_FILENO, TIOCGWINSZ, &ws);
- set_color((struct color) {255, 0, 0}, false);
+ for (struct list *ptr = render_components; ptr != NULL; ptr = ptr->next) {
+ printf("\e[0m\e[0;0H");
+ set_color(black, true);
- for (int i = 0; i < player.max_health; i++) {
- if (i >= player.health)
- set_color(get_color("#5A5A5A"), false);
- printf("\u2665 ");
+ ((void (*)(struct winsize ws)) ptr->element)(ws);
}
- printf("\e[39m\n");
+ fflush(stdout);
}
/* Input */
-static void handle_input(unsigned char c)
+static void handle_interrupt(int signal)
{
- struct input_handler *handler = input_handlers[c];
+ (void) signal;
- if (handler && (handler->run_if_dead || ! player_dead()))
- handler->callback();
+ quit();
}
-/* Multithreading */
-
-static void handle_interrupt(int signal)
+static void handle_input(unsigned char c)
{
- (void) signal;
+ struct input_handler *handler = input_handlers[c];
- running = false;
+ if (handler && (handler->run_if_dead || ! player_dead()))
+ handler->callback();
}
static void *input_thread(void *unused)
@@ -428,56 +425,6 @@ static void *input_thread(void *unused)
/* Main Game */
-__attribute__ ((constructor)) static void init()
-{
- wall = (struct material) {
- .solid = true,
- .color = get_color("#5B2F00"),
- };
-
- air = (struct material) {
- .solid = false,
- .color = get_color("#FFE027"),
- };
-
- outside = (struct material) {
- .solid = true,
- .color = black,
- };
-
- player = (struct entity) {
- .name = "player",
- .x = MAP_WIDTH / 2,
- .y = MAP_HEIGHT / 2,
- .color = get_color("#00FFFF"),
- .texture = "🙂",
- .remove = false,
- .meta = NULL,
- .health = 10,
- .max_health = 10,
- .collide_with_entities = true,
-
- .on_step = NULL,
- .on_collide = NULL,
- .on_collide_with_entity = NULL,
- .on_spawn = NULL,
- .on_remove = NULL,
- .on_death = &player_death,
- .on_damage = &player_damage,
- };
-
- entity_collision_map[player.x][player.y] = &player;
-
- for (int x = 0; x < MAP_WIDTH; x++)
- for (int y = 0; y < MAP_HEIGHT; y++)
- map[x][y] = (struct node) {&wall};
-
- register_input_handler('q', (struct input_handler) {
- .run_if_dead = true,
- .callback = &quit,
- });
-}
-
void game()
{
srand(time(0));
@@ -519,8 +466,6 @@ void game()
damage_overlay = 0.0;
}
- render_entity_list render_list = {{NULL}};
-
for (struct list **ptr = &entities; *ptr != NULL; ) {
struct entity *entity = (*ptr)->element;
@@ -552,7 +497,7 @@ void game()
bool visible = abs(dx) <= LIGHT && abs(dy) <= LIGHT;
if (visible)
- render_list[dx + LIGHT][dy + LIGHT] = entity;
+ render_entities[dx + LIGHT][dy + LIGHT] = entity;
if (! dead && entity->on_step)
entity->on_step(entity, (struct entity_step_data) {
@@ -565,7 +510,7 @@ void game()
ptr = &(*ptr)->next;
}
- render(render_list);
+ render();
// there is no such thing as glfwSwapBuffers, so we just wait 1 / 60 seconds to prevent artifacts
usleep(1000000 / 60);
@@ -575,6 +520,62 @@ void game()
tcsetattr(STDIN_FILENO, TCSANOW, &oldtio);
}
+/* Initializer function */
+
+__attribute__ ((constructor)) static void init()
+{
+ wall = (struct material) {
+ .solid = true,
+ .color = get_color("#5B2F00"),
+ };
+
+ air = (struct material) {
+ .solid = false,
+ .color = get_color("#FFE027"),
+ };
+
+ outside = (struct material) {
+ .solid = true,
+ .color = black,
+ };
+
+ player = (struct entity) {
+ .name = "player",
+ .x = MAP_WIDTH / 2,
+ .y = MAP_HEIGHT / 2,
+ .color = get_color("#00FFFF"),
+ .texture = "🙂",
+ .remove = false,
+ .meta = NULL,
+ .health = 10,
+ .max_health = 10,
+ .collide_with_entities = true,
+
+ .on_step = NULL,
+ .on_collide = NULL,
+ .on_collide_with_entity = NULL,
+ .on_spawn = NULL,
+ .on_remove = NULL,
+ .on_death = &player_death,
+ .on_damage = &player_damage,
+ };
+
+ entity_collision_map[player.x][player.y] = &player;
+
+ for (int x = 0; x < MAP_WIDTH; x++)
+ for (int y = 0; y < MAP_HEIGHT; y++)
+ map[x][y] = (struct node) {&wall};
+
+ register_input_handler('q', (struct input_handler) {
+ .run_if_dead = true,
+ .callback = &quit,
+ });
+
+ register_render_component(&render_map);
+
+ damage_overlay_color = get_color("#F20000");
+}
+
/* Use later */
/*
diff --git a/plugins/game/game.h b/plugins/game/game.h
index d8555d2..f4cd53b 100644
--- a/plugins/game/game.h
+++ b/plugins/game/game.h
@@ -2,6 +2,7 @@
#define _GAME_H_
#include <stdbool.h>
+#include <sys/ioctl.h>
#define MAP_HEIGHT 1000
#define MAP_WIDTH 1000
#define LIGHT 10
@@ -59,8 +60,6 @@ struct list
struct list *next;
};
-typedef struct entity *render_entity_list[LIGHT * 2 + 1][LIGHT * 2 + 1];
-
struct generator_function
{
int chance;
@@ -81,8 +80,6 @@ enum direction
RIGHT,
};
-extern int score;
-
extern struct color black;
extern struct material wall;
@@ -96,27 +93,29 @@ extern struct list *entities;
extern struct entity *entity_collision_map[MAP_WIDTH][MAP_HEIGHT];
-extern struct list *air_functions;
-
-extern struct input_handler *input_handlers[256];
-
-void quit();
struct color get_color(const char *str);
-bool is_outside(int x, int y);
-struct node get_node(int x, int y);
-bool is_solid(int x, int y);
-bool move(struct entity *entity, int xoff, int yoff);
-bool spawn(struct entity def, int x, int y, void *data);
-void add_health(struct entity *entity, int health);
-void add_score(int s);
-bool player_dead();
void set_color(struct color color, bool bg);
void light_color(struct color *color, double light);
void mix_color(struct color *color, struct color other, double ratio);
-void register_air_function(struct generator_function func);
-void register_input_handler(unsigned char c, struct input_handler handler);
void dir_to_xy(enum direction dir, int *x, int *y);
-int clamp(int v, int max, int min);
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 quit();
+bool player_dead();
+
+struct node get_node(int x, int y);
+bool is_outside(int x, int y);
+bool is_solid(int x, int y);
+
+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));
#endif
diff --git a/plugins/healthbar/Makefile b/plugins/healthbar/Makefile
new file mode 100644
index 0000000..91c65d4
--- /dev/null
+++ b/plugins/healthbar/Makefile
@@ -0,0 +1,4 @@
+plugins/healthbar/healthbar.so: plugins/healthbar/healthbar.c plugins/game/game.h
+ cc -g -shared -fpic -o plugins/healthbar/healthbar.so plugins/healthbar/healthbar.c
+
+PLUGINS := ${PLUGINS} plugins/healthbar/healthbar.so
diff --git a/plugins/healthbar/dependencies.txt b/plugins/healthbar/dependencies.txt
new file mode 100644
index 0000000..dc22e61
--- /dev/null
+++ b/plugins/healthbar/dependencies.txt
@@ -0,0 +1 @@
+game
diff --git a/plugins/healthbar/healthbar.c b/plugins/healthbar/healthbar.c
new file mode 100644
index 0000000..5651051
--- /dev/null
+++ b/plugins/healthbar/healthbar.c
@@ -0,0 +1,30 @@
+#include <stdio.h>
+#include "../game/game.h"
+
+static struct color red = {255, 0, 0};
+static struct color gray;
+
+static void render_healthbar(struct winsize ws)
+{
+ int y = max(ws.ws_row - 2, 0);
+ int x = max(ws.ws_col / 2 - player.max_health, 0);
+
+ printf("\e[%u;%uH", y, x);
+
+ set_color(red, false);
+
+ int health = max(player.health, 0);
+
+ for (int i = 0; i < player.max_health; i++) {
+ if (i == health)
+ set_color(gray, false);
+ printf("♥ ");
+ }
+}
+
+__attribute__ ((constructor)) static void init()
+{
+ gray = get_color("#5A5A5A");
+
+ register_render_component(&render_healthbar);
+}
diff --git a/plugins/monster/Makefile b/plugins/monster/Makefile
index 28edde8..5cffca3 100644
--- a/plugins/monster/Makefile
+++ b/plugins/monster/Makefile
@@ -1,4 +1,4 @@
-plugins/monster/monster.so: plugins/monster/monster.c plugins/game/game.h
+plugins/monster/monster.so: plugins/monster/monster.c plugins/game/game.h plugins/score/score.h
cc -g -shared -fpic -o plugins/monster/monster.so plugins/monster/monster.c
PLUGINS := ${PLUGINS} plugins/monster/monster.so
diff --git a/plugins/monster/dependencies.txt b/plugins/monster/dependencies.txt
index dc22e61..3914551 100644
--- a/plugins/monster/dependencies.txt
+++ b/plugins/monster/dependencies.txt
@@ -1 +1,2 @@
game
+score
diff --git a/plugins/monster/monster.c b/plugins/monster/monster.c
index 59fa380..890e2bd 100644
--- a/plugins/monster/monster.c
+++ b/plugins/monster/monster.c
@@ -1,6 +1,7 @@
#include <stdlib.h>
#include <stddef.h>
#include "../game/game.h"
+#include "../score/score.h"
static struct entity monster;
diff --git a/plugins/movement/Makefile b/plugins/movement/Makefile
index 9d23279..c75d541 100644
--- a/plugins/movement/Makefile
+++ b/plugins/movement/Makefile
@@ -1,4 +1,4 @@
-plugins/movement/movement.so: plugins/movement/movement.c plugins/game/game.h
+plugins/movement/movement.so: plugins/movement/movement.c plugins/movement/movement.h plugins/game/game.h
cc -g -shared -fpic -o plugins/movement/movement.so plugins/movement/movement.c
PLUGINS := ${PLUGINS} plugins/movement/movement.so
diff --git a/plugins/score/Makefile b/plugins/score/Makefile
new file mode 100644
index 0000000..33400e5
--- /dev/null
+++ b/plugins/score/Makefile
@@ -0,0 +1,4 @@
+plugins/score/score.so: plugins/score/score.c plugins/score/score.h plugins/game/game.h
+ cc -g -shared -fpic -o plugins/score/score.so plugins/score/score.c
+
+PLUGINS := ${PLUGINS} plugins/score/score.so
diff --git a/plugins/score/dependencies.txt b/plugins/score/dependencies.txt
new file mode 100644
index 0000000..dc22e61
--- /dev/null
+++ b/plugins/score/dependencies.txt
@@ -0,0 +1 @@
+game
diff --git a/plugins/score/score.c b/plugins/score/score.c
new file mode 100644
index 0000000..7ad8b66
--- /dev/null
+++ b/plugins/score/score.c
@@ -0,0 +1,26 @@
+#include <stdio.h>
+#include "../game/game.h"
+
+static int score = 0;
+
+void add_score(int s)
+{
+ score += s;
+}
+
+int get_score()
+{
+ return score;
+}
+
+static void render_score(struct winsize ws)
+{
+ (void) ws;
+
+ printf("\e[32m\e[3mScore:\e[23m %d", score);
+}
+
+__attribute__ ((constructor)) static void init()
+{
+ register_render_component(&render_score);
+}
diff --git a/plugins/score/score.h b/plugins/score/score.h
new file mode 100644
index 0000000..8ee531a
--- /dev/null
+++ b/plugins/score/score.h
@@ -0,0 +1,7 @@
+#ifndef _SCORE_H_
+#define _SCORE_H_
+
+void add_score(int s);
+int get_score();
+
+#endif