changeset 64:da9b7462ab92

core: implement question, closes #2464 @2h
author David Demelier <markand@malikania.fr>
date Thu, 23 Jan 2020 20:44:01 +0100
parents ec0872aaee07
children 80a913d25aa9
files src/adventure/main.c src/core/message.c src/core/message.h
diffstat 3 files changed, 142 insertions(+), 60 deletions(-) [+]
line wrap: on
line diff
--- a/src/adventure/main.c	Thu Jan 23 13:48:49 2020 +0100
+++ b/src/adventure/main.c	Thu Jan 23 20:44:01 2020 +0100
@@ -16,8 +16,6 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-#include <stdio.h>
-
 #include "clock.h"
 #include "error.h"
 #include "event.h"
@@ -57,26 +55,25 @@
 	struct font *font;
 	struct texture *frame;
 
-	if (!(font = font_openf(sys_datapath("fonts/DejaVuSans.ttf"), 14)))
+	if (!(font = font_openf(sys_datapath("fonts/DejaVuSans.ttf"), 15)))
 		error_fatal();
 	if (!(frame = image_openf(sys_datapath("images/message.png"))))
 		error_fatal();
 
 	struct message msg = {
 		.text = {
-			"Hello Molko.",
-			"This is your unique adventure, you must listen to me.",
-			"Do not give up, please be brave.",
-			"Feel free to come back if you need assistance.",
-			"But be sure to take a look at the manual pages.",
-			"And don't forget to update."
+			"Flip a coin.",
+			"Try your best my friend."
 		},
-		.color = 0xd9caddff,
+		.colors = {
+			0xd9caddff,
+			0x94d5ffff
+		},
 		.font = font,
-		.frame = frame
+		.frame = frame,
+		.flags = MESSAGE_QUESTION
 	};
 
-
 	clock_start(&clock);
 	message_start(&msg);
 
@@ -90,11 +87,13 @@
 			if (ev.type == EVENT_QUIT)
 				return;
 
-			if (msg.state)
-				message_update(&msg, elapsed);
 			//game_handle(&ev);
+			message_handle(&msg, &ev);
 		}
-	
+
+		if (msg.state)
+			message_update(&msg, elapsed);
+
 		painter_set_color(0xffffffff);
 		painter_clear();
 
--- a/src/core/message.c	Thu Jan 23 13:48:49 2020 +0100
+++ b/src/core/message.c	Thu Jan 23 20:44:01 2020 +0100
@@ -18,6 +18,7 @@
 
 #include <assert.h>
 
+#include "event.h"
 #include "font.h"
 #include "message.h"
 #include "painter.h"
@@ -25,19 +26,19 @@
 #include "texture.h"
 #include "window.h"
 
-#define MESSAGE_SPEED   1000    /* Time delay for animations */
+#define MESSAGE_SPEED   150     /* Time delay for animations */
 #define MESSAGE_TIMEOUT 5000    /* Time for auto-closing */
 
 static unsigned int
-average_height(const struct message *msg)
+average(const struct message *msg)
 {
 	unsigned int n = 0;
 	unsigned int total = 0;
 
 	for (int i = 0; i < 6; ++i) {
-		if (msg->ttext[i]) {
+		if (msg->textures[i]) {
 			n += 1;
-			total += texture_height(msg->ttext[i]);
+			total += texture_height(msg->textures[i]);
 		}
 	}
 
@@ -45,15 +46,44 @@
 }
 
 static void
+clear(struct message *msg)
+{
+	for (unsigned int i = 0; i < 12; ++i) {
+		if (msg->textures[i]) {
+			texture_close(msg->textures[i]);
+			msg->textures[i] = NULL;
+		}
+	}
+}
+
+static void
 redraw(struct message *msg)
 {
+	clear(msg);
+
 	/* Generate textures if not already done. */
-	for (int i = 0; i < 6; ++i) {
-		if (!msg->text[i] || msg->ttext[i] || msg->stext[i])
+	for (unsigned int i = 0; i < 6; ++i) {
+		if (!msg->text[i])
 			continue;
 
-		msg->stext[i] = font_render(msg->font, msg->text[i], 0x000000ff);
-		msg->ttext[i] = font_render(msg->font, msg->text[i], msg->color);
+		/* Normal lines of text. */
+		unsigned long color = msg->colors[0];
+
+		if (msg->flags & MESSAGE_QUESTION && msg->index == i)
+			color = msg->colors[1];
+
+		if (!msg->textures[i])
+			msg->textures[i] = font_render(
+			    msg->font,
+			    msg->text[i],
+			    color
+			);
+		if (!msg->textures[i + 6])
+			msg->textures[i + 6] = font_render(
+			    msg->font,
+			    msg->text[i],
+			    0x000000ff
+			);
 	}
 }
 
@@ -63,8 +93,40 @@
 	assert(msg);
 
 	msg->elapsed = 0;
-	msg->alpha = 0;
 	msg->state = MESSAGE_OPENING;
+	msg->height[0] = texture_height(msg->frame);
+	msg->height[1] = 0;
+
+	redraw(msg);
+}
+
+void
+message_handle(struct message *msg, const union event *ev)
+{
+	assert(msg);
+	assert(ev);
+
+	if (ev->type != EVENT_KEYDOWN || msg->state == MESSAGE_NONE)
+		return;
+
+	switch (ev->key.key) {
+	case KEY_UP:
+		if (msg->index > 0)
+			msg->index--;
+		break;
+	case KEY_DOWN:
+		if (msg->index < 5 && msg->text[msg->index + 1])
+			msg->index++;
+		break;
+	case KEY_ENTER:
+		msg->state = MESSAGE_HIDING;
+		msg->elapsed = 0;
+		break;
+	default:
+		break;
+	}
+
+	redraw(msg);
 }
 
 bool
@@ -76,10 +138,10 @@
 
 	switch (msg->state) {
 	case MESSAGE_OPENING:
-		msg->alpha += 255 * ticks / MESSAGE_SPEED;
+		msg->height[1] += texture_height(msg->frame) * ticks / MESSAGE_SPEED;
 
-		if (msg->alpha > 255)
-			msg->alpha = 255;
+		if (msg->height[1] > msg->height[0])
+			msg->height[1] = msg->height[0];
 		if (msg->elapsed >= MESSAGE_SPEED) {
 			msg->state = MESSAGE_SHOWING;
 			msg->elapsed = 0;
@@ -95,6 +157,8 @@
 
 		break;
 	case MESSAGE_HIDING:
+		msg->height[1] -= texture_height(msg->frame) * ticks / MESSAGE_SPEED;
+
 		if (msg->elapsed >= MESSAGE_SPEED) {
 			msg->state = MESSAGE_NONE;
 			msg->elapsed = 0;
@@ -118,23 +182,31 @@
 	const unsigned int h = texture_height(msg->frame);
 	const unsigned int x = (window_width() / 2) - (w / 2);
 	const unsigned int y = 80;
-	const unsigned int avgh = average_height(msg);
+	const unsigned int avgh = average(msg);
 	const unsigned int gapy = (h - (avgh * 6)) / 7;
 
-	/* TODO: handle state */
-	redraw(msg);
-	texture_draw(msg->frame, x, y);
+	switch (msg->state) {
+	case MESSAGE_OPENING:
+	case MESSAGE_HIDING:
+		texture_draw_ex(msg->frame, 0, 0, w, msg->height[1], x, y, w, msg->height[1], 0);
+		break;
+	case MESSAGE_SHOWING:
+		texture_draw(msg->frame, x, y);
 
-	for (int i = 0; i < 6; ++i) {
-		/* TODO: avatar handling */
-		const int real_x = x + 20;
-		const int real_y = y + ((i + 1) * gapy) + (i * avgh);
+		for (int i = 0; i < 6; ++i) {
+			/* TODO: avatar handling */
+			const int real_x = x + 20;
+			const int real_y = y + ((i + 1) * gapy) + (i * avgh);
 
-		if (!msg->ttext[i])
-			continue;
+			if (!msg->textures[i])
+				continue;
 
-		texture_draw(msg->stext[i], real_x + 2, real_y + 2);
-		texture_draw(msg->ttext[i], real_x, real_y);
+			texture_draw(msg->textures[i + 6], real_x + 2, real_y + 2);
+			texture_draw(msg->textures[i], real_x, real_y);
+		}
+		break;
+	default:
+		break;
 	}
 }
 
@@ -152,14 +224,5 @@
 {
 	assert(msg);
 
-	for (int i = 0; i < 6; ++i) {
-		if (msg->ttext[i]) {
-			texture_close(msg->ttext[i]);
-			msg->ttext[i] = NULL;
-		}
-		if (msg->stext[i]) {
-			texture_close(msg->stext[i]);
-			msg->stext[i] = NULL;
-		}
-	}
+	clear(msg);
 }
--- a/src/core/message.h	Thu Jan 23 13:48:49 2020 +0100
+++ b/src/core/message.h	Thu Jan 23 20:44:01 2020 +0100
@@ -29,21 +29,24 @@
 struct texture;
 struct font;
 
+union event;
+
 /**
  * \brief Message flags.
  */
 enum message_flags {
-	MESSAGE_AUTOMATIC = (1 << 0)    /*!< Message will automatically close */
+	MESSAGE_AUTOMATIC       = (1 << 0),     /*!< Will automatically change state by itself. */
+	MESSAGE_QUESTION        = (1 << 1)      /*!< The message is a question. */
 };
 
 /**
  * \brief Message state.
  */
 enum message_state {
-	MESSAGE_NONE,                   /*!< Message hasn't start yet or is finished */
-	MESSAGE_OPENING,                /*!< Message animation is opening */
-	MESSAGE_SHOWING,                /*!< Message is displaying */
-	MESSAGE_HIDING                  /*!< Message animation for hiding */
+	MESSAGE_NONE,           /*!< Message hasn't start yet or is finished */
+	MESSAGE_OPENING,        /*!< Message animation is opening */
+	MESSAGE_SHOWING,        /*!< Message is displaying */
+	MESSAGE_HIDING          /*!< Message animation for hiding */
 };
 
 /**
@@ -57,15 +60,18 @@
 	struct texture *frame;          /*!< (RW) Frame to use */
 	struct texture *avatar;         /*!< (RW) Optional avatar */
 	struct font *font;              /*!< (RW) Font to use */
-	unsigned long color;            /*!< (RW) Font color to use */
+	unsigned long colors[2];        /*!< (RW) Normal/selected colors */
+	unsigned int index;             /*!< (RW) Line selected */
 	enum message_flags flags;       /*!< (RW) Message flags */
 	enum message_state state;       /*!< (RO) Current state */
 
-	/* PRIVATE */
-	struct texture *ttext[6];       /*!< (RW) Textures for every lines */
-	struct texture *stext[6];       /*!< (RW) Textures for every lines */
-	unsigned int elapsed;           /*!< (RW) Elapsed time while displaying */
-	unsigned int alpha;             /*!< (RO) Alpha progression */
+	/*! \cond PRIVATE */
+
+	struct texture *textures[12];
+	unsigned int elapsed;
+	int height[2];
+
+	/*! \endcond */
 };
 
 /**
@@ -79,6 +85,20 @@
 message_start(struct message *msg);
 
 /**
+ * Handle input events.
+ *
+ * This function will alter state of the message and change its selection in
+ * case of question.
+ *
+ * \pre msg != NULL
+ * \pre ev != NULL
+ * \param msg the message
+ * \param ev the event which occured
+ */
+void
+message_handle(struct message *msg, const union event *ev);
+
+/**
  * Update the message state and elapsed time..
  *
  * \pre msg != NULL