changeset 484:f14b8290b3ce

examples: improve readability
author David Demelier <markand@malikania.fr>
date Mon, 27 Feb 2023 19:47:09 +0100
parents 6c06c82d276a
children 3ff1fe64d0cd
files examples/example-action/CMakeLists.txt examples/example-action/dialog.c examples/example-action/dialog.h examples/example-action/example-action.c libmlk-core/mlk/core/action-script.c libmlk-rpg/mlk/rpg/message.h
diffstat 6 files changed, 220 insertions(+), 157 deletions(-) [+]
line wrap: on
line diff
--- a/examples/example-action/CMakeLists.txt	Mon Feb 27 18:19:38 2023 +0100
+++ b/examples/example-action/CMakeLists.txt	Mon Feb 27 19:47:09 2023 +0100
@@ -22,6 +22,8 @@
 	SOURCES
 	${example-action_SOURCE_DIR}/chest.c
 	${example-action_SOURCE_DIR}/chest.h
+	${example-action_SOURCE_DIR}/dialog.c
+	${example-action_SOURCE_DIR}/dialog.h
 	${example-action_SOURCE_DIR}/example-action.c
 )
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/example-action/dialog.c	Mon Feb 27 19:47:09 2023 +0100
@@ -0,0 +1,90 @@
+/*
+ * dialog.c -- convenient message wrapper
+ *
+ * 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/example/example.h>
+
+#include "dialog.h"
+
+/* Message width is 80% of window width and height is auto computed. */
+#define QMW (MLK_EXAMPLE_W * 0.8)
+
+/* Position of each message. */
+#define QMX ((MLK_EXAMPLE_W - QMW) / 2)
+#define QMY (MLK_EXAMPLE_H * 0.2)
+
+/* Fading time and spacing. */
+#define QMD 250
+#define QMS 10
+
+static void
+handle(struct mlk_action *act, const union mlk_event *ev)
+{
+	struct dialog *dlg = act->data;
+
+	message_handle(&dlg->msg, ev);
+}
+
+static int
+update(struct mlk_action *act, unsigned int ticks)
+{
+	struct dialog *dlg = act->data;
+
+	return message_update(&dlg->msg, ticks);
+}
+
+static void
+draw(struct mlk_action *act)
+{
+	struct dialog *dlg = act->data;
+
+	message_draw(&dlg->msg);
+}
+
+static void
+end(struct mlk_action *act)
+{
+	struct dialog *dlg = act->data;
+
+	if ((dlg->msg.flags & MESSAGE_FLAGS_QUESTION) && dlg->response)
+		dlg->response(dlg, dlg->msg.index);
+}
+
+struct mlk_action *
+dialog_init(struct dialog *dlg)
+{
+	assert(dlg);
+
+	dlg->msg.x = QMX;
+	dlg->msg.y = QMY;
+	dlg->msg.w = QMW;
+	dlg->msg.delay = QMD;
+	dlg->msg.spacing = QMS;
+
+	message_start(&dlg->msg);
+	message_query(&dlg->msg, NULL, &dlg->msg.h);
+
+	dlg->action.data = dlg;
+	dlg->action.handle = handle;
+	dlg->action.update = update;
+	dlg->action.draw = draw;
+	dlg->action.end = end;
+
+	return &dlg->action;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/example-action/dialog.h	Mon Feb 27 19:47:09 2023 +0100
@@ -0,0 +1,39 @@
+/*
+ * dialog.h -- convenient message wrapper
+ *
+ * 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_DIALOG_H
+#define MLK_EXAMPLE_ACTION_DIALOG_H
+
+#include <mlk/core/action.h>
+
+#include <mlk/rpg/message.h>
+
+struct dialog {
+	/* public */
+	void *data;
+	void (*response)(struct dialog *, unsigned int);
+	struct message msg;
+
+	/* private */
+	struct mlk_action action;
+};
+
+struct mlk_action *
+dialog_init(struct dialog *);
+
+#endif /* !MLK_EXAMPLE_ACTION_DIALOG_H */
--- a/examples/example-action/example-action.c	Mon Feb 27 18:19:38 2023 +0100
+++ b/examples/example-action/example-action.c	Mon Feb 27 19:47:09 2023 +0100
@@ -41,17 +41,7 @@
 #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)
-
-/* Position of each message. */
-#define QMX ((MLK_EXAMPLE_W - QMW) / 2)
-#define QMY (MLK_EXAMPLE_H * 0.2)
-
-/* Fading time and spacing. */
-#define QMD 250
-#define QMS 10
+#include "dialog.h"
 
 static struct mlk_state *states[8];
 
@@ -66,18 +56,11 @@
 static struct chest chests[2];
 
 /*
- * This structure is the item that will be pushed into the mlk_action_script
+ * This structure is the dialog that will be pushed into the mlk_action_script
  * to create a sequence of message the user has to complete.
  */
-struct item {
-	struct message msg;
-	struct mlk_action act;
-};
 
-static struct mlk_action *chests_stack_actions[16] = {
-	[0] = &chests[0].action,
-	[1] = &chests[1].action
-};
+static struct mlk_action *chests_stack_actions[16];
 static struct mlk_action_stack chests_stack = {
 	.actions = chests_stack_actions,
 	.actionsz = MLK_UTIL_SIZE(chests_stack_actions)
@@ -91,14 +74,12 @@
 	.text = "Select your destiny."
 };
 
-static void     item_handle(struct mlk_action *, const union mlk_event *);
-static int      item_update(struct mlk_action *, unsigned int);
-static void     item_draw(struct mlk_action *);
+static void script_left_response(struct dialog *, unsigned int);
+static void script_right_response(struct dialog *, unsigned int);
 
-static void     response_quest1_start(struct mlk_action *);
-static void     response_quest2_start(struct mlk_action *);
+/* {{{ left chest script */
 
-static struct item quest1[] = {
+static struct dialog script_left[] = {
 	{
 		.msg = {
 			.flags = MESSAGE_FLAGS_FADEIN,
@@ -106,12 +87,6 @@
 			.lines = (const char *[]) {
 				"Welcome to this game."
 			}
-		},
-		.act = {
-			.data = &quest1[0].msg,
-			.handle = item_handle,
-			.update = item_update,
-			.draw = item_draw
 		}
 	},
 	{
@@ -122,15 +97,10 @@
 				"you must take this before going any further",
 				"Are you ready?"
 			}
-		},
-		.act = {
-			.data = &quest1[1].msg,
-			.handle = item_handle,
-			.update = item_update,
-			.draw = item_draw
 		}
 	},
 	{
+		.response = script_left_response,
 		.msg = {
 			.flags = MESSAGE_FLAGS_QUESTION,
 			.linesz = 2,
@@ -138,30 +108,36 @@
 				"Of course I am",
 				"No I'm not sure"
 			}
-		},
-		.act = {
-			.data = &quest1[2].msg,
-			.handle = item_handle,
-			.update = item_update,
-			.draw = item_draw,
-		}
-	},
-	/* Text will be replaced on start depending on the question. */
-	{
-		.msg = {
-			.flags = MESSAGE_FLAGS_FADEOUT
-		},
-		.act = {
-			.data = &quest1[3].msg,
-			.start = response_quest1_start,
-			.handle = item_handle,
-			.update = item_update,
-			.draw = item_draw
 		}
 	}
 };
 
-static struct item quest2[] = {
+static struct dialog script_left_responses[] = {
+	{
+		.msg = {
+			.flags = MESSAGE_FLAGS_FADEOUT,
+			.linesz = 1,
+			.lines = (const char *[]) {
+				 "Don't be so confident"
+			}
+		},
+	},
+	{
+		.msg = {
+			.flags = MESSAGE_FLAGS_FADEOUT,
+			.linesz = 1,
+			.lines = (const char *[]) {
+				 "Nevermind, I'll do it myself"
+			}
+		}
+	}
+};
+
+/* }}} */
+
+/* {{{ right chest script */
+
+static struct dialog script_right[] = {
 	{
 		.msg = {
 			.flags = MESSAGE_FLAGS_FADEIN,
@@ -169,15 +145,10 @@
 			.lines = (const char *[]) {
 				"Why did you select this chest?"
 			}
-		},
-		.act = {
-			.data = &quest2[0].msg,
-			.handle = item_handle,
-			.update = item_update,
-			.draw = item_draw
 		}
 	},
 	{
+		.response = script_right_response,
 		.msg = {
 			.flags = MESSAGE_FLAGS_QUESTION,
 			.linesz = 2,
@@ -185,30 +156,33 @@
 				"Because I think there was some gold",
 				"I have no freaking idea"
 			}
-		},
-		.act = {
-			.data = &quest2[1].msg,
-			.handle = item_handle,
-			.update = item_update,
-			.draw = item_draw,
-		}
-	},
-
-	/* See comment in quest 1. */
-	{
-		.msg = {
-			.flags = MESSAGE_FLAGS_FADEOUT
-		},
-		.act = {
-			.data = &quest2[2].msg,
-			.start = response_quest2_start,
-			.handle = item_handle,
-			.update = item_update,
-			.draw = item_draw
 		}
 	}
 };
 
+static struct dialog script_right_responses[] = {
+	{
+		.msg = {
+			.flags = MESSAGE_FLAGS_FADEOUT,
+			.linesz = 1,
+			.lines = (const char *[]) {
+				"Go away!"
+			}
+		},
+	},
+	{
+		.msg = {
+			.flags = MESSAGE_FLAGS_FADEOUT,
+			.linesz = 1,
+			.lines = (const char *[]) {
+				"Install OpenBSD then"
+			}
+		}
+	}
+};
+
+/* }}} */
+
 /*
  * This is the main script that the loop will execute, we will initialize it
  * depending on which chest the player clicks.
@@ -217,42 +191,33 @@
 static struct mlk_action_script script;
 
 static void
-item_handle(struct mlk_action *act, const union mlk_event *ev)
-{
-	message_handle(act->data, ev);
-}
-
-static int
-item_update(struct mlk_action *act, unsigned int ticks)
+script_left_response(struct dialog *dlg, unsigned int index)
 {
-	return message_update(act->data, ticks);
-}
+	(void)dlg;
 
-static void
-item_draw(struct mlk_action *act)
-{
-	message_draw(act->data);
+	mlk_action_script_append(&script, dialog_init(&script_left_responses[index]));
 }
 
 static void
-script_init_quest(struct item *m, size_t n)
+script_right_response(struct dialog *dlg, unsigned int index)
+{
+	(void)dlg;
+
+	mlk_action_script_append(&script, dialog_init(&script_right_responses[index]));
+}
+
+static void
+script_init(struct dialog *msgs, size_t msgsz)
 {
 	int err;
+	struct mlk_action *action;
 
-	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;
-		m[i].msg.w = QMW;
-		m[i].msg.delay = QMD;
-		m[i].msg.spacing = QMS;
+	for (size_t i = 0; i < msgsz; ++i) {
+		action = dialog_init(&msgs[i]);
 
-		message_start(&m[i].msg);
-		message_query(&m[i].msg, NULL, &m[i].msg.h);
-
-		if ((err = mlk_action_script_append(&script, &m[i].act)) < 0)
+		if ((err = mlk_action_script_append(&script, action)) < 0)
 			mlk_panicf("%s", mlk_err_string(err));
 	}
 
@@ -260,57 +225,19 @@
 }
 
 static void
-script_init_quest1(struct chest *chest)
+script_left_run(struct chest *chest)
 {
 	(void)chest;
 
-	script_init_quest(quest1, MLK_UTIL_SIZE(quest1));
-}
-
-static void
-script_init_quest2(struct chest *chest)
-{
-	(void)chest;
-
-	script_init_quest(quest2, MLK_UTIL_SIZE(quest2));
+	script_init(script_left, MLK_UTIL_SIZE(script_left));
 }
 
 static void
-response_quest1_start(struct mlk_action *act)
+script_right_run(struct chest *chest)
 {
-	static const char *line;
-
-	struct message *question = &quest1[2].msg;
-	struct message *cur = act->data;
-
-	cur->linesz = 1;
-	cur->lines = &line;
-
-	if (question->index == 0)
-		 line = "Don't be so confident";
-	else
-		 line = "Nevermind, I'll do it myself";
-
-	message_query(cur, NULL, &cur->h);
-}
+	(void)chest;
 
-static void
-response_quest2_start(struct mlk_action *act)
-{
-	static const char *line;
-
-	struct message *question = &quest2[1].msg;
-	struct message *cur = act->data;
-
-	cur->linesz = 1;
-	cur->lines = &line;
-
-	if (question->index == 0)
-		line = "Go away!";
-	else
-		line = "Install OpenBSD then";
-
-	message_query(cur, NULL, &cur->h);
+	script_init(script_right, MLK_UTIL_SIZE(script_right));
 }
 
 static void
@@ -328,11 +255,11 @@
 	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;
+	chests[0].run = script_left_run;
+	chests[1].run = script_right_run;
 
-	chest_init(&chests[0]);
-	chest_init(&chests[1]);
+	mlk_action_stack_add(&chests_stack, chest_init(&chests[0]));
+	mlk_action_stack_add(&chests_stack, chest_init(&chests[1]));
 }
 
 static void
--- a/libmlk-core/mlk/core/action-script.c	Mon Feb 27 18:19:38 2023 +0100
+++ b/libmlk-core/mlk/core/action-script.c	Mon Feb 27 19:47:09 2023 +0100
@@ -37,10 +37,13 @@
 mlk_action_script_init(struct mlk_action_script *s, struct mlk_action **actions, size_t max)
 {
 	assert(s);
-	
+
 	s->actions = actions;
 	s->max = max;
 	s->size = s->cur = 0;
+
+	for (size_t i = 0; i < max; ++i)
+		s->actions[i] = NULL;
 }
 
 void
--- a/libmlk-rpg/mlk/rpg/message.h	Mon Feb 27 18:19:38 2023 +0100
+++ b/libmlk-rpg/mlk/rpg/message.h	Mon Feb 27 19:47:09 2023 +0100
@@ -19,6 +19,8 @@
 #ifndef MLK_RPG_MESSAGE_H
 #define MLK_RPG_MESSAGE_H
 
+#include <stddef.h>
+
 #include <mlk/core/core.h>
 #include <mlk/core/texture.h>