comparison examples/example-battle.c @ 192:4ad7420ab678

rpg: add minimalist battle system, continue #2477 @60h - Implement battle as states, - Add basic support for spells (no calculation yet), - Add won/lost state, - Add animations and messages, - Add order.
author David Demelier <markand@malikania.fr>
date Sat, 07 Nov 2020 16:00:39 +0100
parents
children 133926e08d6e
comparison
equal deleted inserted replaced
191:633a25df450e 192:4ad7420ab678
1 /*
2 * example-battle.c -- show how to use battle
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 <stdio.h>
21 #include <string.h>
22
23 #include <core/clock.h>
24 #include <core/core.h>
25 #include <core/event.h>
26 #include <core/image.h>
27 #include <core/painter.h>
28 #include <core/panic.h>
29 #include <core/sprite.h>
30 #include <core/sys.h>
31 #include <core/texture.h>
32 #include <core/util.h>
33 #include <core/window.h>
34
35 #include <ui/align.h>
36 #include <ui/label.h>
37 #include <ui/theme.h>
38 #include <ui/ui.h>
39
40 #include <rpg/character.h>
41 #include <rpg/battle.h>
42 #include <rpg/rpg.h>
43 #include <rpg/spell.h>
44
45 #include "battle/registry.h"
46 #include "battle/spell-fire.h"
47
48 #define W 1280
49 #define H 720
50
51 static void
52 adventurer_reset(struct character *ch)
53 {
54 /* TODO: this function should compute the attack thanks to the level. */
55 ch->hpmax = 120;
56 ch->mpmax = 50;
57 ch->atk = 50;
58 ch->def = 50;
59 ch->agt = 50;
60 ch->luck = 50;
61 }
62
63 static void
64 haunted_wood_reset(struct character *ch)
65 {
66 ch->hpmax = ch->hp = 2000;
67 ch->mpmax = ch->mp = 250;
68 ch->atk = 178;
69 ch->def = 80;
70 ch->agt = 80;
71 ch->luck = 100;
72 }
73
74 static void
75 black_cat_reset(struct character *ch)
76 {
77 ch->hpmax = ch->hp = 126;
78 ch->mpmax = ch->mp = 38;
79 ch->atk = 22;
80 ch->def = 19;
81 ch->agt = 21;
82 ch->luck = 14;
83 }
84
85 static struct character team[] = {
86 {
87 .name = "Molko",
88 .type = "Adventurer",
89 .level = 1,
90 .hp = 120,
91 .mp = 50,
92 .reset = adventurer_reset,
93 .sprite = &registry_sprites[REGISTRY_TEXTURE_JOHN],
94 .spells = {
95 &spell_fire
96 }
97 },
98 {
99 .name = "Fake Molko",
100 .type = "Adventurer",
101 .level = 1,
102 .hp = 120,
103 .mp = 50,
104 .reset = adventurer_reset,
105 .sprite = &registry_sprites[REGISTRY_TEXTURE_JOHN],
106 .spells = {
107 &spell_fire
108 }
109 }
110 };
111
112 static void
113 haunted_wood_strat(struct character *ch, struct battle *bt)
114 {
115 (void)ch;
116
117 /* TODO: Select randomly. */
118 battle_attack(bt, bt->order_cur->ch, bt->team[0].ch);
119 }
120
121 static void
122 black_cat_strat(struct character *ch, struct battle *bt)
123 {
124 (void)ch;
125
126 /* TODO: Select randomly. */
127 battle_attack(bt, bt->order_cur->ch, bt->team[0].ch);
128 }
129
130 static struct character haunted_wood = {
131 .name = "Haunted Wood",
132 .type = "Wood",
133 .level = 30,
134 .reset = haunted_wood_reset,
135 .sprite = &registry_sprites[REGISTRY_TEXTURE_HAUNTED_WOOD],
136 .exec = haunted_wood_strat
137 };
138
139 static struct character black_cat = {
140 .name = "Black Cat",
141 .type = "Cat",
142 .level = 6,
143 .reset = black_cat_reset,
144 .sprite = &registry_sprites[REGISTRY_TEXTURE_BLACK_CAT],
145 .exec = black_cat_strat
146 };
147
148 static void
149 init(void)
150 {
151 struct clock clock = {0};
152
153 if (!core_init() || !ui_init() || !rpg_init())
154 panic();
155 if (!window_open("Example - Battle", W, H))
156 panic();
157
158 /* Wait 1 second to let all events processed. */
159 while (clock_elapsed(&clock) < 1000)
160 for (union event ev; event_poll(&ev); )
161 if (ev.type == EVENT_QUIT)
162 return;
163
164 registry_init();
165
166 /* Set cursor in default theme. */
167 theme_default()->sprites[THEME_SPRITE_CURSOR] = &registry_sprites[REGISTRY_TEXTURE_CURSOR];
168 }
169
170 static void
171 prepare_to_fight(struct battle *bt)
172 {
173 assert(bt);
174
175 // bt->enemies[0].ch = &haunted_wood;
176 bt->team[0].ch = &team[0];
177 bt->team[1].ch = &team[1];
178
179 /* Positionate the single ennemy to the left. */
180 align(ALIGN_LEFT,
181 &bt->enemies[0].x, &bt->enemies[0].y, haunted_wood.sprite->cellw, haunted_wood.sprite->cellh,
182 0, 0, window.w, window.h);
183
184 /* Black cat is near the previous monster. */
185 bt->enemies[1].ch = &black_cat;
186 bt->enemies[1].x = 500;
187 bt->enemies[1].y = 100;
188
189 battle_start(bt);
190 }
191
192 static void
193 run(void)
194 {
195 struct clock clock;
196 struct battle battle = {0};
197 struct label info = {
198 .text = "Press <Space> to start a battle.",
199 .x = 10,
200 .y = 10,
201 .flags = LABEL_FLAGS_SHADOW
202 };
203
204 clock_start(&clock);
205
206 for (;;) {
207 unsigned int elapsed = clock_elapsed(&clock);
208
209 clock_start(&clock);
210
211 for (union event ev; event_poll(&ev); ) {
212 switch (ev.type) {
213 case EVENT_QUIT:
214 return;
215 case EVENT_KEYDOWN:
216 if (ev.key.key == KEY_SPACE && !battle.state)
217 prepare_to_fight(&battle);
218 else if (battle.state)
219 battle_handle(&battle, &ev);
220 break;
221 default:
222 if (battle.state)
223 battle_handle(&battle, &ev);
224 break;
225 }
226 }
227
228 if (battle.state) {
229 if (battle_update(&battle, elapsed))
230 battle_finish(&battle);
231 else
232 battle_draw(&battle);
233 } else {
234 painter_set_color(0x4f8fbaff);
235 painter_clear();
236 label_draw(&info);
237 }
238
239 painter_present();
240
241 if ((elapsed = clock_elapsed(&clock)) < 20)
242 delay(1);
243 }
244 }
245
246 static void
247 quit(void)
248 {
249 registry_finish();
250 theme_finish();
251 window_finish();
252 sys_finish();
253 }
254
255 int
256 main(int argc, char **argv)
257 {
258 --argc;
259 ++argv;
260
261 init();
262 run();
263 quit();
264
265 return 0;
266 }