changeset 299:648f5f949afb

core: implement stackable states
author David Demelier <markand@malikania.fr>
date Sun, 11 Apr 2021 16:41:34 +0200
parents 196264679079
children 3638b39ef2bf
files libmlk-adventure/adventure/action/spawner.c libmlk-adventure/adventure/molko.c libmlk-adventure/adventure/state/battle.c libmlk-adventure/adventure/state/continue.c libmlk-adventure/adventure/state/mainmenu.c libmlk-adventure/adventure/state/map.c libmlk-adventure/adventure/state/splashscreen.c libmlk-core/core/game.c libmlk-core/core/game.h libmlk-core/core/state.c libmlk-core/core/state.h libmlk-data/maps/map-world.json
diffstat 12 files changed, 78 insertions(+), 88 deletions(-) [+]
line wrap: on
line diff
--- a/libmlk-adventure/adventure/action/spawner.c	Wed Mar 10 18:49:08 2021 +0100
+++ b/libmlk-adventure/adventure/action/spawner.c	Sun Apr 11 16:41:34 2021 +0200
@@ -46,9 +46,8 @@
 }
 
 static void
-fight(void)
+fight(struct spawner *s)
 {
-	/* TODO: */
 	struct battle *bt;
 
 	bt = alloc_new0(sizeof (*bt));
@@ -87,8 +86,8 @@
 		s->last_y = s->map->player_y;
 
 		if (s->steps == 0) {
-			s->steps = util_nrand(s->low, s->high);
-			fight();
+			spawner_init(s);
+			fight(s);
 		}
 	}
 
--- a/libmlk-adventure/adventure/molko.c	Wed Mar 10 18:49:08 2021 +0100
+++ b/libmlk-adventure/adventure/molko.c	Sun Apr 11 16:41:34 2021 +0200
@@ -85,7 +85,7 @@
 	assets_init();
 
 	/* Start to splash. */
-	game_switch(state_mainmenu_new(), 1);
+	game_push(state_mainmenu_new());
 	molko.team.members[0] = &character_neth;
 	molko.team.members[1] = &character_neth;
 	inventory_add(&molko.inventory, &item_potion, 100);
@@ -108,7 +108,7 @@
 		for (union event ev; event_poll(&ev); )
 			continue;
 
-		game_switch(molko.panic, 1);
+		game_push(molko.panic);
 		game_loop();
 	}
 }
@@ -118,7 +118,7 @@
 {
 	molko.state = MOLKO_STATE_MAP;
 
-	game_switch(state_map_new(map, origin_x, origin_y), 0);
+	game_push(state_map_new(map, origin_x, origin_y));
 	game.inhibit = INHIBIT_NONE;
 }
 
@@ -127,7 +127,7 @@
 {
 	molko.state = MOLKO_STATE_BATTLE;
 
-	game_switch(state_battle_new(bt), 0);
+	game_push(state_battle_new(bt));
 }
 
 const char *
--- a/libmlk-adventure/adventure/state/battle.c	Wed Mar 10 18:49:08 2021 +0100
+++ b/libmlk-adventure/adventure/state/battle.c	Sun Apr 11 16:41:34 2021 +0200
@@ -56,7 +56,7 @@
 
 	/* TODO: once we have stacked states, pop it. */
 	if (battle_update(self->battle, ticks))
-		game_quit();
+		game_pop();
 }
 
 static void
--- a/libmlk-adventure/adventure/state/continue.c	Wed Mar 10 18:49:08 2021 +0100
+++ b/libmlk-adventure/adventure/state/continue.c	Sun Apr 11 16:41:34 2021 +0200
@@ -52,7 +52,7 @@
 		break;
 	case EVENT_KEYDOWN:
 		if (ev->key.key == KEY_ESCAPE)
-			game_switch(state_mainmenu_new(), 0);
+			game_push(state_mainmenu_new());
 		else
 			selected = dialog_save_handle(&self->dialog, ev);
 		break;
--- a/libmlk-adventure/adventure/state/mainmenu.c	Wed Mar 10 18:49:08 2021 +0100
+++ b/libmlk-adventure/adventure/state/mainmenu.c	Sun Apr 11 16:41:34 2021 +0200
@@ -76,7 +76,7 @@
 static void
 resume(void)
 {
-	game_switch(state_continue_new(), 0);
+	game_push(state_continue_new());
 }
 
 static void
--- a/libmlk-adventure/adventure/state/map.c	Wed Mar 10 18:49:08 2021 +0100
+++ b/libmlk-adventure/adventure/state/map.c	Sun Apr 11 16:41:34 2021 +0200
@@ -106,6 +106,14 @@
 }
 
 static void
+suspend(struct state *state)
+{
+	struct self *self = state->data;
+
+	self->map.player_movement = 0;
+}
+
+static void
 finish(struct state *state)
 {
 	struct self *self = state->data;
@@ -134,6 +142,7 @@
 	self->state.handle = handle;
 	self->state.update = update;
 	self->state.draw = draw;
+	self->state.suspend = suspend;
 	self->state.finish = finish;
 
 	return &self->state;
--- a/libmlk-adventure/adventure/state/splashscreen.c	Wed Mar 10 18:49:08 2021 +0100
+++ b/libmlk-adventure/adventure/state/splashscreen.c	Sun Apr 11 16:41:34 2021 +0200
@@ -75,7 +75,7 @@
 	self->elapsed += ticks;
 
 	if (self->elapsed >= DELAY)
-		game_switch(state_mainmenu_new(), 0);
+		game_push(state_mainmenu_new());
 }
 
 static void
--- a/libmlk-core/core/game.c	Wed Mar 10 18:49:08 2021 +0100
+++ b/libmlk-core/core/game.c	Sun Apr 11 16:41:34 2021 +0200
@@ -28,41 +28,34 @@
 #include "util.h"
 #include "window.h"
 
-struct game game;
+struct game game = {
+	.state = &game.states[0],
+};
 
 void
-game_switch(struct state *state, int quick)
+game_push(struct state *state)
 {
 	assert(state);
-
-	if (quick) {
-		if (game.state_next) {
-			state_finish(game.state_next);
-			game.state_next = NULL;
-		}
+	assert(game.state != &game.states[GAME_STATE_MAX]);
 
-		if (game.state) {
-			state_end(game.state);
-			state_finish(game.state);
-		}
-
-		state_start(game.state = state);
+	if (*game.state) {
+		state_suspend(*game.state);
+		state_start(*(++game.state) = state);
 	} else
-		game.state_next = state;
+		state_start((*game.state) = state);
 }
 
-struct state *
-game_replace(struct state *state)
+void
+game_pop(void)
 {
-	assert(state);
+	if (!*game.state)
+		return;
 
-	struct state *save = game.state;
-
-	game.state = state;
+	state_end(*game.state);
+	state_finish(*game.state);
 
-	state_start(state);
-
-	return save;
+	if (game.state != &game.states[0])
+		state_resume(*--game.state);
 }
 
 void
@@ -70,48 +63,22 @@
 {
 	assert(ev);
 
-	if (game.state && !(game.inhibit & INHIBIT_STATE_INPUT))
-		state_handle(game.state, ev);
+	if (*game.state && !(game.inhibit & INHIBIT_STATE_INPUT))
+		state_handle(*game.state, ev);
 }
 
 void
 game_update(unsigned int ticks)
 {
-	if (game.inhibit & INHIBIT_STATE_UPDATE)
-		return;
-
-	/* Change state if any. */
-	if (game.state_next) {
-		struct state *previous;
-
-		/* Inform the current state we're gonna leave it. */
-		if ((previous = game.state))
-			state_end(previous);
-
-		/* Change the state and tell we're starting it. */
-		if ((game.state = game.state_next)) {
-			game.state_next = NULL;
-			state_start(game.state);
-		}
-
-		/*
-		 * Only call finish at the end of the process because
-		 * the user may still use resources from it during the
-		 * transition.
-		 */
-		if (previous)
-			state_finish(previous);
-	}
-
-	if (game.state)
-		state_update(game.state, ticks);
+	if (*game.state && !(game.inhibit & INHIBIT_STATE_UPDATE))
+		state_update(*game.state, ticks);
 }
 
 void
 game_draw(void)
 {
 	if (game.state && !(game.inhibit & INHIBIT_STATE_DRAW))
-		state_draw(game.state);
+		state_draw(*game.state);
 }
 
 void
@@ -150,15 +117,5 @@
 void
 game_quit(void)
 {
-	/* Close the next state if any. */
-	if (game.state_next) {
-		state_finish(game.state_next);
-		game.state_next = NULL;
-	}
-	
-	if (game.state) {
-		state_end(game.state);
-		state_finish(game.state);
-		game.state = NULL;
-	}
+	// TODO: clear.
 }
--- a/libmlk-core/core/game.h	Wed Mar 10 18:49:08 2021 +0100
+++ b/libmlk-core/core/game.h	Sun Apr 11 16:41:34 2021 +0200
@@ -22,17 +22,16 @@
 #include "core.h"
 #include "inhibit.h"
 
+#define GAME_STATE_MAX (32)
+
 struct state;
 
 union event;
 
 struct game {
-	/* Inhibition */
 	enum inhibit inhibit;
-
-	/* Game states. */
-	struct state *state;
-	struct state *state_next;
+	struct state *states[GAME_STATE_MAX + 1];
+	struct state **state;
 };
 
 extern struct game game;
@@ -40,10 +39,10 @@
 CORE_BEGIN_DECLS
 
 void
-game_switch(struct state *, int);
+game_push(struct state *);
 
-struct state *
-game_replace(struct state *);
+void
+game_pop(void);
 
 void
 game_handle(const union event *);
--- a/libmlk-core/core/state.c	Wed Mar 10 18:49:08 2021 +0100
+++ b/libmlk-core/core/state.c	Sun Apr 11 16:41:34 2021 +0200
@@ -58,6 +58,24 @@
 }
 
 void
+state_suspend(struct state *state)
+{
+	assert(state);
+
+	if (state->suspend)
+		state->suspend(state);
+}
+
+void
+state_resume(struct state *state)
+{
+	assert(state);
+
+	if (state->resume)
+		state->resume(state);
+}
+
+void
 state_end(struct state *state)
 {
 	assert(state);
--- a/libmlk-core/core/state.h	Wed Mar 10 18:49:08 2021 +0100
+++ b/libmlk-core/core/state.h	Sun Apr 11 16:41:34 2021 +0200
@@ -29,6 +29,8 @@
 	void (*handle)(struct state *, const union event *);
 	void (*update)(struct state *, unsigned int);
 	void (*draw)(struct state *);
+	void (*suspend)(struct state *);
+	void (*resume)(struct state *);
 	void (*end)(struct state *);
 	void (*finish)(struct state *);
 };
@@ -48,6 +50,12 @@
 state_draw(struct state *);
 
 void
+state_suspend(struct state *);
+
+void
+state_resume(struct state *);
+
+void
 state_end(struct state *);
 
 void
--- a/libmlk-data/maps/map-world.json	Wed Mar 10 18:49:08 2021 +0100
+++ b/libmlk-data/maps/map-world.json	Sun Apr 11 16:41:34 2021 +0200
@@ -63,7 +63,7 @@
                         {
                          "name":"exec",
                          "type":"string",
-                         "value":"spawner|1|2"
+                         "value":"spawner|1000|2000"
                         }],
                  "rotation":0,
                  "type":"",
@@ -109,4 +109,4 @@
  "type":"map",
  "version":1.4,
  "width":300
-}
\ No newline at end of file
+}