changeset 62:d07acc6ee4d9

core: improve message
author David Demelier <markand@malikania.fr>
date Thu, 23 Jan 2020 13:48:31 +0100
parents 8d34a12484db
children ec0872aaee07
files assets/images/message.png assets/images/message.xcf src/adventure/main.c src/core/message.c src/core/message.h
diffstat 5 files changed, 150 insertions(+), 27 deletions(-) [+]
line wrap: on
line diff
Binary file assets/images/message.png has changed
Binary file assets/images/message.xcf has changed
--- a/src/adventure/main.c	Wed Jan 22 12:12:25 2020 +0100
+++ b/src/adventure/main.c	Thu Jan 23 13:48:31 2020 +0100
@@ -21,10 +21,13 @@
 #include "clock.h"
 #include "error.h"
 #include "event.h"
+#include "font.h"
 #include "game.h"
 #include "image.h"
 #include "map.h"
 #include "map_state.h"
+#include "message.h"
+#include "painter.h"
 #include "splashscreen_state.h"
 #include "sprite.h"
 #include "sys.h"
@@ -51,8 +54,31 @@
 {
 	union event ev;
 	struct clock clock;
+	struct font *font;
+	struct texture *frame;
+
+	if (!(font = font_openf(sys_datapath("fonts/DejaVuSans.ttf"), 14)))
+		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."
+		},
+		.color = 0xd9caddff,
+		.font = font,
+		.frame = frame
+	};
+
 
 	clock_start(&clock);
+	message_start(&msg);
 
 	for (;;) {
 		unsigned int elapsed = clock_elapsed(&clock);
@@ -64,11 +90,20 @@
 			if (ev.type == EVENT_QUIT)
 				return;
 
-			game_handle(&ev);
+			if (msg.state)
+				message_update(&msg, elapsed);
+			//game_handle(&ev);
 		}
+	
+		painter_set_color(0xffffffff);
+		painter_clear();
 
-		game_update(elapsed);
-		game_draw();
+		if (msg.state)
+			message_draw(&msg);
+		//game_update(elapsed);
+		//game_draw();
+
+		painter_present();
 
 		if ((elapsed = clock_elapsed(&clock)) < 20)
 			delay(20 - elapsed);
--- a/src/core/message.c	Wed Jan 22 12:12:25 2020 +0100
+++ b/src/core/message.c	Thu Jan 23 13:48:31 2020 +0100
@@ -23,16 +23,47 @@
 #include "painter.h"
 #include "sprite.h"
 #include "texture.h"
+#include "window.h"
 
 #define MESSAGE_SPEED   1000    /* Time delay for animations */
 #define MESSAGE_TIMEOUT 5000    /* Time for auto-closing */
 
+static unsigned int
+average_height(const struct message *msg)
+{
+	unsigned int n = 0;
+	unsigned int total = 0;
+
+	for (int i = 0; i < 6; ++i) {
+		if (msg->ttext[i]) {
+			n += 1;
+			total += texture_height(msg->ttext[i]);
+		}
+	}
+
+	return n > 0 ? total / n : 0;
+}
+
+static void
+redraw(struct message *msg)
+{
+	/* Generate textures if not already done. */
+	for (int i = 0; i < 6; ++i) {
+		if (!msg->text[i] || msg->ttext[i] || msg->stext[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);
+	}
+}
+
 void
 message_start(struct message *msg)
 {
 	assert(msg);
 
 	msg->elapsed = 0;
+	msg->alpha = 0;
 	msg->state = MESSAGE_OPENING;
 }
 
@@ -45,45 +76,65 @@
 
 	switch (msg->state) {
 	case MESSAGE_OPENING:
-		if (msg->elapsed >= MESSAGE_SPEED)
+		msg->alpha += 255 * ticks / MESSAGE_SPEED;
+
+		if (msg->alpha > 255)
+			msg->alpha = 255;
+		if (msg->elapsed >= MESSAGE_SPEED) {
 			msg->state = MESSAGE_SHOWING;
+			msg->elapsed = 0;
+		}
+
 		break;
 	case MESSAGE_SHOWING:
 		/* Do automatically switch state if requested by the user. */
-		if (msg->flags & MESSAGE_AUTOMATIC && msg->elapsed >= MESSAGE_TIMEOUT)
+		if (msg->flags & MESSAGE_AUTOMATIC && msg->elapsed >= MESSAGE_TIMEOUT) {
 			msg->state = MESSAGE_HIDING;
+			msg->elapsed = 0;
+		}
+
+		break;
+	case MESSAGE_HIDING:
+		if (msg->elapsed >= MESSAGE_SPEED) {
+			msg->state = MESSAGE_NONE;
+			msg->elapsed = 0;
+		}
 
 		break;
 	default:
 		break;
 	}
 
-	return msg->state == MESSAGE_HIDING && msg->elapsed >= MESSAGE_SPEED;
+	return msg->state == MESSAGE_NONE;
 }
 
 void
 message_draw(struct message *msg)
 {
 	assert(msg);
+	assert(msg->frame);
 
-	/* TODO: draw states! */
-	/* TODO: more constant variables. */
-	struct texture *lines[3];
-	int x = 160;
-	int y = 80;
+	const unsigned int w = texture_width(msg->frame);
+	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 gapy = (h - (avgh * 6)) / 7;
 
-	painter_set_color(0xff0000ff);
-	painter_draw_rectangle(true, x, y, 960, 160);
+	/* TODO: handle state */
+	redraw(msg);
+	texture_draw(msg->frame, x, y);
 
-	for (int i = 0; msg->text[i]; ++i) {
-		lines[i] = font_render(msg->font, msg->text[i], 0xffffffff);
+	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 (!lines[i])
+		if (!msg->ttext[i])
 			continue;
 
-		texture_draw(lines[i], x, y);
-		texture_close(lines[i]);
-		y += 53;
+		texture_draw(msg->stext[i], real_x + 2, real_y + 2);
+		texture_draw(msg->ttext[i], real_x, real_y);
 	}
 }
 
@@ -92,5 +143,23 @@
 {
 	assert(msg);
 
+	msg->state = MESSAGE_HIDING;
 	msg->elapsed = 0;
 }
+
+void
+message_close(struct message *msg)
+{
+	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;
+		}
+	}
+}
--- a/src/core/message.h	Wed Jan 22 12:12:25 2020 +0100
+++ b/src/core/message.h	Thu Jan 23 13:48:31 2020 +0100
@@ -26,7 +26,7 @@
 
 #include <stdbool.h>
 
-struct sprite;
+struct texture;
 struct font;
 
 /**
@@ -40,6 +40,7 @@
  * \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 */
@@ -47,15 +48,24 @@
 
 /**
  * \brief Message object.
+ *
+ * This structure is used to display a message into the screen. It does not own
+ * any user properties and therefore must exist while using it.
  */
 struct message {
-	const char *text[3];            /*!< (RW) lines of text to show */
-	struct sprite *theme;           /*!< (RW) sprite to use for the frame */
-	struct texture *avatar;         /*!< (RW) optional avatar */
-	struct font *font;              /*!< (RW) font to use */
-	enum message_flags flags;       /*!< (RW) message flags */
-	enum message_state state;       /*!< (RO) current state */
-	unsigned int elapsed;           /*!< (RW) elapsed time while displaying */
+	const char *text[6];            /*!< (RW) Lines of text to show */
+	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 */
+	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 */
 };
 
 /**
@@ -99,4 +109,13 @@
 void
 message_hide(struct message *msg);
 
+/**
+ * Destroy owned resources.
+ *
+ * \pre msg != NULL
+ * \param msg the message
+ */
+void
+message_finish(struct message *msg);
+
 #endif /* !MOLKO_MESSAGE_H */