]> git.lizzy.rs Git - nothing.git/blob - src/game/level_picker.c
Merge pull request #1 from tsoding/master
[nothing.git] / src / game / level_picker.c
1 #include <stdio.h>
2
3 #include "./level_picker.h"
4 #include "game/level/background.h"
5 #include "game/sprite_font.h"
6 #include "system/lt.h"
7 #include "system/nth_alloc.h"
8 #include "system/stacktrace.h"
9 #include "system/str.h"
10 #include "ui/list_selector.h"
11 #include "system/log.h"
12 #include "game/level_folder.h"
13 #include "ui/menu_title.h"
14
15 struct LevelPicker
16 {
17     Lt *lt;
18     Background *background;
19     Vec camera_position;
20     LevelFolder *level_folder;
21     MenuTitle *menu_title;
22     ListSelector *list_selector;
23 };
24
25 LevelPicker *create_level_picker(const Sprite_font *sprite_font, const char *dirpath)
26 {
27     trace_assert(dirpath);
28
29     Lt *lt = create_lt();
30     if (lt == NULL) {
31         return NULL;
32     }
33
34     LevelPicker *level_picker = PUSH_LT(
35         lt,
36         nth_calloc(1, sizeof(LevelPicker)),
37         free);
38     if (level_picker == NULL) {
39         RETURN_LT(lt, NULL);
40     }
41     level_picker->lt = lt;
42
43     level_picker->background = PUSH_LT(
44         lt,
45         create_background(hexstr("073642")),
46         destroy_background);
47     if (level_picker->background == NULL) {
48         RETURN_LT(lt, NULL);
49     }
50
51     level_picker->camera_position = vec(0.0f, 0.0f);
52
53     level_picker->level_folder = PUSH_LT(
54         lt,
55         create_level_folder(dirpath),
56         destroy_level_folder);
57     if (level_picker->level_folder == NULL) {
58         RETURN_LT(lt, NULL);
59     }
60
61     level_picker->menu_title = PUSH_LT(
62         lt,
63         create_menu_title("Select Level", vec(10.0f, 10.0f), sprite_font),
64         destroy_menu_title);
65     if (level_picker->menu_title == NULL) {
66         RETURN_LT(lt, NULL);
67     }
68
69     level_picker->list_selector = PUSH_LT(
70         lt,
71         create_list_selector(
72             sprite_font,
73             level_folder_titles(level_picker->level_folder),
74             level_folder_count(level_picker->level_folder),
75             vec(5.0f, 5.0f),
76             50.0f),
77         destroy_list_selector);
78     if (level_picker->list_selector == NULL) {
79         RETURN_LT(lt, NULL);
80     }
81
82     return level_picker;
83 }
84
85 void destroy_level_picker(LevelPicker *level_picker)
86 {
87     trace_assert(level_picker);
88     RETURN_LT0(level_picker->lt);
89 }
90
91 int level_picker_render(const LevelPicker *level_picker,
92                         Camera *camera,
93                         SDL_Renderer *renderer)
94 {
95     trace_assert(level_picker);
96     trace_assert(renderer);
97
98     if (background_render(level_picker->background, camera) < 0) {
99         return -1;
100     }
101
102     if (menu_title_render(level_picker->menu_title, renderer) < 0) {
103         return -1;
104     }
105
106     if (list_selector_render(level_picker->list_selector, renderer) < 0) {
107         return -1;
108     }
109
110     return 0;
111 }
112
113 int level_picker_update(LevelPicker *level_picker,
114                         float delta_time)
115 {
116     trace_assert(level_picker);
117
118     vec_add(&level_picker->camera_position,
119             vec(50.0f * delta_time, 0.0f));
120
121     if (menu_title_update(level_picker->menu_title, delta_time) < 0) {
122         return -1;
123     }
124
125     return 0;
126 }
127
128 int level_picker_event(LevelPicker *level_picker, const SDL_Event *event)
129 {
130     trace_assert(level_picker);
131     trace_assert(event);
132
133     switch (event->type) {
134     case SDL_WINDOWEVENT: {
135         switch (event->window.event) {
136         case SDL_WINDOWEVENT_RESIZED: {
137             const Vec font_scale = vec(5.0f, 5.0f);
138             const float padding_bottom = 50.0f;
139
140             const float width = (float) event->window.data1;
141
142             const Vec title_size = menu_title_size(level_picker->menu_title);
143             const float title_margin_top = 100.0f;
144             const float title_margin_bottom = 100.0f;
145
146             menu_title_move(
147                 level_picker->menu_title,
148                 vec(width * 0.5f - title_size.x * 0.5f, title_margin_top));
149
150             const Vec selector_size = list_selector_size(
151                 level_picker->list_selector,
152                 font_scale,
153                 padding_bottom);
154
155             list_selector_move(
156                 level_picker->list_selector,
157                 vec(width * 0.5f - selector_size.x * 0.5f,
158                     title_margin_top + title_size.y + title_margin_bottom));
159         } break;
160         }
161     } break;
162     }
163
164     return list_selector_event(level_picker->list_selector, event);
165 }
166
167 int level_picker_input(LevelPicker *level_picker,
168                        const Uint8 *const keyboard_state,
169                        SDL_Joystick *the_stick_of_joy)
170 {
171     trace_assert(level_picker);
172     trace_assert(keyboard_state);
173     (void) the_stick_of_joy;
174     return 0;
175 }
176
177 const char *level_picker_selected_level(const LevelPicker *level_picker)
178 {
179     trace_assert(level_picker);
180
181     const int selected_index = list_selector_selected(level_picker->list_selector);
182     if (selected_index < 0) {
183         return NULL;
184     }
185
186     const char **filenames = level_folder_filenames(level_picker->level_folder);
187
188     return filenames[selected_index];
189 }
190
191 void level_picker_clean_selection(LevelPicker *level_picker)
192 {
193     trace_assert(level_picker);
194     list_selector_clean_selection(level_picker->list_selector);
195 }
196
197 int level_picker_enter_camera_event(LevelPicker *level_picker,
198                                     Camera *camera)
199 {
200     camera_center_at(camera, level_picker->camera_position);
201     return 0;
202 }