comparison src/adventure/mainmenu_state.c @ 80:05ffbcdee585

adventure: create main menu, closes #2482 @4h
author David Demelier <markand@malikania.fr>
date Sat, 15 Feb 2020 12:38:25 +0100
parents
children ed72843a7194
comparison
equal deleted inserted replaced
79:8f95462ac5f8 80:05ffbcdee585
1 /*
2 * mainmenu_state.c -- game main menu
3 *
4 * Copyright (c) 2020 David Demelier <markand@malikania.fr>
5 *
6 * Permission to use, copy, modify, and/or distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18
19 #include <assert.h>
20 #include <stdlib.h>
21 #include <string.h>
22
23 #include <error.h>
24 #include <event.h>
25 #include <font.h>
26 #include <game.h>
27 #include <image.h>
28 #include <map_state.h>
29 #include <painter.h>
30 #include <state.h>
31 #include <sys.h>
32 #include <texture.h>
33 #include <window.h>
34
35 #include "mainmenu_state.h"
36 #include "splashscreen_state.h"
37
38 #define SPEED 120
39 #define SEC 1000
40
41 enum substate {
42 SUBSTATE_MOVING,
43 SUBSTATE_WAITING
44 };
45
46 static int x;
47 static int y;
48 static unsigned int selection;
49 static int destination;
50 static enum substate substate;
51
52 /* Menu items. */
53 static struct {
54 struct texture *texture;
55 int x;
56 int y;
57 } items[3];
58
59 static void
60 enter(void)
61 {
62 struct font *font = font_openf(sys_datapath("fonts/pirata-one.ttf"), 30);
63
64 if (!font)
65 error_fatal();
66
67 substate = SUBSTATE_MOVING;
68 x = splashscreen_state_data.x;
69 y = splashscreen_state_data.y;
70 destination = window_height() / 4;
71
72 /* TODO: change continue color if no game exists. */
73 items[0].texture = font_render(font, "New game", 0x000000ff);
74 items[0].x = (window_width() / 2) - (texture_width(items[0].texture) / 2);
75 items[0].y = window_height() * 0.75;
76
77 items[1].texture = font_render(font, "Continue", 0x000000ff);
78 items[1].x = items[0].x;
79 items[1].y = items[0].y + texture_height(items[0].texture);
80
81 items[2].texture = font_render(font, "Quit", 0x000000ff);
82 items[2].x = items[0].x;
83 items[2].y = items[1].y + texture_height(items[1].texture);
84 }
85
86 static void
87 new(void)
88 {
89 struct map map;
90 struct texture *image;
91
92 /* Prepare map. */
93 if (!map_open(&map, sys_datapath("maps/test.map")))
94 error_fatal();
95
96 memcpy(&map_state_data.map.map, &map, sizeof (map));
97
98 /* Prepare image and sprite. */
99 if (!(image = image_openf(sys_datapath("sprites/test-walk.png"))))
100 error_fatal();
101
102 sprite_init(&map_state_data.player.sprite, image, 48, 48);
103 game_switch(&map_state, false);
104 }
105
106 static void
107 resume(void)
108 {
109 }
110
111 static void
112 quit(void)
113 {
114 game_quit();
115 }
116
117 static void
118 perform(void)
119 {
120 assert(selection < 3);
121
122 static void (*handlers[])(void) = {
123 [0] = new,
124 [1] = resume,
125 [2] = quit
126 };
127
128 handlers[selection]();
129 }
130
131 static void
132 handle(const union event *event)
133 {
134 if (substate != SUBSTATE_WAITING)
135 return;
136
137 switch (event->type) {
138 case EVENT_KEYDOWN:
139 switch (event->key.key) {
140 case KEY_UP:
141 selection = selection == 0 ? 2 : selection - 1;
142 break;
143 case KEY_DOWN:
144 selection = (selection + 1) % 3;
145 break;
146 case KEY_ENTER:
147 perform();
148 default:
149 break;
150 }
151 break;
152 default:
153 break;
154 }
155 }
156
157 static void
158 update(unsigned int ticks)
159 {
160 switch (substate) {
161 case SUBSTATE_MOVING:
162 y -= SPEED * ticks / SEC;
163
164 if (y <= destination) {
165 y = destination;
166 substate = SUBSTATE_WAITING;
167 }
168
169 break;
170 default:
171 break;
172 }
173 }
174
175 static void
176 draw(void)
177 {
178 painter_set_color(0xffffffff);
179 painter_clear();
180 texture_draw(splashscreen_state_data.text, x, y);
181
182 if (substate == SUBSTATE_WAITING) {
183 texture_draw(items[0].texture, items[0].x, items[0].y);
184 texture_draw(items[1].texture, items[1].x, items[1].y);
185 texture_draw(items[2].texture, items[2].x, items[2].y);
186
187 /* Selection cursor. */
188
189 /* TODO: a sword here. */
190 painter_set_color(0x000000ff);
191 painter_draw_rectangle(true, items[selection].x - 30,
192 items[selection].y + 11, 15, 15);
193 }
194 }
195
196 static void
197 leave(void)
198 {
199 texture_close(items[0].texture);
200 texture_close(items[1].texture);
201 memset(items, 0, sizeof (items));
202 }
203
204 struct state mainmenu_state = {
205 .enter = enter,
206 .handle = handle,
207 .update = update,
208 .draw = draw,
209 .leave = leave
210 };