Skip to content

Code_main

lemmiix edited this page Mar 5, 2026 · 4 revisions

Main documentation

main

/**
 * Set initial delta time, used to calculate the time difference between frame generations
*/
float delta_time = 0;

/**
 * The SDL window and renderer used to dispaly the game
*/
SDL_Window* window = NULL;
SDL_Renderer* renderer = NULL;

/**
 * Flag for vertical synchronisation (not properly implemented, vsync is ALWAYS enabled)
*/
static bool vsync_enabled = 1;

/**
 * Bullet and Enemy manager to manage entities, pointing to NULL on init
*/
struct bullets_manager* BM = NULL;
struct enemy_manager* EM = NULL;

/**
 * Rate at which new enemies are spawned into the scene - upper bound for `enemy_timer`
*/
#define ENEMY_SPAWN_INTERVAL 1.0f

/**
 * Counter, reset when `ENEMY_SPAWN_INTERVAL` is reached
*/
float enemy_timer = 0.0f;

/**
 * Current game state
*/
Game_state game_state;

/**
 * User controlled player character
*/
Player_ship ship;


---

main game loop

/**
 * Runs every frame
*/
while(game_state != QUIT) {
	if (game_state == RUNNING) {

    /*
     * this manages the behavious when keys (mouse or keyboard)
     * are pressed and calls relevant functions accordingly
    */
		while (SDL_PollEvent(&event)) {
			if (event.type == SDL_EVENT_QUIT) {
				printf("quit event hit\n");
				game_state = QUIT;

			} else if(event.type == SDL_EVENT_KEY_UP && event.key.key == SDLK_ESCAPE) {
				game_state = PAUSED;

        /*
         * when mouse motion is detected
        */
			} else if (event.type == SDL_EVENT_MOUSE_MOTION) {
				SDL_GetMouseState(&mouse_pos_x, &mouse_pos_y);
				turn_the_thing(&mouse_pos_x, &mouse_pos_y);

        /*
         * when a keyboard key-press is detected
        */
			} else if (event.type == SDL_EVENT_KEY_DOWN) {
				set_key_active(event.key.key);

        /*
         * when a keyboard key-release is detected
        */
			} else if (event.type == SDL_EVENT_KEY_UP) {
				set_key_inactive(event.key.key);

                /*
                 * this spawns different kinds of bullets
                 * when either left or right mouse button
                 * is clicked
                */
			} else if (event.type == SDL_EVENT_MOUSE_BUTTON_DOWN && event.button.button == SDL_BUTTON_LEFT) {
				SDL_GetMouseState(&mouse_pos_x, &mouse_pos_y);
				create_bullet(BASIC);
			} else if (event.type == SDL_EVENT_MOUSE_BUTTON_DOWN && event.button.button == SDL_BUTTON_RIGHT) {
				SDL_GetMouseState(&mouse_pos_x, &mouse_pos_y);
				create_bullet(EXPLOSIVE);
			}
		}

    /**
     * WASD keyboard movement
    */
		if (is_key_active(SDLK_W)) {
			move_ship_up();
		}
		if (is_key_active(SDLK_A)) {
			move_ship_left();
		}
		if (is_key_active(SDLK_S)) {
			move_ship_down();
		}
		if (is_key_active(SDLK_D)) {
			move_ship_right();
		}
		if (is_key_active(SDLK_Q)) {
			game_state = QUIT;
		}

		SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
		SDL_RenderClear(renderer);

    /**
     * renders the player ship on the screen
    */
		SDL_RenderGeometry(renderer, NULL, ship.shape, 3, NULL, 0);

    /**
     * frames per second counter
    */
		++frame_count;
        /*
         * to not update the FPS counter each frame,
         * we only update is every 1000ms
        */
		current_tick = SDL_GetTicks();
		if (current_tick - last_tick >= 1000) {
			frames_per_second = frame_count * 1000.0f / (current_tick - last_tick);
			snprintf(frames_string, 99, "vsync: %i, fps: %.3f", vsync_enabled, frames_per_second);

			frame_count = 0;
			last_tick = current_tick;
		}
        
        /*
         * print control string info etc to the screen
        */
		print_text_to_screen(frames_string, WINDOW_WIDTH / 2, 0, renderer);
		print_text_to_screen(controls_esc, 0, 0, renderer);
		snprintf(score_string, 12, "score: %d", ship.score);
		print_text_to_screen(score_string, WINDOW_WIDTH - 100, 0, renderer);

        /*
         * checks if it is time to spawn a new enemy
        */
		if (enemy_timer >= ENEMY_SPAWN_INTERVAL) {
			create_enemy();
			enemy_timer = 0;
		}

        /*
         * move bullets and enemies one step forwards
        */
		update_bullets();
		update_enemies(BM);

        /*
         * display the renderer to the screen, I guess
        */
		SDL_RenderPresent(renderer);

        /*
         * calculate how much time passed from the
         * last frame to the current frame and use
         * this as a multiplicand on all movement
         * operations
        */
		delta_time = (current_tick - last_delta_tick) / 1000.0f;
		last_delta_tick = current_tick;

		enemy_timer += delta_time;

        /*
         * game over screen if u failed lol
        */
		if (got_hit_by_enemy(EM)) {
			game_state = GAME_OVER;
		}

    /**
     * pause screen when ESC is pressed
    */
	} else if (game_state == PAUSED) {
		while (SDL_PollEvent(&event)) {
			if (event.type == SDL_EVENT_QUIT || event.key.key == SDLK_Q) {
				printf("quit event hit\n");
				game_state = QUIT;

			} else if(event.type == SDL_EVENT_KEY_UP && event.key.key == SDLK_ESCAPE) {
				game_state = RUNNING;
				last_delta_tick = SDL_GetTicks();
			}
		}

		SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
		SDL_RenderClear(renderer);

		SDL_RenderGeometry(renderer, NULL, ship.shape, 3, NULL, 0);

		print_text_to_screen_with_color(paused_text, ((WINDOW_WIDTH / 2.0f) - 60), WINDOW_HEIGHT / 2.0f, renderer, paused_color);
		print_text_to_screen(controls, 0, 0, renderer);

		SDL_RenderPresent(renderer);

	} else if (game_state == GAME_OVER) {
		while (SDL_PollEvent(&event)) {
			if (event.type == SDL_EVENT_QUIT || event.key.key == SDLK_Q) {
				printf("quit event hit\n");
				game_state = QUIT;

			} else if(event.type == SDL_EVENT_KEY_UP && event.key.key == SDLK_R) {
				free_all_bullets();
				free_all_enemies();

				if (bullets_manager_init() != 0) {
					printf("bullet manager not initialized\n");
					return SDL_APP_FAILURE;
				}
				if (enemy_manager_init() != 0) {
					printf("enemy manager not initialized\n");
					return SDL_APP_FAILURE;
				}

				create_player(&ship);

				flush_keystate();
				flush_mousepos();
				flush_playerpos();

				game_state = RUNNING;
				last_delta_tick = SDL_GetTicks();
			}
		}

		SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
		SDL_RenderClear(renderer);

		print_text_to_screen_with_color(gameover_text, WINDOW_WIDTH / 2 - 60, WINDOW_HEIGHT / 2, renderer, paused_color);
		print_text_to_screen(score_string, WINDOW_WIDTH / 2 -  60, WINDOW_HEIGHT / 2 + 20, renderer);
		print_text_to_screen(gameover_controls, WINDOW_WIDTH / 2 - 60, WINDOW_HEIGHT / 2 + 40, renderer);

		SDL_RenderPresent(renderer);
	}
}

Cleanup

printf("ending program\n");
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
SDL_Quit();

kill_font();
/**
 * remember to free your pointers
*/
free_all_bullets();
free_all_enemies();
free_map_uint_bool(&key_state);

Quicknav

Go back to wiki home

Code documentation:
doc_code

Architecture documentation:
doc_arch

Project license

Clone this wiki locally