This repository has been archived by the owner on Feb 11, 2021. It is now read-only.
/
testsprite.c
321 lines (290 loc) · 9.06 KB
1
2
3
4
5
6
/* Simple program: Move N sprites around on the screen as fast as possible */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
7
#include <math.h>
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <time.h>
#include "SDL.h"
#define NUM_SPRITES 100
#define MAX_SPEED 1
SDL_Surface *sprite;
int numsprites;
SDL_Rect *sprite_rects;
SDL_Rect *positions;
SDL_Rect *velocities;
int sprites_visible;
21
int debug_flip;
22
Uint16 sprite_w, sprite_h;
23
24
/* Call this instead of exit(), so we can clean up SDL: atexit() is evil. */
25
static void
26
quit(int rc)
27
{
28
29
SDL_Quit();
exit(rc);
30
31
}
32
int
33
LoadSprite(char *file)
34
{
35
SDL_Surface *temp;
36
37
/* Load the sprite image */
38
sprite = SDL_LoadBMP(file);
39
if (sprite == NULL) {
40
fprintf(stderr, "Couldn't load %s: %s", file, SDL_GetError());
41
42
return (-1);
}
43
44
45
/* Set transparent pixel as the pixel at (0,0) */
if (sprite->format->palette) {
46
47
SDL_SetColorKey(sprite, (SDL_SRCCOLORKEY | SDL_RLEACCEL),
*(Uint8 *) sprite->pixels);
48
}
49
50
/* Convert sprite to video format */
51
52
temp = SDL_DisplayFormat(sprite);
SDL_FreeSurface(sprite);
53
if (temp == NULL) {
54
fprintf(stderr, "Couldn't convert background: %s\n", SDL_GetError());
55
56
57
return (-1);
}
sprite = temp;
58
59
60
/* We're ready to roll. :) */
return (0);
61
62
}
63
void
64
MoveSprites(SDL_Surface * screen, Uint32 background)
65
{
66
67
int i, nupdates;
SDL_Rect area, *position, *velocity;
68
69
70
71
nupdates = 0;
/* Erase all the sprites if necessary */
if (sprites_visible) {
72
SDL_FillRect(screen, NULL, background);
73
}
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
/* Move the sprite, bounce at the wall, and draw */
for (i = 0; i < numsprites; ++i) {
position = &positions[i];
velocity = &velocities[i];
position->x += velocity->x;
if ((position->x < 0) || (position->x >= (screen->w - sprite_w))) {
velocity->x = -velocity->x;
position->x += velocity->x;
}
position->y += velocity->y;
if ((position->y < 0) || (position->y >= (screen->h - sprite_w))) {
velocity->y = -velocity->y;
position->y += velocity->y;
}
89
90
91
/* Blit the sprite onto the screen */
area = *position;
92
SDL_BlitSurface(sprite, NULL, screen, &area);
93
94
sprite_rects[nupdates++] = area;
}
95
96
97
98
if (debug_flip) {
if ((screen->flags & SDL_DOUBLEBUF) == SDL_DOUBLEBUF) {
static int t = 0;
99
100
Uint32 color = SDL_MapRGB(screen->format, 255, 0, 0);
101
102
SDL_Rect r;
r.x =
103
(sin((float) t * 2 * 3.1459) + 1.0) / 2.0 * (screen->w - 20);
104
105
106
r.y = 0;
r.w = 20;
r.h = screen->h;
107
108
SDL_FillRect(screen, &r, color);
109
110
111
t += 2;
}
}
112
113
114
/* Update the screen! */
if ((screen->flags & SDL_DOUBLEBUF) == SDL_DOUBLEBUF) {
115
SDL_Flip(screen);
116
} else {
117
SDL_UpdateRects(screen, nupdates, sprite_rects);
118
119
}
sprites_visible = 1;
120
121
122
}
/* This is a way of telling whether or not to use hardware surfaces */
123
Uint32
124
FastestFlags(Uint32 flags, int width, int height, int bpp)
125
{
126
const SDL_VideoInfo *info;
127
128
129
/* Hardware acceleration is only used in fullscreen mode */
flags |= SDL_FULLSCREEN;
130
131
/* Check for various video capabilities */
132
info = SDL_GetVideoInfo();
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
if (info->blit_hw_CC && info->blit_fill) {
/* We use accelerated colorkeying and color filling */
flags |= SDL_HWSURFACE;
}
/* If we have enough video memory, and will use accelerated
blits directly to it, then use page flipping.
*/
if ((flags & SDL_HWSURFACE) == SDL_HWSURFACE) {
/* Direct hardware blitting without double-buffering
causes really bad flickering.
*/
if (info->video_mem * 1024 > (height * width * bpp / 8)) {
flags |= SDL_DOUBLEBUF;
} else {
flags &= ~SDL_HWSURFACE;
}
}
150
151
152
/* Return the flags */
return (flags);
153
154
}
155
int
156
main(int argc, char *argv[])
157
{
158
159
160
161
162
163
164
165
166
SDL_Surface *screen;
Uint8 *mem;
int width, height;
Uint8 video_bpp;
Uint32 videoflags;
Uint32 background;
int i, done;
SDL_Event event;
Uint32 then, now, frames;
167
168
/* Initialize SDL */
169
170
if (SDL_Init(SDL_INIT_VIDEO) < 0) {
fprintf(stderr, "Couldn't initialize SDL: %s\n", SDL_GetError());
171
172
return (1);
}
173
174
175
176
177
178
179
180
181
numsprites = NUM_SPRITES;
videoflags = SDL_SWSURFACE | SDL_ANYFORMAT;
width = 640;
height = 480;
video_bpp = 8;
debug_flip = 0;
while (argc > 1) {
--argc;
182
183
if (strcmp(argv[argc - 1], "-width") == 0) {
width = atoi(argv[argc]);
184
--argc;
185
186
} else if (strcmp(argv[argc - 1], "-height") == 0) {
height = atoi(argv[argc]);
187
--argc;
188
189
} else if (strcmp(argv[argc - 1], "-bpp") == 0) {
video_bpp = atoi(argv[argc]);
190
191
videoflags &= ~SDL_ANYFORMAT;
--argc;
192
193
194
} else if (strcmp(argv[argc], "-fast") == 0) {
videoflags = FastestFlags(videoflags, width, height, video_bpp);
} else if (strcmp(argv[argc], "-hw") == 0) {
195
videoflags ^= SDL_HWSURFACE;
196
} else if (strcmp(argv[argc], "-flip") == 0) {
197
videoflags ^= SDL_DOUBLEBUF;
198
} else if (strcmp(argv[argc], "-debugflip") == 0) {
199
debug_flip ^= 1;
200
} else if (strcmp(argv[argc], "-fullscreen") == 0) {
201
videoflags ^= SDL_FULLSCREEN;
202
203
} else if (isdigit(argv[argc][0])) {
numsprites = atoi(argv[argc]);
204
} else {
205
206
207
208
fprintf(stderr,
"Usage: %s [-bpp N] [-hw] [-flip] [-fast] [-fullscreen] [numsprites]\n",
argv[0]);
quit(1);
209
210
}
}
211
212
/* Set video mode */
213
screen = SDL_SetVideoMode(width, height, video_bpp, videoflags);
214
if (!screen) {
215
216
217
fprintf(stderr, "Couldn't set %dx%d video mode: %s\n",
width, height, SDL_GetError());
quit(2);
218
}
219
220
/* Load the sprite */
221
222
if (LoadSprite("icon.bmp") < 0) {
quit(1);
223
}
224
225
/* Allocate memory for the sprite info */
226
mem = (Uint8 *) malloc(4 * sizeof(SDL_Rect) * numsprites);
227
if (mem == NULL) {
228
229
230
SDL_FreeSurface(sprite);
fprintf(stderr, "Out of memory!\n");
quit(2);
231
232
233
234
235
236
237
238
}
sprite_rects = (SDL_Rect *) mem;
positions = sprite_rects;
sprite_rects += numsprites;
velocities = sprite_rects;
sprite_rects += numsprites;
sprite_w = sprite->w;
sprite_h = sprite->h;
239
srand(time(NULL));
240
for (i = 0; i < numsprites; ++i) {
241
242
positions[i].x = rand() % (screen->w - sprite_w);
positions[i].y = rand() % (screen->h - sprite_h);
243
244
245
246
247
positions[i].w = sprite->w;
positions[i].h = sprite->h;
velocities[i].x = 0;
velocities[i].y = 0;
while (!velocities[i].x && !velocities[i].y) {
248
249
velocities[i].x = (rand() % (MAX_SPEED * 2 + 1)) - MAX_SPEED;
velocities[i].y = (rand() % (MAX_SPEED * 2 + 1)) - MAX_SPEED;
250
251
}
}
252
background = SDL_MapRGB(screen->format, 0x00, 0x00, 0x00);
253
254
/* Print out information about our surfaces */
255
printf("Screen is at %d bits per pixel\n", screen->format->BitsPerPixel);
256
if ((screen->flags & SDL_HWSURFACE) == SDL_HWSURFACE) {
257
printf("Screen is in video memory\n");
258
} else {
259
printf("Screen is in system memory\n");
260
261
}
if ((screen->flags & SDL_DOUBLEBUF) == SDL_DOUBLEBUF) {
262
printf("Screen has double-buffering enabled\n");
263
264
}
if ((sprite->flags & SDL_HWSURFACE) == SDL_HWSURFACE) {
265
printf("Sprite is in video memory\n");
266
} else {
267
printf("Sprite is in system memory\n");
268
269
270
271
272
273
274
275
}
/* Run a sample blit to trigger blit acceleration */
{
SDL_Rect dst;
dst.x = 0;
dst.y = 0;
dst.w = sprite->w;
dst.h = sprite->h;
276
277
SDL_BlitSurface(sprite, NULL, screen, &dst);
SDL_FillRect(screen, &dst, background);
278
279
}
if ((sprite->flags & SDL_HWACCEL) == SDL_HWACCEL) {
280
printf("Sprite blit uses hardware acceleration\n");
281
282
}
if ((sprite->flags & SDL_RLEACCEL) == SDL_RLEACCEL) {
283
printf("Sprite blit uses RLE acceleration\n");
284
}
285
286
287
/* Loop, blitting sprites and waiting for a keystroke */
frames = 0;
288
then = SDL_GetTicks();
289
290
291
292
293
done = 0;
sprites_visible = 0;
while (!done) {
/* Check for events */
++frames;
294
while (SDL_PollEvent(&event)) {
295
296
switch (event.type) {
case SDL_MOUSEBUTTONDOWN:
297
SDL_WarpMouse(screen->w / 2, screen->h / 2);
298
299
300
301
302
303
304
305
306
307
break;
case SDL_KEYDOWN:
/* Any keypress quits the app... */
case SDL_QUIT:
done = 1;
break;
default:
break;
}
}
308
MoveSprites(screen, background);
309
}
310
311
SDL_FreeSurface(sprite);
free(mem);
312
313
/* Print out some timing information */
314
now = SDL_GetTicks();
315
if (now > then) {
316
317
printf("%2.2f frames per second\n",
((double) frames * 1000) / (now - then));
318
}
319
SDL_Quit();
320
return (0);
321
}