changeset 44:c97fe725fdeb

core: implement basic states, closes #2457 @1h
author David Demelier <markand@malikania.fr>
date Wed, 15 Jan 2020 21:31:17 +0100
parents 291be94202c7
children e10fd1b6323f
files Makefile src/game.c src/game.h src/main.c src/state.h
diffstat 5 files changed, 235 insertions(+), 124 deletions(-) [+]
line wrap: on
line diff
--- a/Makefile	Wed Jan 15 20:54:53 2020 +0100
+++ b/Makefile	Wed Jan 15 21:31:17 2020 +0100
@@ -27,6 +27,7 @@
                 src/error.c \
                 src/event.c \
                 src/font.c \
+                src/game.c \
                 src/image.c \
                 src/map.c \
                 src/message.c \
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/game.c	Wed Jan 15 21:31:17 2020 +0100
@@ -0,0 +1,58 @@
+/*
+ * game.c -- main game 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 <stddef.h>
+
+#include "game.h"
+#include "state.h"
+
+struct game game = {
+	.state = NULL,
+	.state_next = NULL
+};
+
+void
+game_handle(const union event *event)
+{
+	if (game.state)
+		game.state->handle(event);
+}
+
+void
+game_update(unsigned int ticks)
+{
+	/* Change state if any. */
+	if (game.state_next) {
+		/* Inform the current state we're gonna leave it. */
+		if (game.state)
+			game.state->leave();
+
+		game.state = game.state_next;
+		game.state->enter();
+	}
+
+	if (game.state)
+		game.state->update(ticks);
+}
+
+void
+game_draw(void)
+{
+	if (game.state)
+		game.state->draw();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/game.h	Wed Jan 15 21:31:17 2020 +0100
@@ -0,0 +1,67 @@
+/*
+ * game.h -- main game 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_GAME_H
+#define MOLKO_GAME_H
+
+/**
+ * \file game.h
+ * \brief Main game object.
+ */
+
+struct state;
+
+union event;
+
+/**
+ * \brief Main game object.
+ */
+struct game {
+	/* Game states */
+	struct state *state;            /*!< (RO) Current state  */
+	struct state *state_next;       /*!< (RO) Next state */
+};
+
+/**
+ * Global game object.
+ */
+extern struct game game;
+
+/**
+ * Handle input event.
+ *
+ * \param event the event
+ */
+void
+game_handle(const union event *event);
+
+/**
+ * Update the game state.
+ *
+ * \param ticks the number of milliseconds between last frame
+ */
+void
+game_update(unsigned int ticks);
+
+/**
+ * Draw the game using the current state.
+ */
+void
+game_draw(void);
+
+#endif /* !MOLKO_GAME_H */
--- a/src/main.c	Wed Jan 15 20:54:53 2020 +0100
+++ b/src/main.c	Wed Jan 15 21:31:17 2020 +0100
@@ -16,20 +16,57 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-#include <stdio.h>
-#include <stdlib.h>
-
 #include "clock.h"
+#include "game.h"
 #include "error.h"
 #include "event.h"
-#include "painter.h"
-#include "image.h"
-#include "map.h"
 #include "sys.h"
-#include "walksprite.h"
 #include "window.h"
-#include "util.h"
-#include "texture.h"
+
+#define WINDOW_WIDTH 1280
+#define WINDOW_HEIGHT 720
+
+static void
+init(void)
+{
+	if (!sys_init())
+		error_fatal();
+	if (!window_init("Molko's Adventure", WINDOW_WIDTH, WINDOW_HEIGHT))
+		error_fatal();
+}
+
+static void
+run(void)
+{
+	union event ev;
+	struct clock clock;
+
+	clock_start(&clock);
+
+	for (;;) {
+		uint64_t elapsed = clock_elapsed(&clock);
+
+		clock_start(&clock);
+
+		while (event_poll(&ev)) {
+			/* TODO: this must be handled by states. */
+			if (ev.type == EVENT_QUIT)
+				return;
+
+			game_handle(&ev);
+		}
+
+		game_update(elapsed);
+		game_draw();
+	}
+}
+
+static void
+close(void)
+{
+	window_close();
+	sys_close();
+}
 
 int
 main(int argc, char **argv)
@@ -37,121 +74,9 @@
 	(void)argc;
 	(void)argv;
 
-	struct texture *tex;
-
-	if (!sys_init())
-		error_fatal();
-	if (!window_init("Molko's Adventure", 1024, 576))
-		error_fatal();
-	if (!(tex = texture_new(100, 100)))
-		error_fatal();
-
-	painter_set_color(0xffffffff);
-	painter_clear();
-
-	PAINTER_BEGIN(tex);
-	painter_set_color(0xff0000ff);
-	painter_clear();
-	PAINTER_END();
-
-	texture_draw(tex, 10, 10);
-	painter_present();
-	delay(5000);
-
-#if 0
-
-	struct clock clock;
-	struct map map;
-	struct texture *guy;
-	struct sprite sprite;
-	struct walksprite ws;
-
-	if (!sys_init())
-		error_fatal();
-	if (!window_init("Molko's Adventure", 1024, 576))
-		error_fatal();
-	if (!map_open(&map, "world.json"))
-		error_fatal();
-	if (!(guy = image_openf(sys_datapath("sprites/test-walk.png"))))
-		error_fatal();
-
-	sprite_init(&sprite, guy, 48, 48);
-	walksprite_init(&ws, &sprite, 200);
-	clock_start(&clock);
-	map_repaint(&map);
-
-	int guy_x = 10;
-	int guy_y = 10;
-	int guy_dx = 0;
-	int guy_dy = 0;
-
-	int dx = 0;
-	int dy = 0;
-	int orientation = 0;
-
-	for (;;) {
-		uint64_t elapsed = clock_elapsed(&clock);
-		union event ev;
-
-		clock_start(&clock);
-
-		while (event_poll(&ev)) {
-			switch (ev.type) {
-			case EVENT_QUIT:
-				return 0;
-			case EVENT_KEYDOWN:
-				switch (ev.key.key) {
-				case KEY_UP:
-					orientation = 0;
-					dy = -5;
-					break;
-				case KEY_RIGHT:
-					orientation = 2;
-					dx = 5;
-					break;
-				case KEY_DOWN:
-					orientation = 4;
-					dy = 5;
-					break;
-				case KEY_LEFT:
-					orientation = 6;
-					dx = -5;
-					break;
-				default:
-					break;
-				}
-				break;
-			case EVENT_KEYUP:
-				switch (ev.key.key) {
-				case KEY_DOWN:
-					dy = 0;
-					break;
-				case KEY_UP:
-					dy = 0;
-					break;
-				case KEY_LEFT:
-					dx = 0;
-					break;
-				case KEY_RIGHT:
-					dx = 0;
-					break;
-				default:
-					break;
-				}
-				break;
-			default:
-				break;
-			}
-		}
-
-		walksprite_update(&ws, elapsed);
-		painter_clear();
-		map_draw(&map);
-		walksprite_draw(&ws, orientation, 100, 100);
-		painter_present();
-		delay(50);
-	}
-#endif
+	init();
+	run();
+	close();
 
 	return 0;
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/state.h	Wed Jan 15 21:31:17 2020 +0100
@@ -0,0 +1,60 @@
+/*
+ * state.h -- abstract state
+ *
+ * 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_STATE_H
+#define MOLKO_STATE_H
+
+/**
+ * \file state.h
+ * \brief Abstract state.
+ */
+
+union event;
+
+/**
+ * \brief Abstract state.
+ */
+struct state {
+	/**
+	 * This function is called when the state is entered.
+	 */
+	void (*enter)(void);
+
+	/**
+	 * This function is called when the state is about to be left.
+	 */
+	void (*leave)(void);
+
+	/**
+	 * This function is called for each event that happened.
+	 */
+	void (*handle)(const union event *);
+
+	/**
+	 * This function is called to update the game, with the number of
+	 * milliseconds since the last frame.
+	 */
+	void (*update)(unsigned int ticks);
+
+	/**
+	 * This function is supposed to draw the game.
+	 */
+	void (*draw)(void);
+};
+
+#endif /* !MOLKO_STATE_H */