1 | /* |
2 | Copyright (C) 1997-2021 Sam Lantinga <slouken@libsdl.org> |
3 | |
4 | This software is provided 'as-is', without any express or implied |
5 | warranty. In no event will the authors be held liable for any damages |
6 | arising from the use of this software. |
7 | |
8 | Permission is granted to anyone to use this software for any purpose, |
9 | including commercial applications, and to alter it and redistribute it |
10 | freely. |
11 | */ |
12 | /* Simple program: Move N sprites around on the screen as fast as possible */ |
13 | |
14 | #include <stdlib.h> |
15 | #include <stdio.h> |
16 | #include <time.h> |
17 | |
18 | #ifdef __EMSCRIPTEN__ |
19 | #include <emscripten/emscripten.h> |
20 | #endif |
21 | |
22 | #include "SDL.h" |
23 | |
24 | #define WINDOW_WIDTH 640 |
25 | #define WINDOW_HEIGHT 480 |
26 | #define NUM_SPRITES 100 |
27 | #define MAX_SPEED 1 |
28 | |
29 | static SDL_Texture *sprite; |
30 | static SDL_Rect positions[NUM_SPRITES]; |
31 | static SDL_Rect velocities[NUM_SPRITES]; |
32 | static int sprite_w, sprite_h; |
33 | |
34 | SDL_Renderer *renderer; |
35 | int done; |
36 | |
37 | /* Call this instead of exit(), so we can clean up SDL: atexit() is evil. */ |
38 | static void |
39 | quit(int rc) |
40 | { |
41 | SDL_Quit(); |
42 | exit(rc); |
43 | } |
44 | |
45 | int |
46 | LoadSprite(char *file) |
47 | { |
48 | SDL_Surface *temp; |
49 | |
50 | /* Load the sprite image */ |
51 | temp = SDL_LoadBMP(file); |
52 | if (temp == NULL) { |
53 | SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't load %s: %s\n" , file, SDL_GetError()); |
54 | return (-1); |
55 | } |
56 | sprite_w = temp->w; |
57 | sprite_h = temp->h; |
58 | |
59 | /* Set transparent pixel as the pixel at (0,0) */ |
60 | if (temp->format->palette) { |
61 | SDL_SetColorKey(temp, SDL_TRUE, *(Uint8 *) temp->pixels); |
62 | } else { |
63 | switch (temp->format->BitsPerPixel) { |
64 | case 15: |
65 | SDL_SetColorKey(temp, SDL_TRUE, |
66 | (*(Uint16 *) temp->pixels) & 0x00007FFF); |
67 | break; |
68 | case 16: |
69 | SDL_SetColorKey(temp, SDL_TRUE, *(Uint16 *) temp->pixels); |
70 | break; |
71 | case 24: |
72 | SDL_SetColorKey(temp, SDL_TRUE, |
73 | (*(Uint32 *) temp->pixels) & 0x00FFFFFF); |
74 | break; |
75 | case 32: |
76 | SDL_SetColorKey(temp, SDL_TRUE, *(Uint32 *) temp->pixels); |
77 | break; |
78 | } |
79 | } |
80 | |
81 | /* Create textures from the image */ |
82 | sprite = SDL_CreateTextureFromSurface(renderer, temp); |
83 | if (!sprite) { |
84 | SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't create texture: %s\n" , SDL_GetError()); |
85 | SDL_FreeSurface(temp); |
86 | return (-1); |
87 | } |
88 | SDL_FreeSurface(temp); |
89 | |
90 | /* We're ready to roll. :) */ |
91 | return (0); |
92 | } |
93 | |
94 | void |
95 | MoveSprites() |
96 | { |
97 | int i; |
98 | int window_w = WINDOW_WIDTH; |
99 | int window_h = WINDOW_HEIGHT; |
100 | SDL_Rect *position, *velocity; |
101 | |
102 | /* Draw a gray background */ |
103 | SDL_SetRenderDrawColor(renderer, 0xA0, 0xA0, 0xA0, 0xFF); |
104 | SDL_RenderClear(renderer); |
105 | |
106 | /* Move the sprite, bounce at the wall, and draw */ |
107 | for (i = 0; i < NUM_SPRITES; ++i) { |
108 | position = &positions[i]; |
109 | velocity = &velocities[i]; |
110 | position->x += velocity->x; |
111 | if ((position->x < 0) || (position->x >= (window_w - sprite_w))) { |
112 | velocity->x = -velocity->x; |
113 | position->x += velocity->x; |
114 | } |
115 | position->y += velocity->y; |
116 | if ((position->y < 0) || (position->y >= (window_h - sprite_h))) { |
117 | velocity->y = -velocity->y; |
118 | position->y += velocity->y; |
119 | } |
120 | |
121 | /* Blit the sprite onto the screen */ |
122 | SDL_RenderCopy(renderer, sprite, NULL, position); |
123 | } |
124 | |
125 | /* Update the screen! */ |
126 | SDL_RenderPresent(renderer); |
127 | } |
128 | |
129 | void loop() |
130 | { |
131 | SDL_Event event; |
132 | |
133 | /* Check for events */ |
134 | while (SDL_PollEvent(&event)) { |
135 | if (event.type == SDL_QUIT || event.type == SDL_KEYDOWN) { |
136 | done = 1; |
137 | } |
138 | } |
139 | MoveSprites(); |
140 | #ifdef __EMSCRIPTEN__ |
141 | if (done) { |
142 | emscripten_cancel_main_loop(); |
143 | } |
144 | #endif |
145 | } |
146 | |
147 | int |
148 | main(int argc, char *argv[]) |
149 | { |
150 | SDL_Window *window; |
151 | int i; |
152 | |
153 | |
154 | /* Enable standard application logging */ |
155 | SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO); |
156 | |
157 | if (SDL_CreateWindowAndRenderer(WINDOW_WIDTH, WINDOW_HEIGHT, 0, &window, &renderer) < 0) { |
158 | quit(2); |
159 | } |
160 | |
161 | if (LoadSprite("icon.bmp" ) < 0) { |
162 | quit(2); |
163 | } |
164 | |
165 | /* Initialize the sprite positions */ |
166 | srand(time(NULL)); |
167 | for (i = 0; i < NUM_SPRITES; ++i) { |
168 | positions[i].x = rand() % (WINDOW_WIDTH - sprite_w); |
169 | positions[i].y = rand() % (WINDOW_HEIGHT - sprite_h); |
170 | positions[i].w = sprite_w; |
171 | positions[i].h = sprite_h; |
172 | velocities[i].x = 0; |
173 | velocities[i].y = 0; |
174 | while (!velocities[i].x && !velocities[i].y) { |
175 | velocities[i].x = (rand() % (MAX_SPEED * 2 + 1)) - MAX_SPEED; |
176 | velocities[i].y = (rand() % (MAX_SPEED * 2 + 1)) - MAX_SPEED; |
177 | } |
178 | } |
179 | |
180 | /* Main render loop */ |
181 | done = 0; |
182 | |
183 | #ifdef __EMSCRIPTEN__ |
184 | emscripten_set_main_loop(loop, 0, 1); |
185 | #else |
186 | while (!done) { |
187 | loop(); |
188 | } |
189 | #endif |
190 | quit(0); |
191 | |
192 | return 0; /* to prevent compiler warning */ |
193 | } |
194 | |
195 | /* vi: set ts=4 sw=4 expandtab: */ |
196 | |