37 DefenderWindow(
const std::string &path,
int width,
int height,
bool fullscreen,
bool enable_vsync);
39 void event(SDL_Event &e)
override;
44 std::string asset_root;
45 std::chrono::steady_clock::time_point last_frame_time = std::chrono::steady_clock::now();
46 float elapsed_seconds = 0.0f;
48 float intro_fade = 1.0f;
49 Uint32 intro_last_update_ms = 0;
50 Uint32 intro_fade_in_start_ms = 0;
51 static constexpr Uint32 INTRO_FADE_IN_DURATION_MS = 500;
52 static constexpr int INTRO_RAIN_TEXTURE_WIDTH = 1280;
53 static constexpr int INTRO_RAIN_TEXTURE_HEIGHT = 720;
54 static constexpr int ENEMY_SPAWN_ATTEMPTS = 16;
55 static constexpr float ENEMY_SEPARATION_PADDING = 0.12f;
56 Uint32 countdown_timer = 0;
57 Uint32 countdown_duration = 1000;
58 Uint32 countdown_start_ms = 0;
59 int countdown_number = 3;
60 Uint32 launch_timer = 0;
61 Uint32 launch_duration = 1000;
62 Uint32 launch_start_ms = 0;
63 float ship_forward_direction = 1.0f;
64 float camera_center_x = 0.0f;
66 float respawn_timer = 0.0f;
70 bool level_active =
false;
71 bool game_over =
false;
72 bool ship_respawning =
false;
73 bool reverse_pressed =
false;
74 bool propulsion_pressed =
false;
75 bool up_pressed =
false;
76 bool down_pressed =
false;
77 bool fire_pressed =
false;
78 bool roll_left_pressed =
false;
79 bool roll_right_pressed =
false;
80 bool boost_pressed =
false;
81 bool controller_propulsion_pressed =
false;
82 bool controller_boost_pressed =
false;
83 bool controller_roll_left_pressed =
false;
84 bool controller_roll_right_pressed =
false;
85 bool controller_reverse_trigger_pressed =
false;
86 float controller_vertical_input = 0.0f;
87 bool show_fps_counter =
false;
88 bool crt_enabled =
true;
89 float fps_accumulator = 0.0f;
90 int fps_frame_count = 0;
91 std::string fps_text =
"FPS: --";
92 float barrel_roll_direction = 1.0f;
93 float barrel_roll_progress = 0.0f;
94 float barrel_roll_angle = 0.0f;
95 static constexpr float BARREL_ROLL_DURATION = 0.65f;
96 static constexpr int DEFAULT_FONT_SIZE = 24;
97 static constexpr int HUD_FONT_SIZE = DEFAULT_FONT_SIZE * 2;
98 static constexpr int COUNTDOWN_FONT_SIZE = HUD_FONT_SIZE;
103 std::array<space::Projectile, MAX_PROJECTILES> projectiles{};
104 std::array<Ufo, MAX_UFOS> ufos{};
105 std::array<Asteroid, MAX_ASTEROIDS> asteroids{};
106 std::array<space::Particle, space::MAX_PARTICLES> particles{};
109 std::array<mxvk::VKAbstractModel, MAX_ASTEROIDS> asteroid_models{};
113 std::array<std::array<mxvk::VK_Sprite3D *, UFO_ANIMATION_FRAMES>,
UFO_SPRITE_SET_COUNT> ufo_sprite_sets{};
114 std::array<std::array<SpriteAlphaBounds, UFO_ANIMATION_FRAMES>,
UFO_SPRITE_SET_COUNT> ufo_sprite_bounds{};
118 std::unique_ptr<matrix::Rain> intro_rain{};
121 bool console_ready =
false;
122#if defined(MXVK_WITH_MIXER) || defined(WITH_MIXER)
123 std::unique_ptr<mxvk::VK_Mixer> background_music{};
124 int background_music_track = -1;
125 int crash_sound = -1;
126 int shoot_sound = -1;
127 int takeoff_sound = -1;
128 int asteroid_explosion_sound = -1;
129 int ufo_explosion_sound = -1;
132 glm::mat4 last_ship_model_matrix{1.0f};
133 VkBuffer flame_vertex_buffer = VK_NULL_HANDLE;
134 VkDeviceMemory flame_vertex_buffer_memory = VK_NULL_HANDLE;
135 VkPipeline flame_pipeline = VK_NULL_HANDLE;
136 VkPipelineLayout flame_pipeline_layout = VK_NULL_HANDLE;
137 uint32_t flame_vertex_count = 0;
139 void configure_console();
140 bool handle_console_command(
const std::vector<std::string> &args, std::ostream &out);
141 void log_game(
const std::string &message, SDL_Color color = SDL_Color{180, 220, 255, 255});
142 [[nodiscard]]
const char *mode_name()
const;
143 [[nodiscard]]
static std::string format_vec3(
const glm::vec3 &value);
144 bool parse_int_arg(
const std::vector<std::string> &args, std::size_t index,
const char *name,
int &value, std::ostream &out)
const;
145 bool parse_float_arg(
const std::vector<std::string> &args, std::size_t index,
const char *name,
float &value, std::ostream &out)
const;
146 [[nodiscard]]
int active_ufo_count()
const;
147 [[nodiscard]]
int active_asteroid_count()
const;
148 [[nodiscard]]
int active_projectile_count()
const;
149 Ufo *find_inactive_ufo();
151 void clear_input_state();
152 bool open_controller();
153 void sync_controller_connection();
154 [[nodiscard]]
float controller_axis(SDL_GamepadAxis axis)
const;
155 void update_controller_input();
156#if defined(MXVK_WITH_MIXER) || defined(WITH_MIXER)
157 void ensure_background_music_playing();
158 void play_sound(
int sound_id);
160 void update_ship(
float dt);
161 void update_barrel_roll(
float dt);
162 glm::mat4 build_ship_model_matrix();
164 void update_camera_position(
float dt);
165 void update_playable_world_top(
const VkExtent2D &extent);
166 void reset_intro_screen();
167 void start_launch_countdown();
168 void start_intro_fade_in();
169 void draw_intro(
const VkExtent2D &extent);
170 void draw_intro_fade_in(
const VkExtent2D &extent);
171 void draw_fade_overlay(
const VkExtent2D &extent,
float alpha);
172 void update_camera_scroll(
float aspect);
173 void update_countdown();
174 void draw_countdown(VkCommandBuffer cmd, uint32_t image_index,
const VkExtent2D &extent,
const glm::mat4 &view,
const glm::mat4 &projection);
176 void init_asteroids();
178 void update_level_progress();
179 void respawn_ufo(
Ufo &ufo,
bool initial_spawn =
false);
180 void update_ufos(
float dt);
181 void respawn_asteroid(
Asteroid &asteroid,
bool initial_spawn =
false);
182 void update_asteroids(
float dt);
183 [[nodiscard]]
float ufo_collision_radius(
const Ufo &ufo)
const;
184 [[nodiscard]]
bool enemy_spawn_is_clear(
const glm::vec3 &position,
float radius,
const Ufo *ignored_ufo,
const Asteroid *ignored_asteroid)
const;
185 void clamp_enemy_to_world_y(glm::vec3 &position, glm::vec3 &velocity,
float radius);
186 void separate_enemies(glm::vec3 &first_position,
187 glm::vec3 &first_velocity,
189 glm::vec3 &second_position,
190 glm::vec3 &second_velocity,
193 void resolve_enemy_overlaps();
194 [[nodiscard]]
int current_ufo_frame(
const Ufo &ufo)
const;
195 [[nodiscard]]
float current_ufo_pulse(
const Ufo &ufo)
const;
196 [[nodiscard]] glm::vec2 ufo_draw_size(
const Ufo &ufo,
float pulse)
const;
199 void draw_asteroids(VkCommandBuffer cmd, uint32_t image_index,
const glm::mat4 &view,
const glm::mat4 &projection);
200 void create_flame_resources();
201 void cleanup_flame_resources();
202 void cleanup_flame_swapchain_resources();
203 void create_flame_swapchain_resources();
204 void create_flame_mesh();
205 void create_flame_pipeline();
206 void draw_engine_flame(VkCommandBuffer cmd,
const VkExtent2D &extent,
const glm::mat4 &view,
const glm::mat4 &projection);
207 void create_buffer(VkDeviceSize size,
208 VkBufferUsageFlags usage,
209 VkMemoryPropertyFlags properties,
211 VkDeviceMemory &buffer_memory)
const;
212 [[nodiscard]] uint32_t find_memory_type(uint32_t type_filter, VkMemoryPropertyFlags properties)
const;
213 void fire_projectile();
214 void update_projectiles(
float dt);
215 void check_projectile_ufo_hits();
216 void check_projectile_asteroid_hits();
217 void check_ship_ufo_collisions();
218 void check_ship_asteroid_collisions();
220 void update_respawn(
float dt);
221 void reset_ship_to_origin();
222 void reset_ufos_for_origin_start();
224 void clear_projectiles();
225 void draw_projectiles();
226 void spawn_ufo_explosion(
const glm::vec3 &position,
float explosion_scale = 1.0f);
227 void spawn_alien_explosion(
const glm::vec3 &position,
float explosion_scale = 1.0f);
228 void spawn_ship_explosion(
const glm::vec3 &position,
float explosion_scale = 1.0f);
229 void spawn_enemy_explosion(
const glm::vec3 &position,
float explosion_scale,
const std::array<glm::vec3, 4> &wave_colors,
bool color_flash =
false);
231 void update_particles(
float dt);
232 void draw_particles();
233 void clear_particles();
234 void update_fps_counter(
float delta_seconds);
235 void draw_hud(
const VkExtent2D &extent);
236 void draw_scanner(
const VkExtent2D &extent);