├── 01-Open-Window.c ├── 02-Close-Window.c ├── 03-Background.c ├── 04-Colors.c ├── 05-Create-Text.c ├── 06-Moving-Text.c ├── 07-Player-Sprite.c ├── 08-Sound-Effects.c ├── 09-Music-and-Icon.c ├── README.md ├── fonts └── freesansbold.ttf ├── images ├── C-logo.png └── background.png ├── music └── freesoftwaresong-8bit.ogg ├── screenshot.png └── sounds ├── C.ogg └── SDL.ogg /01-Open-Window.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #define WINDOW_TITLE "01 Open Window" 6 | #define SCREEN_WIDTH 800 7 | #define SCREEN_HEIGHT 600 8 | 9 | struct Game { 10 | SDL_Window *window; 11 | SDL_Renderer *renderer; 12 | }; 13 | 14 | void game_cleanup(struct Game *game, int exit_status); 15 | bool sdl_initialize(struct Game *game); 16 | 17 | int main() { 18 | struct Game game = { 19 | .window = NULL, 20 | .renderer = NULL, 21 | }; 22 | 23 | if (sdl_initialize(&game)) { 24 | game_cleanup(&game, EXIT_FAILURE); 25 | } 26 | 27 | SDL_RenderClear(game.renderer); 28 | 29 | SDL_RenderPresent(game.renderer); 30 | 31 | SDL_Delay(5000); 32 | 33 | game_cleanup(&game, EXIT_SUCCESS); 34 | 35 | return 0; 36 | } 37 | 38 | void game_cleanup(struct Game *game, int exit_status) { 39 | SDL_DestroyRenderer(game->renderer); 40 | SDL_DestroyWindow(game->window); 41 | SDL_Quit(); 42 | exit(exit_status); 43 | } 44 | 45 | bool sdl_initialize(struct Game *game) { 46 | if (SDL_Init(SDL_INIT_EVERYTHING)) { 47 | fprintf(stderr, "Error initializing SDL: %s\n", SDL_GetError()); 48 | return true; 49 | } 50 | 51 | game->window = SDL_CreateWindow(WINDOW_TITLE, SDL_WINDOWPOS_CENTERED, 52 | SDL_WINDOWPOS_CENTERED, SCREEN_WIDTH, 53 | SCREEN_HEIGHT, 0); 54 | if (!game->window) { 55 | fprintf(stderr, "Error creating window: %s\n", SDL_GetError()); 56 | return true; 57 | } 58 | 59 | game->renderer = SDL_CreateRenderer(game->window, -1, 0); 60 | if (!game->renderer) { 61 | fprintf(stderr, "Error creating renderer: %s\n", SDL_GetError()); 62 | return true; 63 | } 64 | 65 | return false; 66 | } 67 | -------------------------------------------------------------------------------- /02-Close-Window.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #define WINDOW_TITLE "02 Close Window" 6 | #define SCREEN_WIDTH 800 7 | #define SCREEN_HEIGHT 600 8 | 9 | struct Game { 10 | SDL_Window *window; 11 | SDL_Renderer *renderer; 12 | }; 13 | 14 | void game_cleanup(struct Game *game, int exit_status); 15 | bool sdl_initialize(struct Game *game); 16 | 17 | int main() { 18 | struct Game game = { 19 | .window = NULL, 20 | .renderer = NULL, 21 | }; 22 | 23 | if (sdl_initialize(&game)) { 24 | game_cleanup(&game, EXIT_FAILURE); 25 | } 26 | 27 | while (true) { 28 | SDL_Event event; 29 | while (SDL_PollEvent(&event)) { 30 | switch (event.type) { 31 | case SDL_QUIT: 32 | game_cleanup(&game, EXIT_SUCCESS); 33 | break; 34 | case SDL_KEYDOWN: 35 | switch (event.key.keysym.scancode) { 36 | case SDL_SCANCODE_ESCAPE: 37 | game_cleanup(&game, EXIT_SUCCESS); 38 | break; 39 | default: 40 | break; 41 | } 42 | default: 43 | break; 44 | } 45 | } 46 | SDL_RenderClear(game.renderer); 47 | 48 | SDL_RenderPresent(game.renderer); 49 | 50 | SDL_Delay(16); 51 | } 52 | 53 | game_cleanup(&game, EXIT_SUCCESS); 54 | 55 | return 0; 56 | } 57 | 58 | void game_cleanup(struct Game *game, int exit_status) { 59 | SDL_DestroyRenderer(game->renderer); 60 | SDL_DestroyWindow(game->window); 61 | SDL_Quit(); 62 | exit(exit_status); 63 | } 64 | 65 | bool sdl_initialize(struct Game *game) { 66 | if (SDL_Init(SDL_INIT_EVERYTHING)) { 67 | fprintf(stderr, "Error initializing SDL: %s\n", SDL_GetError()); 68 | return true; 69 | } 70 | 71 | game->window = SDL_CreateWindow(WINDOW_TITLE, SDL_WINDOWPOS_CENTERED, 72 | SDL_WINDOWPOS_CENTERED, SCREEN_WIDTH, 73 | SCREEN_HEIGHT, 0); 74 | if (!game->window) { 75 | fprintf(stderr, "Error creating window: %s\n", SDL_GetError()); 76 | return true; 77 | } 78 | 79 | game->renderer = SDL_CreateRenderer(game->window, -1, 0); 80 | if (!game->renderer) { 81 | fprintf(stderr, "Error creating renderer: %s\n", SDL_GetError()); 82 | return true; 83 | } 84 | 85 | return false; 86 | } 87 | -------------------------------------------------------------------------------- /03-Background.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #define WINDOW_TITLE "03 Background" 7 | #define SCREEN_WIDTH 800 8 | #define SCREEN_HEIGHT 600 9 | #define IMAGE_FLAGS IMG_INIT_PNG 10 | 11 | struct Game { 12 | SDL_Window *window; 13 | SDL_Renderer *renderer; 14 | SDL_Texture *background; 15 | }; 16 | 17 | void game_cleanup(struct Game *game, int exit_status); 18 | bool load_media(struct Game *game); 19 | bool sdl_initialize(struct Game *game); 20 | 21 | int main() { 22 | struct Game game = { 23 | .window = NULL, 24 | .renderer = NULL, 25 | .background = NULL, 26 | }; 27 | 28 | if (sdl_initialize(&game)) { 29 | game_cleanup(&game, EXIT_FAILURE); 30 | } 31 | 32 | if (load_media(&game)) { 33 | game_cleanup(&game, EXIT_FAILURE); 34 | } 35 | 36 | while (true) { 37 | SDL_Event event; 38 | while (SDL_PollEvent(&event)) { 39 | switch (event.type) { 40 | case SDL_QUIT: 41 | game_cleanup(&game, EXIT_SUCCESS); 42 | break; 43 | case SDL_KEYDOWN: 44 | switch (event.key.keysym.scancode) { 45 | case SDL_SCANCODE_ESCAPE: 46 | game_cleanup(&game, EXIT_SUCCESS); 47 | break; 48 | default: 49 | break; 50 | } 51 | default: 52 | break; 53 | } 54 | } 55 | SDL_RenderClear(game.renderer); 56 | 57 | SDL_RenderCopy(game.renderer, game.background, NULL, NULL); 58 | 59 | SDL_RenderPresent(game.renderer); 60 | 61 | SDL_Delay(16); 62 | } 63 | 64 | game_cleanup(&game, EXIT_SUCCESS); 65 | 66 | return 0; 67 | } 68 | 69 | void game_cleanup(struct Game *game, int exit_status) { 70 | SDL_DestroyTexture(game->background); 71 | SDL_DestroyRenderer(game->renderer); 72 | SDL_DestroyWindow(game->window); 73 | IMG_Quit(); 74 | SDL_Quit(); 75 | exit(exit_status); 76 | } 77 | 78 | bool sdl_initialize(struct Game *game) { 79 | if (SDL_Init(SDL_INIT_EVERYTHING)) { 80 | fprintf(stderr, "Error initializing SDL: %s\n", SDL_GetError()); 81 | return true; 82 | } 83 | 84 | int img_init = IMG_Init(IMAGE_FLAGS); 85 | if ((img_init & IMAGE_FLAGS) != IMAGE_FLAGS) { 86 | fprintf(stderr, "Error initializing SDL_image: %s\n", IMG_GetError()); 87 | return true; 88 | } 89 | 90 | game->window = SDL_CreateWindow(WINDOW_TITLE, SDL_WINDOWPOS_CENTERED, 91 | SDL_WINDOWPOS_CENTERED, SCREEN_WIDTH, 92 | SCREEN_HEIGHT, 0); 93 | if (!game->window) { 94 | fprintf(stderr, "Error creating window: %s\n", SDL_GetError()); 95 | return true; 96 | } 97 | 98 | game->renderer = SDL_CreateRenderer(game->window, -1, 0); 99 | if (!game->renderer) { 100 | fprintf(stderr, "Error creating renderer: %s\n", SDL_GetError()); 101 | return true; 102 | } 103 | 104 | return false; 105 | } 106 | 107 | bool load_media(struct Game *game) { 108 | game->background = IMG_LoadTexture(game->renderer, "images/background.png"); 109 | if (!game->background) { 110 | fprintf(stderr, "Error creating Texture: %s\n", IMG_GetError()); 111 | return true; 112 | } 113 | 114 | return false; 115 | } 116 | -------------------------------------------------------------------------------- /04-Colors.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #define WINDOW_TITLE "04 Colors" 9 | #define SCREEN_WIDTH 800 10 | #define SCREEN_HEIGHT 600 11 | #define IMAGE_FLAGS IMG_INIT_PNG 12 | 13 | struct Game { 14 | SDL_Window *window; 15 | SDL_Renderer *renderer; 16 | SDL_Texture *background; 17 | }; 18 | 19 | void game_cleanup(struct Game *game, int exit_status); 20 | bool load_media(struct Game *game); 21 | bool sdl_initialize(struct Game *game); 22 | 23 | int main() { 24 | struct Game game = { 25 | .window = NULL, 26 | .renderer = NULL, 27 | .background = NULL, 28 | }; 29 | 30 | if (sdl_initialize(&game)) { 31 | game_cleanup(&game, EXIT_FAILURE); 32 | } 33 | 34 | if (load_media(&game)) { 35 | game_cleanup(&game, EXIT_FAILURE); 36 | } 37 | 38 | while (true) { 39 | SDL_Event event; 40 | while (SDL_PollEvent(&event)) { 41 | switch (event.type) { 42 | case SDL_QUIT: 43 | game_cleanup(&game, EXIT_SUCCESS); 44 | break; 45 | case SDL_KEYDOWN: 46 | switch (event.key.keysym.scancode) { 47 | case SDL_SCANCODE_ESCAPE: 48 | game_cleanup(&game, EXIT_SUCCESS); 49 | break; 50 | case SDL_SCANCODE_SPACE: 51 | SDL_SetRenderDrawColor(game.renderer, rand() % 256, 52 | rand() % 256, rand() % 256, 255); 53 | break; 54 | default: 55 | break; 56 | } 57 | default: 58 | break; 59 | } 60 | } 61 | SDL_RenderClear(game.renderer); 62 | 63 | SDL_RenderCopy(game.renderer, game.background, NULL, NULL); 64 | 65 | SDL_RenderPresent(game.renderer); 66 | 67 | SDL_Delay(16); 68 | } 69 | 70 | game_cleanup(&game, EXIT_SUCCESS); 71 | 72 | return 0; 73 | } 74 | 75 | void game_cleanup(struct Game *game, int exit_status) { 76 | SDL_DestroyTexture(game->background); 77 | SDL_DestroyRenderer(game->renderer); 78 | SDL_DestroyWindow(game->window); 79 | IMG_Quit(); 80 | SDL_Quit(); 81 | exit(exit_status); 82 | } 83 | 84 | bool sdl_initialize(struct Game *game) { 85 | if (SDL_Init(SDL_INIT_EVERYTHING)) { 86 | fprintf(stderr, "Error initializing SDL: %s\n", SDL_GetError()); 87 | return true; 88 | } 89 | 90 | int img_init = IMG_Init(IMAGE_FLAGS); 91 | if ((img_init & IMAGE_FLAGS) != IMAGE_FLAGS) { 92 | fprintf(stderr, "Error initializing SDL_image: %s\n", IMG_GetError()); 93 | return true; 94 | } 95 | 96 | game->window = SDL_CreateWindow(WINDOW_TITLE, SDL_WINDOWPOS_CENTERED, 97 | SDL_WINDOWPOS_CENTERED, SCREEN_WIDTH, 98 | SCREEN_HEIGHT, 0); 99 | if (!game->window) { 100 | fprintf(stderr, "Error creating window: %s\n", SDL_GetError()); 101 | return true; 102 | } 103 | 104 | game->renderer = SDL_CreateRenderer(game->window, -1, 0); 105 | if (!game->renderer) { 106 | fprintf(stderr, "Error creating renderer: %s\n", SDL_GetError()); 107 | return true; 108 | } 109 | 110 | srand((unsigned)time(NULL)); 111 | 112 | return false; 113 | } 114 | 115 | bool load_media(struct Game *game) { 116 | game->background = IMG_LoadTexture(game->renderer, "images/background.png"); 117 | if (!game->background) { 118 | fprintf(stderr, "Error creating Texture: %s\n", IMG_GetError()); 119 | return true; 120 | } 121 | 122 | return false; 123 | } 124 | -------------------------------------------------------------------------------- /05-Create-Text.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #define WINDOW_TITLE "05 Create Text" 11 | #define SCREEN_WIDTH 800 12 | #define SCREEN_HEIGHT 600 13 | #define IMAGE_FLAGS IMG_INIT_PNG 14 | #define TEXT_SIZE 80 15 | 16 | struct Game { 17 | SDL_Window *window; 18 | SDL_Renderer *renderer; 19 | SDL_Texture *background; 20 | TTF_Font *text_font; 21 | SDL_Color text_color; 22 | SDL_Rect text_rect; 23 | SDL_Texture *text_image; 24 | }; 25 | 26 | void game_cleanup(struct Game *game, int exit_status); 27 | bool load_media(struct Game *game); 28 | bool sdl_initialize(struct Game *game); 29 | 30 | int main() { 31 | struct Game game = { 32 | .window = NULL, 33 | .renderer = NULL, 34 | .background = NULL, 35 | .text_font = NULL, 36 | .text_color = {255, 255, 255, 255}, 37 | .text_rect = {0, 0, 0, 0}, 38 | .text_image = NULL, 39 | }; 40 | 41 | if (sdl_initialize(&game)) { 42 | game_cleanup(&game, EXIT_FAILURE); 43 | } 44 | 45 | if (load_media(&game)) { 46 | game_cleanup(&game, EXIT_FAILURE); 47 | } 48 | 49 | while (true) { 50 | SDL_Event event; 51 | while (SDL_PollEvent(&event)) { 52 | switch (event.type) { 53 | case SDL_QUIT: 54 | game_cleanup(&game, EXIT_SUCCESS); 55 | break; 56 | case SDL_KEYDOWN: 57 | switch (event.key.keysym.scancode) { 58 | case SDL_SCANCODE_ESCAPE: 59 | game_cleanup(&game, EXIT_SUCCESS); 60 | break; 61 | case SDL_SCANCODE_SPACE: 62 | SDL_SetRenderDrawColor(game.renderer, rand() % 256, 63 | rand() % 256, rand() % 256, 255); 64 | break; 65 | default: 66 | break; 67 | } 68 | default: 69 | break; 70 | } 71 | } 72 | SDL_RenderClear(game.renderer); 73 | 74 | SDL_RenderCopy(game.renderer, game.background, NULL, NULL); 75 | 76 | SDL_RenderCopy(game.renderer, game.text_image, NULL, &game.text_rect); 77 | 78 | SDL_RenderPresent(game.renderer); 79 | 80 | SDL_Delay(16); 81 | } 82 | 83 | game_cleanup(&game, EXIT_SUCCESS); 84 | 85 | return 0; 86 | } 87 | 88 | void game_cleanup(struct Game *game, int exit_status) { 89 | SDL_DestroyTexture(game->text_image); 90 | TTF_CloseFont(game->text_font); 91 | SDL_DestroyTexture(game->background); 92 | SDL_DestroyRenderer(game->renderer); 93 | SDL_DestroyWindow(game->window); 94 | TTF_Quit(); 95 | IMG_Quit(); 96 | SDL_Quit(); 97 | exit(exit_status); 98 | } 99 | 100 | bool sdl_initialize(struct Game *game) { 101 | if (SDL_Init(SDL_INIT_EVERYTHING)) { 102 | fprintf(stderr, "Error initializing SDL: %s\n", SDL_GetError()); 103 | return true; 104 | } 105 | 106 | int img_init = IMG_Init(IMAGE_FLAGS); 107 | if ((img_init & IMAGE_FLAGS) != IMAGE_FLAGS) { 108 | fprintf(stderr, "Error initializing SDL_image: %s\n", IMG_GetError()); 109 | return true; 110 | } 111 | 112 | if (TTF_Init()) { 113 | fprintf(stderr, "Error initializing SDL_ttf: %s\n", IMG_GetError()); 114 | return true; 115 | } 116 | 117 | game->window = SDL_CreateWindow(WINDOW_TITLE, SDL_WINDOWPOS_CENTERED, 118 | SDL_WINDOWPOS_CENTERED, SCREEN_WIDTH, 119 | SCREEN_HEIGHT, 0); 120 | if (!game->window) { 121 | fprintf(stderr, "Error creating window: %s\n", SDL_GetError()); 122 | return true; 123 | } 124 | 125 | game->renderer = SDL_CreateRenderer(game->window, -1, 0); 126 | if (!game->renderer) { 127 | fprintf(stderr, "Error creating renderer: %s\n", SDL_GetError()); 128 | return true; 129 | } 130 | 131 | srand((unsigned)time(NULL)); 132 | 133 | return false; 134 | } 135 | 136 | bool load_media(struct Game *game) { 137 | game->background = IMG_LoadTexture(game->renderer, "images/background.png"); 138 | if (!game->background) { 139 | fprintf(stderr, "Error creating Texture: %s\n", IMG_GetError()); 140 | return true; 141 | } 142 | 143 | game->text_font = TTF_OpenFont("fonts/freesansbold.ttf", TEXT_SIZE); 144 | if (!game->text_font) { 145 | fprintf(stderr, "Error creating Font: %s\n", TTF_GetError()); 146 | return true; 147 | } 148 | 149 | SDL_Surface *surface = 150 | TTF_RenderText_Blended(game->text_font, "SDL", game->text_color); 151 | if (!surface) { 152 | fprintf(stderr, "Error creating Surface: %s\n", SDL_GetError()); 153 | return true; 154 | } 155 | game->text_rect.w = surface->w; 156 | game->text_rect.h = surface->h; 157 | game->text_image = SDL_CreateTextureFromSurface(game->renderer, surface); 158 | SDL_FreeSurface(surface); 159 | if (!game->text_image) { 160 | fprintf(stderr, "Error creating Texture: %s\n", SDL_GetError()); 161 | return true; 162 | } 163 | 164 | return false; 165 | } 166 | -------------------------------------------------------------------------------- /06-Moving-Text.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #define WINDOW_TITLE "06 Moving Text" 11 | #define SCREEN_WIDTH 800 12 | #define SCREEN_HEIGHT 600 13 | #define IMAGE_FLAGS IMG_INIT_PNG 14 | #define TEXT_SIZE 80 15 | 16 | struct Game { 17 | SDL_Window *window; 18 | SDL_Renderer *renderer; 19 | SDL_Texture *background; 20 | TTF_Font *text_font; 21 | SDL_Color text_color; 22 | SDL_Rect text_rect; 23 | SDL_Texture *text_image; 24 | int text_xvel; 25 | int text_yvel; 26 | }; 27 | 28 | void game_cleanup(struct Game *game, int exit_status); 29 | bool load_media(struct Game *game); 30 | bool sdl_initialize(struct Game *game); 31 | void text_update(struct Game *game); 32 | 33 | int main() { 34 | struct Game game = { 35 | .window = NULL, 36 | .renderer = NULL, 37 | .background = NULL, 38 | .text_font = NULL, 39 | .text_color = {255, 255, 255, 255}, 40 | .text_rect = {100, 0, 0, 0}, 41 | .text_image = NULL, 42 | .text_xvel = 3, 43 | .text_yvel = 3, 44 | }; 45 | 46 | if (sdl_initialize(&game)) { 47 | game_cleanup(&game, EXIT_FAILURE); 48 | } 49 | 50 | if (load_media(&game)) { 51 | game_cleanup(&game, EXIT_FAILURE); 52 | } 53 | 54 | while (true) { 55 | SDL_Event event; 56 | while (SDL_PollEvent(&event)) { 57 | switch (event.type) { 58 | case SDL_QUIT: 59 | game_cleanup(&game, EXIT_SUCCESS); 60 | break; 61 | case SDL_KEYDOWN: 62 | switch (event.key.keysym.scancode) { 63 | case SDL_SCANCODE_ESCAPE: 64 | game_cleanup(&game, EXIT_SUCCESS); 65 | break; 66 | case SDL_SCANCODE_SPACE: 67 | SDL_SetRenderDrawColor(game.renderer, rand() % 256, 68 | rand() % 256, rand() % 256, 255); 69 | break; 70 | default: 71 | break; 72 | } 73 | default: 74 | break; 75 | } 76 | } 77 | 78 | text_update(&game); 79 | 80 | SDL_RenderClear(game.renderer); 81 | 82 | SDL_RenderCopy(game.renderer, game.background, NULL, NULL); 83 | 84 | SDL_RenderCopy(game.renderer, game.text_image, NULL, &game.text_rect); 85 | 86 | SDL_RenderPresent(game.renderer); 87 | 88 | SDL_Delay(16); 89 | } 90 | 91 | game_cleanup(&game, EXIT_SUCCESS); 92 | 93 | return 0; 94 | } 95 | 96 | void game_cleanup(struct Game *game, int exit_status) { 97 | SDL_DestroyTexture(game->text_image); 98 | TTF_CloseFont(game->text_font); 99 | SDL_DestroyTexture(game->background); 100 | SDL_DestroyRenderer(game->renderer); 101 | SDL_DestroyWindow(game->window); 102 | TTF_Quit(); 103 | IMG_Quit(); 104 | SDL_Quit(); 105 | exit(exit_status); 106 | } 107 | 108 | bool sdl_initialize(struct Game *game) { 109 | if (SDL_Init(SDL_INIT_EVERYTHING)) { 110 | fprintf(stderr, "Error initializing SDL: %s\n", SDL_GetError()); 111 | return true; 112 | } 113 | 114 | int img_init = IMG_Init(IMAGE_FLAGS); 115 | if ((img_init & IMAGE_FLAGS) != IMAGE_FLAGS) { 116 | fprintf(stderr, "Error initializing SDL_image: %s\n", IMG_GetError()); 117 | return true; 118 | } 119 | 120 | if (TTF_Init()) { 121 | fprintf(stderr, "Error initializing SDL_ttf: %s\n", IMG_GetError()); 122 | return true; 123 | } 124 | 125 | game->window = SDL_CreateWindow(WINDOW_TITLE, SDL_WINDOWPOS_CENTERED, 126 | SDL_WINDOWPOS_CENTERED, SCREEN_WIDTH, 127 | SCREEN_HEIGHT, 0); 128 | if (!game->window) { 129 | fprintf(stderr, "Error creating window: %s\n", SDL_GetError()); 130 | return true; 131 | } 132 | 133 | game->renderer = SDL_CreateRenderer(game->window, -1, 0); 134 | if (!game->renderer) { 135 | fprintf(stderr, "Error creating renderer: %s\n", SDL_GetError()); 136 | return true; 137 | } 138 | 139 | srand((unsigned)time(NULL)); 140 | 141 | return false; 142 | } 143 | 144 | bool load_media(struct Game *game) { 145 | game->background = IMG_LoadTexture(game->renderer, "images/background.png"); 146 | if (!game->background) { 147 | fprintf(stderr, "Error creating Texture: %s\n", IMG_GetError()); 148 | return true; 149 | } 150 | 151 | game->text_font = TTF_OpenFont("fonts/freesansbold.ttf", TEXT_SIZE); 152 | if (!game->text_font) { 153 | fprintf(stderr, "Error creating Font: %s\n", TTF_GetError()); 154 | return true; 155 | } 156 | 157 | SDL_Surface *surface = 158 | TTF_RenderText_Blended(game->text_font, "SDL", game->text_color); 159 | if (!surface) { 160 | fprintf(stderr, "Error creating Surface: %s\n", SDL_GetError()); 161 | return true; 162 | } 163 | game->text_rect.w = surface->w; 164 | game->text_rect.h = surface->h; 165 | game->text_image = SDL_CreateTextureFromSurface(game->renderer, surface); 166 | SDL_FreeSurface(surface); 167 | if (!game->text_image) { 168 | fprintf(stderr, "Error creating Texture: %s\n", SDL_GetError()); 169 | return true; 170 | } 171 | 172 | return false; 173 | } 174 | 175 | void text_update(struct Game *game) { 176 | game->text_rect.x += game->text_xvel; 177 | game->text_rect.y += game->text_yvel; 178 | if (game->text_rect.x + game->text_rect.w > SCREEN_WIDTH) { 179 | game->text_xvel = -3; 180 | } 181 | if (game->text_rect.x < 0) { 182 | game->text_xvel = 3; 183 | } 184 | if (game->text_rect.y + game->text_rect.h > SCREEN_HEIGHT) { 185 | game->text_yvel = -3; 186 | } 187 | if (game->text_rect.y < 0) { 188 | game->text_yvel = 3; 189 | } 190 | } 191 | -------------------------------------------------------------------------------- /07-Player-Sprite.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #define WINDOW_TITLE "07 Player Sprite" 11 | #define SCREEN_WIDTH 800 12 | #define SCREEN_HEIGHT 600 13 | #define IMAGE_FLAGS IMG_INIT_PNG 14 | #define TEXT_SIZE 80 15 | 16 | struct Game { 17 | SDL_Window *window; 18 | SDL_Renderer *renderer; 19 | SDL_Texture *background; 20 | TTF_Font *text_font; 21 | SDL_Color text_color; 22 | SDL_Rect text_rect; 23 | SDL_Texture *text_image; 24 | int text_xvel; 25 | int text_yvel; 26 | SDL_Texture *sprite_image; 27 | SDL_Rect sprite_rect; 28 | int sprite_vel; 29 | const Uint8 *keystate; 30 | }; 31 | 32 | void game_cleanup(struct Game *game, int exit_status); 33 | bool load_media(struct Game *game); 34 | bool sdl_initialize(struct Game *game); 35 | void text_update(struct Game *game); 36 | void sprite_update(struct Game *game); 37 | 38 | int main() { 39 | struct Game game = { 40 | .window = NULL, 41 | .renderer = NULL, 42 | .background = NULL, 43 | .text_font = NULL, 44 | .text_color = {255, 255, 255, 255}, 45 | .text_rect = {100, 0, 0, 0}, 46 | .text_image = NULL, 47 | .text_xvel = 3, 48 | .text_yvel = 3, 49 | .sprite_image = NULL, 50 | .sprite_rect = {0, 0, 0, 0}, 51 | .sprite_vel = 5, 52 | .keystate = SDL_GetKeyboardState(NULL), 53 | }; 54 | 55 | if (sdl_initialize(&game)) { 56 | game_cleanup(&game, EXIT_FAILURE); 57 | } 58 | 59 | if (load_media(&game)) { 60 | game_cleanup(&game, EXIT_FAILURE); 61 | } 62 | 63 | while (true) { 64 | SDL_Event event; 65 | while (SDL_PollEvent(&event)) { 66 | switch (event.type) { 67 | case SDL_QUIT: 68 | game_cleanup(&game, EXIT_SUCCESS); 69 | break; 70 | case SDL_KEYDOWN: 71 | switch (event.key.keysym.scancode) { 72 | case SDL_SCANCODE_ESCAPE: 73 | game_cleanup(&game, EXIT_SUCCESS); 74 | break; 75 | case SDL_SCANCODE_SPACE: 76 | SDL_SetRenderDrawColor(game.renderer, rand() % 256, 77 | rand() % 256, rand() % 256, 255); 78 | break; 79 | default: 80 | break; 81 | } 82 | default: 83 | break; 84 | } 85 | } 86 | 87 | text_update(&game); 88 | 89 | sprite_update(&game); 90 | 91 | SDL_RenderClear(game.renderer); 92 | 93 | SDL_RenderCopy(game.renderer, game.background, NULL, NULL); 94 | 95 | SDL_RenderCopy(game.renderer, game.text_image, NULL, &game.text_rect); 96 | 97 | SDL_RenderCopy(game.renderer, game.sprite_image, NULL, 98 | &game.sprite_rect); 99 | 100 | SDL_RenderPresent(game.renderer); 101 | 102 | SDL_Delay(16); 103 | } 104 | 105 | game_cleanup(&game, EXIT_SUCCESS); 106 | 107 | return 0; 108 | } 109 | 110 | void game_cleanup(struct Game *game, int exit_status) { 111 | SDL_DestroyTexture(game->sprite_image); 112 | SDL_DestroyTexture(game->text_image); 113 | TTF_CloseFont(game->text_font); 114 | SDL_DestroyTexture(game->background); 115 | SDL_DestroyRenderer(game->renderer); 116 | SDL_DestroyWindow(game->window); 117 | TTF_Quit(); 118 | IMG_Quit(); 119 | SDL_Quit(); 120 | exit(exit_status); 121 | } 122 | 123 | bool sdl_initialize(struct Game *game) { 124 | if (SDL_Init(SDL_INIT_EVERYTHING)) { 125 | fprintf(stderr, "Error initializing SDL: %s\n", SDL_GetError()); 126 | return true; 127 | } 128 | 129 | int img_init = IMG_Init(IMAGE_FLAGS); 130 | if ((img_init & IMAGE_FLAGS) != IMAGE_FLAGS) { 131 | fprintf(stderr, "Error initializing SDL_image: %s\n", IMG_GetError()); 132 | return true; 133 | } 134 | 135 | if (TTF_Init()) { 136 | fprintf(stderr, "Error initializing SDL_ttf: %s\n", IMG_GetError()); 137 | return true; 138 | } 139 | 140 | game->window = SDL_CreateWindow(WINDOW_TITLE, SDL_WINDOWPOS_CENTERED, 141 | SDL_WINDOWPOS_CENTERED, SCREEN_WIDTH, 142 | SCREEN_HEIGHT, 0); 143 | if (!game->window) { 144 | fprintf(stderr, "Error creating window: %s\n", SDL_GetError()); 145 | return true; 146 | } 147 | 148 | game->renderer = SDL_CreateRenderer(game->window, -1, 0); 149 | if (!game->renderer) { 150 | fprintf(stderr, "Error creating renderer: %s\n", SDL_GetError()); 151 | return true; 152 | } 153 | 154 | srand((unsigned)time(NULL)); 155 | 156 | return false; 157 | } 158 | 159 | bool load_media(struct Game *game) { 160 | game->background = IMG_LoadTexture(game->renderer, "images/background.png"); 161 | if (!game->background) { 162 | fprintf(stderr, "Error creating Texture: %s\n", IMG_GetError()); 163 | return true; 164 | } 165 | 166 | game->text_font = TTF_OpenFont("fonts/freesansbold.ttf", TEXT_SIZE); 167 | if (!game->text_font) { 168 | fprintf(stderr, "Error creating Font: %s\n", TTF_GetError()); 169 | return true; 170 | } 171 | 172 | SDL_Surface *surface = 173 | TTF_RenderText_Blended(game->text_font, "SDL", game->text_color); 174 | if (!surface) { 175 | fprintf(stderr, "Error creating Surface: %s\n", SDL_GetError()); 176 | return true; 177 | } 178 | game->text_rect.w = surface->w; 179 | game->text_rect.h = surface->h; 180 | game->text_image = SDL_CreateTextureFromSurface(game->renderer, surface); 181 | SDL_FreeSurface(surface); 182 | if (!game->text_image) { 183 | fprintf(stderr, "Error creating Texture: %s\n", SDL_GetError()); 184 | return true; 185 | } 186 | 187 | game->sprite_image = IMG_LoadTexture(game->renderer, "images/C-logo.png"); 188 | if (!game->sprite_image) { 189 | fprintf(stderr, "Error creating Texture: %s\n", IMG_GetError()); 190 | return true; 191 | } 192 | 193 | if (SDL_QueryTexture(game->sprite_image, NULL, NULL, &game->sprite_rect.w, 194 | &game->sprite_rect.h)) { 195 | fprintf(stderr, "Error querying Texture: %s\n", SDL_GetError()); 196 | return true; 197 | } 198 | 199 | return false; 200 | } 201 | 202 | void text_update(struct Game *game) { 203 | game->text_rect.x += game->text_xvel; 204 | game->text_rect.y += game->text_yvel; 205 | if (game->text_rect.x + game->text_rect.w > SCREEN_WIDTH) { 206 | game->text_xvel = -3; 207 | } 208 | if (game->text_rect.x < 0) { 209 | game->text_xvel = 3; 210 | } 211 | if (game->text_rect.y + game->text_rect.h > SCREEN_HEIGHT) { 212 | game->text_yvel = -3; 213 | } 214 | if (game->text_rect.y < 0) { 215 | game->text_yvel = 3; 216 | } 217 | } 218 | 219 | void sprite_update(struct Game *game) { 220 | if (game->keystate[SDL_SCANCODE_LEFT] || game->keystate[SDL_SCANCODE_A]) { 221 | game->sprite_rect.x -= game->sprite_vel; 222 | } 223 | if (game->keystate[SDL_SCANCODE_RIGHT] || game->keystate[SDL_SCANCODE_D]) { 224 | game->sprite_rect.x += game->sprite_vel; 225 | } 226 | if (game->keystate[SDL_SCANCODE_UP] || game->keystate[SDL_SCANCODE_W]) { 227 | game->sprite_rect.y -= game->sprite_vel; 228 | } 229 | if (game->keystate[SDL_SCANCODE_DOWN] || game->keystate[SDL_SCANCODE_S]) { 230 | game->sprite_rect.y += game->sprite_vel; 231 | } 232 | } 233 | -------------------------------------------------------------------------------- /08-Sound-Effects.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #define WINDOW_TITLE "08 Sound Effects" 11 | #define SCREEN_WIDTH 800 12 | #define SCREEN_HEIGHT 600 13 | #define IMAGE_FLAGS IMG_INIT_PNG 14 | #define TEXT_SIZE 80 15 | #define MIXER_FLAGS MIX_INIT_OGG 16 | 17 | struct Game { 18 | SDL_Window *window; 19 | SDL_Renderer *renderer; 20 | SDL_Texture *background; 21 | TTF_Font *text_font; 22 | SDL_Color text_color; 23 | SDL_Rect text_rect; 24 | SDL_Texture *text_image; 25 | int text_xvel; 26 | int text_yvel; 27 | SDL_Texture *sprite_image; 28 | SDL_Rect sprite_rect; 29 | int sprite_vel; 30 | const Uint8 *keystate; 31 | Mix_Chunk *c_sound; 32 | Mix_Chunk *sdl_sound; 33 | }; 34 | 35 | void game_cleanup(struct Game *game, int exit_status); 36 | bool load_media(struct Game *game); 37 | bool sdl_initialize(struct Game *game); 38 | void text_update(struct Game *game); 39 | void sprite_update(struct Game *game); 40 | 41 | int main() { 42 | struct Game game = { 43 | .window = NULL, 44 | .renderer = NULL, 45 | .background = NULL, 46 | .text_font = NULL, 47 | .text_color = {255, 255, 255, 255}, 48 | .text_rect = {100, 0, 0, 0}, 49 | .text_image = NULL, 50 | .text_xvel = 3, 51 | .text_yvel = 3, 52 | .sprite_image = NULL, 53 | .sprite_rect = {0, 0, 0, 0}, 54 | .sprite_vel = 5, 55 | .keystate = SDL_GetKeyboardState(NULL), 56 | .c_sound = NULL, 57 | .sdl_sound = NULL, 58 | }; 59 | 60 | if (sdl_initialize(&game)) { 61 | game_cleanup(&game, EXIT_FAILURE); 62 | } 63 | 64 | if (load_media(&game)) { 65 | game_cleanup(&game, EXIT_FAILURE); 66 | } 67 | 68 | while (true) { 69 | SDL_Event event; 70 | while (SDL_PollEvent(&event)) { 71 | switch (event.type) { 72 | case SDL_QUIT: 73 | game_cleanup(&game, EXIT_SUCCESS); 74 | break; 75 | case SDL_KEYDOWN: 76 | switch (event.key.keysym.scancode) { 77 | case SDL_SCANCODE_ESCAPE: 78 | game_cleanup(&game, EXIT_SUCCESS); 79 | break; 80 | case SDL_SCANCODE_SPACE: 81 | SDL_SetRenderDrawColor(game.renderer, rand() % 256, 82 | rand() % 256, rand() % 256, 255); 83 | Mix_PlayChannel(-1, game.c_sound, 0); 84 | break; 85 | default: 86 | break; 87 | } 88 | default: 89 | break; 90 | } 91 | } 92 | 93 | text_update(&game); 94 | 95 | sprite_update(&game); 96 | 97 | SDL_RenderClear(game.renderer); 98 | 99 | SDL_RenderCopy(game.renderer, game.background, NULL, NULL); 100 | 101 | SDL_RenderCopy(game.renderer, game.text_image, NULL, &game.text_rect); 102 | 103 | SDL_RenderCopy(game.renderer, game.sprite_image, NULL, 104 | &game.sprite_rect); 105 | 106 | SDL_RenderPresent(game.renderer); 107 | 108 | SDL_Delay(16); 109 | } 110 | 111 | game_cleanup(&game, EXIT_SUCCESS); 112 | 113 | return 0; 114 | } 115 | 116 | void game_cleanup(struct Game *game, int exit_status) { 117 | Mix_HaltChannel(-1); 118 | Mix_FreeChunk(game->sdl_sound); 119 | Mix_FreeChunk(game->c_sound); 120 | Mix_CloseAudio(); 121 | SDL_DestroyTexture(game->sprite_image); 122 | SDL_DestroyTexture(game->text_image); 123 | TTF_CloseFont(game->text_font); 124 | SDL_DestroyTexture(game->background); 125 | SDL_DestroyRenderer(game->renderer); 126 | SDL_DestroyWindow(game->window); 127 | 128 | Mix_Quit(); 129 | TTF_Quit(); 130 | IMG_Quit(); 131 | SDL_Quit(); 132 | 133 | exit(exit_status); 134 | } 135 | 136 | bool sdl_initialize(struct Game *game) { 137 | if (SDL_Init(SDL_INIT_EVERYTHING)) { 138 | fprintf(stderr, "Error initializing SDL: %s\n", SDL_GetError()); 139 | return true; 140 | } 141 | 142 | int img_init = IMG_Init(IMAGE_FLAGS); 143 | if ((img_init & IMAGE_FLAGS) != IMAGE_FLAGS) { 144 | fprintf(stderr, "Error initializing SDL_image: %s\n", IMG_GetError()); 145 | return true; 146 | } 147 | 148 | if (TTF_Init()) { 149 | fprintf(stderr, "Error initializing SDL_ttf: %s\n", IMG_GetError()); 150 | return true; 151 | } 152 | 153 | int mix_init = Mix_Init(MIXER_FLAGS); 154 | if ((mix_init & MIXER_FLAGS) != MIXER_FLAGS) { 155 | fprintf(stderr, "Error initializing SDL_mixer: %s\n", Mix_GetError()); 156 | return true; 157 | } 158 | 159 | if (Mix_OpenAudio(MIX_DEFAULT_FREQUENCY, MIX_DEFAULT_FORMAT, 160 | MIX_DEFAULT_CHANNELS, 1024)) { 161 | fprintf(stderr, "Error Opening Audio: %s\n", Mix_GetError()); 162 | return true; 163 | } 164 | 165 | game->window = SDL_CreateWindow(WINDOW_TITLE, SDL_WINDOWPOS_CENTERED, 166 | SDL_WINDOWPOS_CENTERED, SCREEN_WIDTH, 167 | SCREEN_HEIGHT, 0); 168 | if (!game->window) { 169 | fprintf(stderr, "Error creating window: %s\n", SDL_GetError()); 170 | return true; 171 | } 172 | 173 | game->renderer = SDL_CreateRenderer(game->window, -1, 0); 174 | if (!game->renderer) { 175 | fprintf(stderr, "Error creating renderer: %s\n", SDL_GetError()); 176 | return true; 177 | } 178 | 179 | srand((unsigned)time(NULL)); 180 | 181 | return false; 182 | } 183 | 184 | bool load_media(struct Game *game) { 185 | game->background = IMG_LoadTexture(game->renderer, "images/background.png"); 186 | if (!game->background) { 187 | fprintf(stderr, "Error creating Texture: %s\n", IMG_GetError()); 188 | return true; 189 | } 190 | 191 | game->text_font = TTF_OpenFont("fonts/freesansbold.ttf", TEXT_SIZE); 192 | if (!game->text_font) { 193 | fprintf(stderr, "Error creating Font: %s\n", TTF_GetError()); 194 | return true; 195 | } 196 | 197 | SDL_Surface *surface = 198 | TTF_RenderText_Blended(game->text_font, "SDL", game->text_color); 199 | if (!surface) { 200 | fprintf(stderr, "Error creating Surface: %s\n", SDL_GetError()); 201 | return true; 202 | } 203 | game->text_rect.w = surface->w; 204 | game->text_rect.h = surface->h; 205 | game->text_image = SDL_CreateTextureFromSurface(game->renderer, surface); 206 | SDL_FreeSurface(surface); 207 | if (!game->text_image) { 208 | fprintf(stderr, "Error creating Texture: %s\n", SDL_GetError()); 209 | return true; 210 | } 211 | 212 | game->sprite_image = IMG_LoadTexture(game->renderer, "images/C-logo.png"); 213 | if (!game->sprite_image) { 214 | fprintf(stderr, "Error creating Texture: %s\n", IMG_GetError()); 215 | return true; 216 | } 217 | 218 | if (SDL_QueryTexture(game->sprite_image, NULL, NULL, &game->sprite_rect.w, 219 | &game->sprite_rect.h)) { 220 | fprintf(stderr, "Error querying Texture: %s\n", SDL_GetError()); 221 | return true; 222 | } 223 | 224 | game->c_sound = Mix_LoadWAV("sounds/C.ogg"); 225 | if (!game->c_sound) { 226 | fprintf(stderr, "Error loading Chunk: %s\n", Mix_GetError()); 227 | return true; 228 | } 229 | 230 | game->sdl_sound = Mix_LoadWAV("sounds/SDL.ogg"); 231 | if (!game->sdl_sound) { 232 | fprintf(stderr, "Error loading Chunk: %s\n", Mix_GetError()); 233 | return true; 234 | } 235 | 236 | return false; 237 | } 238 | 239 | void text_update(struct Game *game) { 240 | game->text_rect.x += game->text_xvel; 241 | game->text_rect.y += game->text_yvel; 242 | if (game->text_rect.x + game->text_rect.w > SCREEN_WIDTH) { 243 | game->text_xvel = -3; 244 | Mix_PlayChannel(-1, game->sdl_sound, 0); 245 | } 246 | if (game->text_rect.x < 0) { 247 | game->text_xvel = 3; 248 | Mix_PlayChannel(-1, game->sdl_sound, 0); 249 | } 250 | if (game->text_rect.y + game->text_rect.h > SCREEN_HEIGHT) { 251 | game->text_yvel = -3; 252 | Mix_PlayChannel(-1, game->sdl_sound, 0); 253 | } 254 | if (game->text_rect.y < 0) { 255 | game->text_yvel = 3; 256 | Mix_PlayChannel(-1, game->sdl_sound, 0); 257 | } 258 | } 259 | 260 | void sprite_update(struct Game *game) { 261 | if (game->keystate[SDL_SCANCODE_LEFT] || game->keystate[SDL_SCANCODE_A]) { 262 | game->sprite_rect.x -= game->sprite_vel; 263 | } 264 | if (game->keystate[SDL_SCANCODE_RIGHT] || game->keystate[SDL_SCANCODE_D]) { 265 | game->sprite_rect.x += game->sprite_vel; 266 | } 267 | if (game->keystate[SDL_SCANCODE_UP] || game->keystate[SDL_SCANCODE_W]) { 268 | game->sprite_rect.y -= game->sprite_vel; 269 | } 270 | if (game->keystate[SDL_SCANCODE_DOWN] || game->keystate[SDL_SCANCODE_S]) { 271 | game->sprite_rect.y += game->sprite_vel; 272 | } 273 | } 274 | -------------------------------------------------------------------------------- /09-Music-and-Icon.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #define WINDOW_TITLE "09 Music and Icon" 11 | #define SCREEN_WIDTH 800 12 | #define SCREEN_HEIGHT 600 13 | #define IMAGE_FLAGS IMG_INIT_PNG 14 | #define TEXT_SIZE 80 15 | #define MIXER_FLAGS MIX_INIT_OGG 16 | 17 | struct Game { 18 | SDL_Window *window; 19 | SDL_Renderer *renderer; 20 | SDL_Texture *background; 21 | TTF_Font *text_font; 22 | SDL_Color text_color; 23 | SDL_Rect text_rect; 24 | SDL_Texture *text_image; 25 | int text_xvel; 26 | int text_yvel; 27 | SDL_Texture *sprite_image; 28 | SDL_Rect sprite_rect; 29 | int sprite_vel; 30 | const Uint8 *keystate; 31 | Mix_Chunk *c_sound; 32 | Mix_Chunk *sdl_sound; 33 | Mix_Music *music; 34 | }; 35 | 36 | void game_cleanup(struct Game *game, int exit_status); 37 | bool load_media(struct Game *game); 38 | bool sdl_initialize(struct Game *game); 39 | void text_update(struct Game *game); 40 | void sprite_update(struct Game *game); 41 | 42 | int main(void) { 43 | struct Game game = { 44 | .window = NULL, 45 | .renderer = NULL, 46 | .background = NULL, 47 | .text_font = NULL, 48 | .text_color = {255, 255, 255, 255}, 49 | .text_rect = {100, 0, 0, 0}, 50 | .text_image = NULL, 51 | .text_xvel = 3, 52 | .text_yvel = 3, 53 | .sprite_image = NULL, 54 | .sprite_rect = {0, 0, 0, 0}, 55 | .sprite_vel = 5, 56 | .keystate = SDL_GetKeyboardState(NULL), 57 | .c_sound = NULL, 58 | .sdl_sound = NULL, 59 | .music = NULL, 60 | }; 61 | 62 | if (sdl_initialize(&game)) { 63 | game_cleanup(&game, EXIT_FAILURE); 64 | } 65 | 66 | if (load_media(&game)) { 67 | game_cleanup(&game, EXIT_FAILURE); 68 | } 69 | 70 | if (Mix_PlayMusic(game.music, -1)) { 71 | fprintf(stderr, "Error Playing Music: %s\n", Mix_GetError()); 72 | return true; 73 | } 74 | 75 | while (true) { 76 | SDL_Event event; 77 | while (SDL_PollEvent(&event)) { 78 | switch (event.type) { 79 | case SDL_QUIT: 80 | game_cleanup(&game, EXIT_SUCCESS); 81 | break; 82 | case SDL_KEYDOWN: 83 | switch (event.key.keysym.scancode) { 84 | case SDL_SCANCODE_ESCAPE: 85 | game_cleanup(&game, EXIT_SUCCESS); 86 | break; 87 | case SDL_SCANCODE_SPACE: 88 | SDL_SetRenderDrawColor(game.renderer, (Uint8)rand() % 256, 89 | (Uint8)rand() % 256, 90 | (Uint8)rand() % 256, 255); 91 | Mix_PlayChannel(-1, game.c_sound, 0); 92 | break; 93 | case SDL_SCANCODE_M: 94 | if (Mix_PausedMusic()) { 95 | Mix_ResumeMusic(); 96 | } else { 97 | Mix_PauseMusic(); 98 | } 99 | break; 100 | default: 101 | break; 102 | } 103 | default: 104 | break; 105 | } 106 | } 107 | 108 | text_update(&game); 109 | 110 | sprite_update(&game); 111 | 112 | SDL_RenderClear(game.renderer); 113 | 114 | SDL_RenderCopy(game.renderer, game.background, NULL, NULL); 115 | 116 | SDL_RenderCopy(game.renderer, game.text_image, NULL, &game.text_rect); 117 | 118 | SDL_RenderCopy(game.renderer, game.sprite_image, NULL, 119 | &game.sprite_rect); 120 | 121 | SDL_RenderPresent(game.renderer); 122 | 123 | SDL_Delay(16); 124 | } 125 | 126 | game_cleanup(&game, EXIT_SUCCESS); 127 | 128 | return 0; 129 | } 130 | 131 | void game_cleanup(struct Game *game, int exit_status) { 132 | Mix_HaltMusic(); 133 | Mix_HaltChannel(-1); 134 | 135 | Mix_FreeMusic(game->music); 136 | Mix_FreeChunk(game->sdl_sound); 137 | Mix_FreeChunk(game->c_sound); 138 | SDL_DestroyTexture(game->sprite_image); 139 | SDL_DestroyTexture(game->text_image); 140 | TTF_CloseFont(game->text_font); 141 | SDL_DestroyTexture(game->background); 142 | SDL_DestroyRenderer(game->renderer); 143 | SDL_DestroyWindow(game->window); 144 | 145 | Mix_CloseAudio(); 146 | Mix_Quit(); 147 | TTF_Quit(); 148 | IMG_Quit(); 149 | SDL_Quit(); 150 | 151 | exit(exit_status); 152 | } 153 | 154 | bool sdl_initialize(struct Game *game) { 155 | if (SDL_Init(SDL_INIT_EVERYTHING)) { 156 | fprintf(stderr, "Error initializing SDL: %s\n", SDL_GetError()); 157 | return true; 158 | } 159 | 160 | int img_init = IMG_Init(IMAGE_FLAGS); 161 | if ((img_init & IMAGE_FLAGS) != IMAGE_FLAGS) { 162 | fprintf(stderr, "Error initializing SDL_image: %s\n", IMG_GetError()); 163 | return true; 164 | } 165 | 166 | if (TTF_Init()) { 167 | fprintf(stderr, "Error initializing SDL_ttf: %s\n", IMG_GetError()); 168 | return true; 169 | } 170 | 171 | int mix_init = Mix_Init(MIXER_FLAGS); 172 | if ((mix_init & MIXER_FLAGS) != MIXER_FLAGS) { 173 | fprintf(stderr, "Error initializing SDL_mixer: %s\n", Mix_GetError()); 174 | return true; 175 | } 176 | 177 | if (Mix_OpenAudio(MIX_DEFAULT_FREQUENCY, MIX_DEFAULT_FORMAT, 178 | MIX_DEFAULT_CHANNELS, 1024)) { 179 | fprintf(stderr, "Error Opening Audio: %s\n", Mix_GetError()); 180 | return true; 181 | } 182 | 183 | game->window = SDL_CreateWindow(WINDOW_TITLE, SDL_WINDOWPOS_CENTERED, 184 | SDL_WINDOWPOS_CENTERED, SCREEN_WIDTH, 185 | SCREEN_HEIGHT, 0); 186 | if (!game->window) { 187 | fprintf(stderr, "Error creating window: %s\n", SDL_GetError()); 188 | return true; 189 | } 190 | 191 | game->renderer = SDL_CreateRenderer(game->window, -1, 0); 192 | if (!game->renderer) { 193 | fprintf(stderr, "Error creating renderer: %s\n", SDL_GetError()); 194 | return true; 195 | } 196 | 197 | SDL_Surface *icon_surf = IMG_Load("images/C-logo.png"); 198 | if (!icon_surf) { 199 | fprintf(stderr, "Error loading Surface: %s\n", IMG_GetError()); 200 | return true; 201 | } 202 | 203 | SDL_SetWindowIcon(game->window, icon_surf); 204 | SDL_FreeSurface(icon_surf); 205 | 206 | srand((unsigned)time(NULL)); 207 | 208 | return false; 209 | } 210 | 211 | bool load_media(struct Game *game) { 212 | game->background = IMG_LoadTexture(game->renderer, "images/background.png"); 213 | if (!game->background) { 214 | fprintf(stderr, "Error creating Texture: %s\n", IMG_GetError()); 215 | return true; 216 | } 217 | 218 | game->text_font = TTF_OpenFont("fonts/freesansbold.ttf", TEXT_SIZE); 219 | if (!game->text_font) { 220 | fprintf(stderr, "Error creating Font: %s\n", TTF_GetError()); 221 | return true; 222 | } 223 | 224 | SDL_Surface *surface = 225 | TTF_RenderText_Blended(game->text_font, "SDL", game->text_color); 226 | if (!surface) { 227 | fprintf(stderr, "Error creating Surface: %s\n", SDL_GetError()); 228 | return true; 229 | } 230 | game->text_rect.w = surface->w; 231 | game->text_rect.h = surface->h; 232 | game->text_image = SDL_CreateTextureFromSurface(game->renderer, surface); 233 | SDL_FreeSurface(surface); 234 | if (!game->text_image) { 235 | fprintf(stderr, "Error creating Texture: %s\n", SDL_GetError()); 236 | return true; 237 | } 238 | 239 | game->sprite_image = IMG_LoadTexture(game->renderer, "images/C-logo.png"); 240 | if (!game->sprite_image) { 241 | fprintf(stderr, "Error creating Texture: %s\n", IMG_GetError()); 242 | return true; 243 | } 244 | 245 | if (SDL_QueryTexture(game->sprite_image, NULL, NULL, &game->sprite_rect.w, 246 | &game->sprite_rect.h)) { 247 | fprintf(stderr, "Error querying Texture: %s\n", SDL_GetError()); 248 | return true; 249 | } 250 | 251 | game->c_sound = Mix_LoadWAV("sounds/C.ogg"); 252 | if (!game->c_sound) { 253 | fprintf(stderr, "Error loading Chunk: %s\n", Mix_GetError()); 254 | return true; 255 | } 256 | 257 | game->sdl_sound = Mix_LoadWAV("sounds/SDL.ogg"); 258 | if (!game->sdl_sound) { 259 | fprintf(stderr, "Error loading Chunk: %s\n", Mix_GetError()); 260 | return true; 261 | } 262 | 263 | game->music = Mix_LoadMUS("music/freesoftwaresong-8bit.ogg"); 264 | if (!game->music) { 265 | fprintf(stderr, "Error loading Music: %s\n", Mix_GetError()); 266 | return true; 267 | } 268 | 269 | return false; 270 | } 271 | 272 | void text_update(struct Game *game) { 273 | game->text_rect.x += game->text_xvel; 274 | game->text_rect.y += game->text_yvel; 275 | if (game->text_rect.x + game->text_rect.w > SCREEN_WIDTH) { 276 | game->text_xvel = -3; 277 | Mix_PlayChannel(-1, game->sdl_sound, 0); 278 | } 279 | if (game->text_rect.x < 0) { 280 | game->text_xvel = 3; 281 | Mix_PlayChannel(-1, game->sdl_sound, 0); 282 | } 283 | if (game->text_rect.y + game->text_rect.h > SCREEN_HEIGHT) { 284 | game->text_yvel = -3; 285 | Mix_PlayChannel(-1, game->sdl_sound, 0); 286 | } 287 | if (game->text_rect.y < 0) { 288 | game->text_yvel = 3; 289 | Mix_PlayChannel(-1, game->sdl_sound, 0); 290 | } 291 | } 292 | 293 | void sprite_update(struct Game *game) { 294 | if (game->keystate[SDL_SCANCODE_LEFT] || game->keystate[SDL_SCANCODE_A]) { 295 | game->sprite_rect.x -= game->sprite_vel; 296 | } 297 | if (game->keystate[SDL_SCANCODE_RIGHT] || game->keystate[SDL_SCANCODE_D]) { 298 | game->sprite_rect.x += game->sprite_vel; 299 | } 300 | if (game->keystate[SDL_SCANCODE_UP] || game->keystate[SDL_SCANCODE_W]) { 301 | game->sprite_rect.y -= game->sprite_vel; 302 | } 303 | if (game->keystate[SDL_SCANCODE_DOWN] || game->keystate[SDL_SCANCODE_S]) { 304 | game->sprite_rect.y += game->sprite_vel; 305 | } 306 | } 307 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # An in-depth guide to getting started with SDL2 in the C Language. 2 | 3 | https://www.youtube.com/playlist?list=PLO02jwa2ZaiCgilk8EEVnfnGWA0LNu4As 4 | 5 | ![Screenshot](screenshot.png) 6 | -------------------------------------------------------------------------------- /fonts/freesansbold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ProgrammingRainbow/Beginners-Guide-to-SDL2-in-C/51356be4e0d3285e028b287e8d14ffd47e852ee8/fonts/freesansbold.ttf -------------------------------------------------------------------------------- /images/C-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ProgrammingRainbow/Beginners-Guide-to-SDL2-in-C/51356be4e0d3285e028b287e8d14ffd47e852ee8/images/C-logo.png -------------------------------------------------------------------------------- /images/background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ProgrammingRainbow/Beginners-Guide-to-SDL2-in-C/51356be4e0d3285e028b287e8d14ffd47e852ee8/images/background.png -------------------------------------------------------------------------------- /music/freesoftwaresong-8bit.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ProgrammingRainbow/Beginners-Guide-to-SDL2-in-C/51356be4e0d3285e028b287e8d14ffd47e852ee8/music/freesoftwaresong-8bit.ogg -------------------------------------------------------------------------------- /screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ProgrammingRainbow/Beginners-Guide-to-SDL2-in-C/51356be4e0d3285e028b287e8d14ffd47e852ee8/screenshot.png -------------------------------------------------------------------------------- /sounds/C.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ProgrammingRainbow/Beginners-Guide-to-SDL2-in-C/51356be4e0d3285e028b287e8d14ffd47e852ee8/sounds/C.ogg -------------------------------------------------------------------------------- /sounds/SDL.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ProgrammingRainbow/Beginners-Guide-to-SDL2-in-C/51356be4e0d3285e028b287e8d14ffd47e852ee8/sounds/SDL.ogg --------------------------------------------------------------------------------