-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathlesson04.c
172 lines (154 loc) · 4.7 KB
/
lesson04.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
// based on https://github.com/Twinklebear/TwinklebearDev-Lessons/tree/master/Lesson3/src
#include <stdio.h>
#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>
/*
* Recurse through the list of arguments to clean up, cleaning up
* the first one in the list each iteration.
*/
void cleanup_window(SDL_Window *win){
if (!win){
return;
}
SDL_DestroyWindow(win);
}
void cleanup_renderer(SDL_Renderer *ren){
if (!ren){
return;
}
SDL_DestroyRenderer(ren);
}
void cleanup_texture(SDL_Texture *tex){
if (!tex){
return;
}
SDL_DestroyTexture(tex);
}
/*
* Lesson 3: SDL Extension Libraries
*/
//Screen attributes
const int SCREEN_WIDTH = 640;
const int SCREEN_HEIGHT = 480;
//We'll be scaling our tiles to be 40x40
const int TILE_SIZE = 40;
/*
* Log an SDL error with some error message to the output stream of our choice
* @param os The output stream to write the message too
* @param msg The error message to write, format will be msg error: SDL_GetError()
*/
void logSDLError(FILE *os, const char* msg){
fprintf(os, " error: %s\n", SDL_GetError());
}
/*
* Loads an image into a texture on the rendering device
* @param file The image file to load
* @param ren The renderer to load the texture onto
* @return the loaded texture, or nullptr if something went wrong.
*/
SDL_Texture* loadTexture(const char* file, SDL_Renderer *ren){
SDL_Texture *texture = IMG_LoadTexture(ren, file);
if (texture == NULL){
logSDLError(stdout, "LoadTexture");
}
return texture;
}
/*
* Draw an SDL_Texture to an SDL_Renderer at position x, y, with some desired
* width and height
* @param tex The source texture we want to draw
* @param rend The renderer we want to draw too
* @param x The x coordinate to draw too
* @param y The y coordinate to draw too
* @param w The width of the texture to draw
* @param h The height of the texture to draw
*/
void renderTexture(SDL_Texture *tex, SDL_Renderer *ren, int x, int y, int w, int h){
//Setup the destination rectangle to be at the position we want
SDL_Rect dst;
dst.x = x;
dst.y = y;
dst.w = w;
dst.h = h;
SDL_RenderCopy(ren, tex, NULL, &dst);
}
/*
* Draw an SDL_Texture to an SDL_Renderer at position x, y, preserving
* the texture's width and height
* @param tex The source texture we want to draw
* @param rend The renderer we want to draw too
* @param x The x coordinate to draw too
* @param y The y coordinate to draw too
*/
void renderTexture2(SDL_Texture *tex, SDL_Renderer *ren, int x, int y){
int w, h;
SDL_QueryTexture(tex, NULL, NULL, &w, &h);
renderTexture(tex, ren, x, y, w, h);
}
int main(int argc, char** argv){
//Start up SDL and make sure it went ok
if (SDL_Init(SDL_INIT_VIDEO) != 0){
logSDLError(stdout, "SDL_Init");
return 1;
}
//Setup our window and renderer
SDL_Window *window = SDL_CreateWindow("Lesson 3", 100, 100, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN);
if (window == NULL){
logSDLError(stdout, "CreateWindow");
SDL_Quit();
return 1;
}
SDL_Renderer *renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
if (renderer == NULL){
logSDLError(stdout, "CreateRenderer");
cleanup_window(window);
SDL_Quit();
return 1;
}
//The textures we'll be using
SDL_Texture *background = loadTexture("./background.png", renderer);
SDL_Texture *image = loadTexture("./image.png", renderer);
//Make sure they both loaded ok
if (background == NULL || image == NULL){
cleanup_texture(background);
cleanup_texture(image);
cleanup_renderer(renderer);
cleanup_window(window);
SDL_Quit();
return 1;
}
//A sleepy rendering loop, wait for 3 seconds and render and present the screen each time
for (int i = 0; i < 3; ++i){
//Clear the window
SDL_RenderClear(renderer);
//Determine how many tiles we'll need to fill the screen
int xTiles = SCREEN_WIDTH / TILE_SIZE;
int yTiles = SCREEN_HEIGHT / TILE_SIZE;
//Draw the tiles by calculating their positions
for (int i = 0; i < xTiles * yTiles; ++i){
int x = i % xTiles;
int y = i / xTiles;
renderTexture(background, renderer, x * TILE_SIZE, y * TILE_SIZE, TILE_SIZE, TILE_SIZE);
}
//Draw our image in the center of the window
//We need the foreground image's width to properly compute the position
//of it's top left corner so that the image will be centered
int iW, iH;
SDL_QueryTexture(image, NULL, NULL, &iW, &iH);
int x = SCREEN_WIDTH / 2 - iW / 2;
int y = SCREEN_HEIGHT / 2 - iH / 2;
renderTexture2(image, renderer, x, y);
//Update the screen
SDL_RenderPresent(renderer);
//Take a quick break after all that hard work
SDL_Delay(1000);
}
//Destroy the various items
cleanup_texture(background);
cleanup_texture(image);
cleanup_renderer(renderer);
cleanup_window(window);
IMG_Quit();
SDL_Quit();
return 0;
}