changeset 271:eadd3dbfa0af

adventure: add a basic chest
author David Demelier <markand@malikania.fr>
date Sat, 12 Dec 2020 12:14:44 +0100
parents 2d8d1cacda36
children a49ae1b6ea4f
files libmlk-adventure/CMakeLists.txt libmlk-adventure/adventure/actions/chest.c libmlk-adventure/adventure/actions/chest.h libmlk-adventure/adventure/assets.c libmlk-adventure/adventure/assets.h libmlk-data/sprites/chest.png libmlk-data/sprites/chest.xcf
diffstat 7 files changed, 221 insertions(+), 2 deletions(-) [+]
line wrap: on
line diff
--- a/libmlk-adventure/CMakeLists.txt	Sat Dec 12 12:14:34 2020 +0100
+++ b/libmlk-adventure/CMakeLists.txt	Sat Dec 12 12:14:44 2020 +0100
@@ -20,6 +20,8 @@
 
 set(
 	SOURCES
+	${libadventure_SOURCE_DIR}/adventure/actions/chest.c
+	${libadventure_SOURCE_DIR}/adventure/actions/chest.h
 	${libadventure_SOURCE_DIR}/adventure/actions/spawner.c
 	${libadventure_SOURCE_DIR}/adventure/actions/spawner.h
 	${libadventure_SOURCE_DIR}/adventure/actions/teleport.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libmlk-adventure/adventure/actions/chest.c	Sat Dec 12 12:14:44 2020 +0100
@@ -0,0 +1,153 @@
+/*
+ * chest.c -- chest object
+ *
+ * Copyright (c) 2020 David Demelier <markand@malikania.fr>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <core/animation.h>
+#include <core/event.h>
+#include <core/maths.h>
+#include <core/panic.h>
+#include <core/save.h>
+#include <core/sound.h>
+#include <core/sprite.h>
+
+#include <rpg/map.h>
+
+#include "chest.h"
+
+#define X(c)            ((c)->x - ((c)->map)->view_x)
+#define Y(c)            ((c)->y - ((c)->map)->view_y)
+#define W(c)            ((c)->animation.sprite->cellw)
+#define H(c)            ((c)->animation.sprite->cellh)
+#define TOLERANCE       (10)
+
+static bool
+is_near(const struct chest *c)
+{
+	const int x          = c->x - c->map->player_sprite->cellw - TOLERANCE;
+	const int y          = c->y - c->map->player_sprite->cellh - TOLERANCE;
+	const unsigned int w = W(c) + c->map->player_sprite->cellw + (TOLERANCE * 2);
+	const unsigned int h = H(c) + c->map->player_sprite->cellh + (TOLERANCE * 2);
+
+	return maths_is_boxed(x, y, w, h, c->map->player_x, c->map->player_y);
+}
+
+static void
+invoke(struct chest *c)
+{
+	c->state = CHEST_STATE_ANIMATE;
+
+	animation_start(&c->animation);
+
+	if (c->sound)
+		sound_play(c->sound, -1, 0);
+}
+
+static void
+handle(struct action *act, const union event *ev)
+{
+	struct chest *c = act->data;
+
+	if (!is_near(c) || c->state != CHEST_STATE_CLOSED)
+		return;
+
+	switch (ev->type) {
+	case EVENT_KEYDOWN:
+		if (ev->key.key == KEY_ENTER)
+			invoke(c);
+		break;
+	case EVENT_CLICKDOWN:
+		if (maths_is_boxed(X(c), Y(c), W(c), H(c), ev->click.x, ev->click.y))
+			invoke(c);
+		break;
+	default:
+		break;
+	}
+}
+
+static bool
+update(struct action *act, unsigned int ticks)
+{
+	struct chest *c = act->data;
+
+	if (c->state != CHEST_STATE_ANIMATE)
+		return false;
+
+	if (animation_update(&c->animation, ticks)) {
+		c->state = CHEST_STATE_OPEN;
+
+		if (c->exec)
+			c->exec(c);
+	}
+
+	return false;
+}
+
+static void
+draw(struct action *act)
+{
+	struct chest *c = act->data;
+
+	switch (c->state) {
+	case CHEST_STATE_OPEN:
+		sprite_draw(
+		    c->animation.sprite,
+		    c->animation.sprite->nrows - 1,
+		    c->animation.sprite->ncols - 1,
+		    X(c),
+		    Y(c)
+		);
+		break;
+	case CHEST_STATE_ANIMATE:
+		animation_draw(&c->animation, X(c), Y(c));
+		break;
+	default:
+		sprite_draw(c->animation.sprite, 0, 0, X(c), Y(c));
+		break;
+	}
+}
+
+void
+chest_init(struct chest *c)
+{
+	assert(c);
+
+	if (c->save && c->property) {
+		if (!save_get_property(c->save, c->property))
+			panic();
+
+		/* TODO: add an utility. */
+		if (strcmp(c->property->value, "true") == 0)
+			c->state = CHEST_STATE_OPEN;
+	}
+}
+
+struct action *
+chest_action(struct chest *c)
+{
+	assert(c);
+
+	c->action.data = c;
+	c->action.handle = handle;
+	c->action.update = update;
+	c->action.draw = draw;
+
+	return &c->action;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libmlk-adventure/adventure/actions/chest.h	Sat Dec 12 12:14:44 2020 +0100
@@ -0,0 +1,59 @@
+/*
+ * chest.h -- chest object
+ *
+ * Copyright (c) 2020 David Demelier <markand@malikania.fr>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef MOLKO_ADVENTURE_ACTIONS_CHEST_H
+#define MOLKO_ADVENTURE_ACTIONS_CHEST_H
+
+#include <core/action.h>
+#include <core/animation.h>
+
+struct map;
+struct sound;
+
+enum chest_state {
+	CHEST_STATE_CLOSED,
+	CHEST_STATE_ANIMATE,
+	CHEST_STATE_OPEN
+};
+
+struct chest {
+	/* Mandatory. */
+	int x;
+	int y;
+	struct map *map;
+	struct animation animation;
+
+	/* Defaulted. */
+	enum chest_state state;
+	struct action action;
+
+	/* Optional. */
+	struct save *save;
+	struct save_property *property;
+	struct sound *sound;
+	void *data;
+	void (*exec)(struct chest *);
+};
+
+void
+chest_init(struct chest *c);
+
+struct action *
+chest_action(struct chest *c);
+
+#endif /* !MOLKO_ADVENTURE_ACTIONS_CHEST_H */
--- a/libmlk-adventure/adventure/assets.c	Sat Dec 12 12:14:34 2020 +0100
+++ b/libmlk-adventure/adventure/assets.c	Sat Dec 12 12:14:44 2020 +0100
@@ -36,7 +36,8 @@
 	struct texture texture;
 	struct sprite sprite;
 } table_sprites[] = {
-	SPRITE(ASSETS_SPRITE_UI_CURSOR, "sprites/ui-cursor.png", 24, 24)
+	SPRITE(ASSETS_SPRITE_UI_CURSOR, "sprites/ui-cursor.png", 24, 24),
+	SPRITE(ASSETS_SPRITE_CHEST, "sprites/chest.png", 32, 32)
 };
 
 struct sprite *assets_sprites[ASSETS_SPRITE_NUM] = {0};
--- a/libmlk-adventure/adventure/assets.h	Sat Dec 12 12:14:34 2020 +0100
+++ b/libmlk-adventure/adventure/assets.h	Sat Dec 12 12:14:44 2020 +0100
@@ -19,11 +19,15 @@
 #ifndef MOLKO_ADVENTURE_ASSETS_H
 #define MOLKO_ADVENTURE_ASSETS_H
 
-#include <core/sprite.h>
+struct sprite;
 
 enum assets_sprite {
 	/* UI elements. */
 	ASSETS_SPRITE_UI_CURSOR,
+
+	/* Actions. */
+	ASSETS_SPRITE_CHEST,
+
 	ASSETS_SPRITE_NUM
 };
 
Binary file libmlk-data/sprites/chest.png has changed
Binary file libmlk-data/sprites/chest.xcf has changed