changeset 481:4b99b760e99c

examples: add chest for simplicity
author David Demelier <markand@malikania.fr>
date Mon, 27 Feb 2023 17:57:13 +0100
parents c1f64d451230
children f78455f45bf6
files examples/example-action/CMakeLists.txt examples/example-action/chest.c examples/example-action/chest.h examples/example-action/example-action.c
diffstat 4 files changed, 183 insertions(+), 85 deletions(-) [+]
line wrap: on
line diff
--- a/examples/example-action/CMakeLists.txt	Mon Feb 27 17:26:00 2023 +0100
+++ b/examples/example-action/CMakeLists.txt	Mon Feb 27 17:57:13 2023 +0100
@@ -20,6 +20,8 @@
 
 set(
 	SOURCES
+	${example-action_SOURCE_DIR}/chest.c
+	${example-action_SOURCE_DIR}/chest.h
 	${example-action_SOURCE_DIR}/example-action.c
 )
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/example-action/chest.c	Mon Feb 27 17:57:13 2023 +0100
@@ -0,0 +1,115 @@
+/*
+ * chest.c -- animated chest
+ *
+ * Copyright (c) 2020-2023 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 <mlk/core/event.h>
+#include <mlk/core/maths.h>
+#include <mlk/core/sprite.h>
+
+#include <mlk/example/registry.h>
+
+#include "chest.h"
+
+#define CHEST_DELAY 80
+
+static void
+handle(struct mlk_action *act, const union mlk_event *ev)
+{
+	struct chest *chest = act->data;
+	unsigned int cw, ch;
+
+	/* Make sure that we don't operate on a already opened chest. */
+	if (chest->state == CHEST_STATE_OPENED)
+		return;
+
+	/*
+	 * We are only interested if the event is a click on the chest itself
+	 * so we have to test because actions have no notion of geometry.
+	 */
+	if (ev->type != MLK_EVENT_CLICKDOWN)
+		return;
+
+	cw = registry_sprites[REGISTRY_TEXTURE_CHEST].cellw;
+	ch = registry_sprites[REGISTRY_TEXTURE_CHEST].cellh;
+
+	if (!mlk_maths_is_boxed(chest->x, chest->y, cw, ch, ev->click.x, ev->click.y))
+		return;
+
+	mlk_animation_start(&chest->animation);
+	chest->state = CHEST_STATE_OPENING;
+}
+
+static int
+update(struct mlk_action *act, unsigned int ticks)
+{
+	struct chest *chest = act->data;
+
+	if (chest->state != CHEST_STATE_OPENING)
+		return 0;
+
+	if (mlk_animation_update(&chest->animation, ticks)) {
+		chest->state = CHEST_STATE_OPENED;
+
+		if (chest->run)
+			chest->run(chest);
+	}
+
+	/* The chest never dies. */
+	return 0;
+}
+
+static void
+draw(struct mlk_action *act)
+{
+	const struct chest *chest = act->data;
+
+	switch (chest->state) {
+	case CHEST_STATE_CLOSED:
+		mlk_sprite_draw(chest->animation.sprite, 0, 0, chest->x, chest->y);
+		break;
+	case CHEST_STATE_OPENING:
+		mlk_animation_draw(&chest->animation, chest->x, chest->y);
+		break;
+	case CHEST_STATE_OPENED:
+		mlk_sprite_draw(chest->animation.sprite,
+		    chest->animation.sprite->nrows - 1,
+		    chest->animation.sprite->ncols - 1,
+		    chest->x,
+		    chest->y);
+		break;
+	default:
+		break;
+	}
+}
+
+struct mlk_action *
+chest_init(struct chest *chest)
+{
+	assert(chest);
+
+	chest->state = CHEST_STATE_CLOSED;
+	chest->action.data = chest;
+	chest->action.handle = handle;
+	chest->action.update = update;
+	chest->action.draw = draw;
+
+	mlk_animation_init(&chest->animation, &registry_sprites[REGISTRY_TEXTURE_CHEST], CHEST_DELAY);
+
+	return &chest->action;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/example-action/chest.h	Mon Feb 27 17:57:13 2023 +0100
@@ -0,0 +1,48 @@
+/*
+ * chest.h -- animated chest
+ *
+ * Copyright (c) 2020-2023 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 MLK_EXAMPLE_ACTION_CHEST_H
+#define MLK_EXAMPLE_ACTION_CHEST_H
+
+#include <mlk/core/action.h>
+#include <mlk/core/animation.h>
+
+enum chest_state {
+	CHEST_STATE_CLOSED,
+	CHEST_STATE_OPENING,
+	CHEST_STATE_OPENED
+};
+
+struct chest {
+	/* public */
+	int x;
+	int y;
+	void *data;
+	enum chest_state state;
+	void (*run)(struct chest *);
+	void (*finish)(struct chest *);
+
+	/* private */
+	struct mlk_animation animation;
+	struct mlk_action action;
+};
+
+struct mlk_action *
+chest_init(struct chest *chest);
+
+#endif /* !MLK_EXAMPLE_ACTION_CHEST_H */
--- a/examples/example-action/example-action.c	Mon Feb 27 17:26:00 2023 +0100
+++ b/examples/example-action/example-action.c	Mon Feb 27 17:57:13 2023 +0100
@@ -24,7 +24,6 @@
 #include <mlk/core/err.h>
 #include <mlk/core/event.h>
 #include <mlk/core/game.h>
-#include <mlk/core/maths.h>
 #include <mlk/core/painter.h>
 #include <mlk/core/panic.h>
 #include <mlk/core/sprite.h>
@@ -41,6 +40,8 @@
 
 #include <mlk/rpg/message.h>
 
+#include "chest.h"
+
 /* Message width is 80% of window width and height is auto computed. */
 #define QMW (MLK_EXAMPLE_W * 0.8)
 
@@ -61,33 +62,8 @@
  * For convenience, we arrange those two chests into a mlk_action_stack to
  * avoid calling all mlk_action functions for every chests.
  */
-static void chest_handle(struct mlk_action *, const union mlk_event *);
-static void chest_draw(struct mlk_action *);
 
-static struct chest {
-	int x;
-	int y;
-	int open;
-	struct mlk_sprite *sprite;
-	struct mlk_action action;
-} chests[2] = {
-	[0] = {
-		.sprite = &registry_sprites[REGISTRY_TEXTURE_CHEST],
-		.action = {
-			.data = &chests[0],
-			.draw = chest_draw,
-			.handle = chest_handle,
-		}
-	},
-	[1] = {
-		.sprite = &registry_sprites[REGISTRY_TEXTURE_CHEST],
-		.action = {
-			.data = &chests[1],
-			.draw = chest_draw,
-			.handle = chest_handle,
-		}
-	}
-};
+static struct chest chests[2];
 
 /*
  * This structure is the item that will be pushed into the mlk_action_script
@@ -119,9 +95,6 @@
 static int      item_update(struct mlk_action *, unsigned int);
 static void     item_draw(struct mlk_action *);
 
-static void     script_init_quest1(void);
-static void     script_init_quest2(void);
-
 static void     response_quest1_start(struct mlk_action *);
 static void     response_quest2_start(struct mlk_action *);
 
@@ -244,59 +217,6 @@
 static struct mlk_action_script script;
 
 static void
-chest_handle(struct mlk_action *act, const union mlk_event *ev)
-{
-	struct chest *chest = act->data;
-	unsigned int cw, ch;
-
-	/* Make sure that we don't operate on a already opened chest. */
-	if (chest->open)
-		return;
-
-	/*
-	 * We are only interested if the event is a click on the chest itself
-	 * so we have to test because actions have no notion of geometry.
-	 */
-	if (ev->type != MLK_EVENT_CLICKDOWN)
-		return;
-
-	cw = registry_sprites[REGISTRY_TEXTURE_CHEST].cellw;
-	ch = registry_sprites[REGISTRY_TEXTURE_CHEST].cellh;
-
-	if (!mlk_maths_is_boxed(chest->x, chest->y, cw, ch, ev->click.x, ev->click.y))
-		return;
-
-	/* Also, make sure that we don't operate on a already opened chest. */
-	chest->open = 1;
-
-	/*
-	 * Now depending on the chest, update the main script with actual code
-	 * we're interested in.
-	 */
-	memset(script_actions, 0, sizeof (script_actions));
-	mlk_action_script_init(&script, script_actions, MLK_UTIL_SIZE(script_actions));
-
-	if (chest == &chests[0])
-		script_init_quest1();
-	else
-		script_init_quest2();
-}
-
-static void
-chest_draw(struct mlk_action *act)
-{
-	const struct chest *chest = act->data;
-	int column;
-
-	if (chest->open)
-		column = 3;
-	else
-		column = 0;
-
-	mlk_sprite_draw(chest->sprite, 0, column, chest->x, chest->y);
-}
-
-static void
 item_handle(struct mlk_action *act, const union mlk_event *ev)
 {
 	message_handle(act->data, ev);
@@ -319,6 +239,9 @@
 {
 	int err;
 
+	memset(script_actions, 0, sizeof (script_actions));
+	mlk_action_script_init(&script, script_actions, MLK_UTIL_SIZE(script_actions));
+
 	for (size_t i = 0; i < n; ++i) {
 		m[i].msg.x = QMX;
 		m[i].msg.y = QMY;
@@ -337,14 +260,18 @@
 }
 
 static void
-script_init_quest1(void)
+script_init_quest1(struct chest *chest)
 {
+	(void)chest;
+
 	script_init_quest(quest1, MLK_UTIL_SIZE(quest1));
 }
 
 static void
-script_init_quest2(void)
+script_init_quest2(struct chest *chest)
 {
+	(void)chest;
+
 	script_init_quest(quest2, MLK_UTIL_SIZE(quest2));
 }
 
@@ -400,6 +327,12 @@
 	    0, 0, MLK_EXAMPLE_W / 2, MLK_EXAMPLE_H);
 	align(ALIGN_CENTER, &chests[1].x, &chests[1].y, cw, ch,
 	    MLK_EXAMPLE_W / 2, 0, MLK_EXAMPLE_W / 2, MLK_EXAMPLE_H);
+
+	chests[0].run = script_init_quest1;
+	chests[1].run = script_init_quest2;
+
+	chest_init(&chests[0]);
+	chest_init(&chests[1]);
 }
 
 static void