testsprite2.c
Go to the documentation of this file.
/*
Copyright (C) 1997-2016 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely.
*/
/* Simple program: Move N sprites around on the screen as fast as possible */
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#ifdef __EMSCRIPTEN__
#include <emscripten/emscripten.h>
#endif
#include "SDL_test.h"
#include "SDL_test_common.h"
#define NUM_SPRITES 100
#define MAX_SPEED 1
static SDLTest_CommonState *state;
static int num_sprites;
static SDL_Texture **sprites;
static SDL_bool cycle_color;
static SDL_bool cycle_alpha;
static int cycle_direction = 1;
static int current_alpha = 0;
static int current_color = 0;
static SDL_Rect *positions;
static SDL_Rect *velocities;
static int sprite_w, sprite_h;
static SDL_BlendMode blendMode = SDL_BLENDMODE_BLEND;
/* Number of iterations to move sprites - used for visual tests. */
/* -1: infinite random moves (default); >=0: enables N deterministic moves */
static int iterations = -1;
int done;
/* Call this instead of exit(), so we can clean up SDL: atexit() is evil. */
static void
quit(int rc)
{
SDL_free(sprites);
SDL_free(positions);
SDL_free(velocities);
SDLTest_CommonQuit(state);
exit(rc);
}
int
LoadSprite(const char *file)
{
int i;
SDL_Surface *temp;
/* Load the sprite image */
temp = SDL_LoadBMP(file);
if (temp == NULL) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't load %s: %s", file, SDL_GetError());
return (-1);
}
sprite_w = temp->w;
sprite_h = temp->h;
/* Set transparent pixel as the pixel at (0,0) */
if (temp->format->palette) {
SDL_SetColorKey(temp, 1, *(Uint8 *) temp->pixels);
} else {
switch (temp->format->BitsPerPixel) {
case 15:
SDL_SetColorKey(temp, 1, (*(Uint16 *) temp->pixels) & 0x00007FFF);
break;
case 16:
SDL_SetColorKey(temp, 1, *(Uint16 *) temp->pixels);
break;
case 24:
SDL_SetColorKey(temp, 1, (*(Uint32 *) temp->pixels) & 0x00FFFFFF);
break;
case 32:
SDL_SetColorKey(temp, 1, *(Uint32 *) temp->pixels);
break;
}
}
/* Create textures from the image */
for (i = 0; i < state->num_windows; ++i) {
SDL_Renderer *renderer = state->renderers[i];
sprites[i] = SDL_CreateTextureFromSurface(renderer, temp);
if (!sprites[i]) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't create texture: %s\n", SDL_GetError());
SDL_FreeSurface(temp);
return (-1);
}
SDL_SetTextureBlendMode(sprites[i], blendMode);
}
SDL_FreeSurface(temp);
/* We're ready to roll. :) */
return (0);
}
void
MoveSprites(SDL_Renderer * renderer, SDL_Texture * sprite)
{
int i;
SDL_Rect viewport, temp;
SDL_Rect *position, *velocity;
/* Query the sizes */
SDL_RenderGetViewport(renderer, &viewport);
/* Cycle the color and alpha, if desired */
if (cycle_color) {
current_color += cycle_direction;
if (current_color < 0) {
current_color = 0;
cycle_direction = -cycle_direction;
}
if (current_color > 255) {
current_color = 255;
cycle_direction = -cycle_direction;
}
SDL_SetTextureColorMod(sprite, 255, (Uint8) current_color,
(Uint8) current_color);
}
if (cycle_alpha) {
current_alpha += cycle_direction;
if (current_alpha < 0) {
current_alpha = 0;
cycle_direction = -cycle_direction;
}
if (current_alpha > 255) {
current_alpha = 255;
cycle_direction = -cycle_direction;
}
SDL_SetTextureAlphaMod(sprite, (Uint8) current_alpha);
}
/* Draw a gray background */
SDL_SetRenderDrawColor(renderer, 0xA0, 0xA0, 0xA0, 0xFF);
SDL_RenderClear(renderer);
/* Test points */
SDL_SetRenderDrawColor(renderer, 0xFF, 0x00, 0x00, 0xFF);
SDL_RenderDrawPoint(renderer, 0, 0);
SDL_RenderDrawPoint(renderer, viewport.w-1, 0);
SDL_RenderDrawPoint(renderer, 0, viewport.h-1);
SDL_RenderDrawPoint(renderer, viewport.w-1, viewport.h-1);
/* Test horizontal and vertical lines */
SDL_SetRenderDrawColor(renderer, 0x00, 0xFF, 0x00, 0xFF);
SDL_RenderDrawLine(renderer, 1, 0, viewport.w-2, 0);
SDL_RenderDrawLine(renderer, 1, viewport.h-1, viewport.w-2, viewport.h-1);
SDL_RenderDrawLine(renderer, 0, 1, 0, viewport.h-2);
SDL_RenderDrawLine(renderer, viewport.w-1, 1, viewport.w-1, viewport.h-2);
/* Test fill and copy */
SDL_SetRenderDrawColor(renderer, 0xFF, 0xFF, 0xFF, 0xFF);
temp.x = 1;
temp.y = 1;
temp.w = sprite_w;
temp.h = sprite_h;
SDL_RenderFillRect(renderer, &temp);
SDL_RenderCopy(renderer, sprite, NULL, &temp);
temp.x = viewport.w-sprite_w-1;
temp.y = 1;
temp.w = sprite_w;
temp.h = sprite_h;
SDL_RenderFillRect(renderer, &temp);
SDL_RenderCopy(renderer, sprite, NULL, &temp);
temp.x = 1;
temp.y = viewport.h-sprite_h-1;
temp.w = sprite_w;
temp.h = sprite_h;
SDL_RenderFillRect(renderer, &temp);
SDL_RenderCopy(renderer, sprite, NULL, &temp);
temp.x = viewport.w-sprite_w-1;
temp.y = viewport.h-sprite_h-1;
temp.w = sprite_w;
temp.h = sprite_h;
SDL_RenderFillRect(renderer, &temp);
SDL_RenderCopy(renderer, sprite, NULL, &temp);
/* Test diagonal lines */
SDL_SetRenderDrawColor(renderer, 0x00, 0xFF, 0x00, 0xFF);
SDL_RenderDrawLine(renderer, sprite_w, sprite_h,
viewport.w-sprite_w-2, viewport.h-sprite_h-2);
SDL_RenderDrawLine(renderer, viewport.w-sprite_w-2, sprite_h,
sprite_w, viewport.h-sprite_h-2);
/* Conditionally move the sprites, bounce at the wall */
if (iterations == -1 || iterations > 0) {
for (i = 0; i < num_sprites; ++i) {
position = &positions[i];
velocity = &velocities[i];
position->x += velocity->x;
if ((position->x < 0) || (position->x >= (viewport.w - sprite_w))) {
velocity->x = -velocity->x;
position->x += velocity->x;
}
position->y += velocity->y;
if ((position->y < 0) || (position->y >= (viewport.h - sprite_h))) {
velocity->y = -velocity->y;
position->y += velocity->y;
}
}
/* Countdown sprite-move iterations and disable color changes at iteration end - used for visual tests. */
if (iterations > 0) {
iterations--;
if (iterations == 0) {
cycle_alpha = SDL_FALSE;
cycle_color = SDL_FALSE;
}
}
}
/* Draw sprites */
for (i = 0; i < num_sprites; ++i) {
position = &positions[i];
/* Blit the sprite onto the screen */
SDL_RenderCopy(renderer, sprite, NULL, position);
}
/* Update the screen! */
SDL_RenderPresent(renderer);
}
void
loop()
{
int i;
SDL_Event event;
/* Check for events */
while (SDL_PollEvent(&event)) {
SDLTest_CommonEvent(state, &event, &done);
}
for (i = 0; i < state->num_windows; ++i) {
if (state->windows[i] == NULL)
continue;
MoveSprites(state->renderers[i], sprites[i]);
}
#ifdef __EMSCRIPTEN__
if (done) {
emscripten_cancel_main_loop();
}
#endif
}
int
main(int argc, char *argv[])
{
int i;
Uint32 then, now, frames;
Uint64 seed;
const char *icon = "icon.bmp";
/* Initialize parameters */
num_sprites = NUM_SPRITES;
/* Initialize test framework */
state = SDLTest_CommonCreateState(argv, SDL_INIT_VIDEO);
if (!state) {
return 1;
}
for (i = 1; i < argc;) {
int consumed;
consumed = SDLTest_CommonArg(state, i);
if (consumed == 0) {
consumed = -1;
if (SDL_strcasecmp(argv[i], "--blend") == 0) {
if (argv[i + 1]) {
if (SDL_strcasecmp(argv[i + 1], "none") == 0) {
blendMode = SDL_BLENDMODE_NONE;
consumed = 2;
} else if (SDL_strcasecmp(argv[i + 1], "blend") == 0) {
blendMode = SDL_BLENDMODE_BLEND;
consumed = 2;
} else if (SDL_strcasecmp(argv[i + 1], "add") == 0) {
blendMode = SDL_BLENDMODE_ADD;
consumed = 2;
} else if (SDL_strcasecmp(argv[i + 1], "mod") == 0) {
blendMode = SDL_BLENDMODE_MOD;
consumed = 2;
}
}
} else if (SDL_strcasecmp(argv[i], "--iterations") == 0) {
if (argv[i + 1]) {
iterations = SDL_atoi(argv[i + 1]);
if (iterations < -1) iterations = -1;
consumed = 2;
}
} else if (SDL_strcasecmp(argv[i], "--cyclecolor") == 0) {
cycle_color = SDL_TRUE;
consumed = 1;
} else if (SDL_strcasecmp(argv[i], "--cyclealpha") == 0) {
cycle_alpha = SDL_TRUE;
consumed = 1;
} else if (SDL_isdigit(*argv[i])) {
num_sprites = SDL_atoi(argv[i]);
consumed = 1;
} else if (argv[i][0] != '-') {
icon = argv[i];
consumed = 1;
}
}
if (consumed < 0) {
SDL_Log("Usage: %s %s [--blend none|blend|add|mod] [--cyclecolor] [--cyclealpha] [--iterations N] [num_sprites] [icon.bmp]\n",
argv[0], SDLTest_CommonUsage(state));
quit(1);
}
i += consumed;
}
if (!SDLTest_CommonInit(state)) {
quit(2);
}
/* Create the windows, initialize the renderers, and load the textures */
sprites =
(SDL_Texture **) SDL_malloc(state->num_windows * sizeof(*sprites));
if (!sprites) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Out of memory!\n");
quit(2);
}
for (i = 0; i < state->num_windows; ++i) {
SDL_Renderer *renderer = state->renderers[i];
SDL_SetRenderDrawColor(renderer, 0xA0, 0xA0, 0xA0, 0xFF);
SDL_RenderClear(renderer);
}
if (LoadSprite(icon) < 0) {
quit(2);
}
/* Allocate memory for the sprite info */
positions = (SDL_Rect *) SDL_malloc(num_sprites * sizeof(SDL_Rect));
velocities = (SDL_Rect *) SDL_malloc(num_sprites * sizeof(SDL_Rect));
if (!positions || !velocities) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Out of memory!\n");
quit(2);
}
/* Position sprites and set their velocities using the fuzzer */
if (iterations >= 0) {
/* Deterministic seed - used for visual tests */
seed = (Uint64)iterations;
} else {
/* Pseudo-random seed generated from the time */
seed = (Uint64)time(NULL);
}
SDLTest_FuzzerInit(seed);
for (i = 0; i < num_sprites; ++i) {
positions[i].x = SDLTest_RandomIntegerInRange(0, state->window_w - sprite_w);
positions[i].y = SDLTest_RandomIntegerInRange(0, state->window_h - sprite_h);
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) {
velocities[i].x = SDLTest_RandomIntegerInRange(-MAX_SPEED, MAX_SPEED);
velocities[i].y = SDLTest_RandomIntegerInRange(-MAX_SPEED, MAX_SPEED);
}
}
/* Main render loop */
frames = 0;
then = SDL_GetTicks();
done = 0;
#ifdef __EMSCRIPTEN__
emscripten_set_main_loop(loop, 0, 1);
#else
while (!done) {
++frames;
loop();
}
#endif
/* Print out some timing information */
now = SDL_GetTicks();
if (now > then) {
double fps = ((double) frames * 1000) / (now - then);
SDL_Log("%2.2f frames per second\n", fps);
}
quit(0);
return 0;
}
/* vi: set ts=4 sw=4 expandtab: */
SDL_test.h
SDL_RenderDrawPoint
#define SDL_RenderDrawPoint
Definition: SDL_dynapi_overrides.h:341
quit
static void quit(int rc)
Definition: testsprite2.c:49
SDL_PollEvent
#define SDL_PollEvent
Definition: SDL_dynapi_overrides.h:128
SDL_GetError
#define SDL_GetError
Definition: SDL_dynapi_overrides.h:119
sprites
static SDL_Texture ** sprites
Definition: testsprite2.c:30
Uint32
uint32_t Uint32
An unsigned 32-bit integer type.
Definition: SDL_stdinc.h:157
SDL_Surface::h
int h
Definition: SDL_surface.h:73
SDL_LoadBMP
#define SDL_LoadBMP(file)
Definition: SDL_surface.h:182
SDL_BLENDMODE_NONE
Definition: SDL_blendmode.h:42
SDLTest_RandomIntegerInRange
Sint32 SDLTest_RandomIntegerInRange(Sint32 min, Sint32 max)
Definition: SDL_test_fuzzer.c:156
x
GLint GLint GLint GLint GLint x
Definition: SDL_opengl.h:1567
velocities
static SDL_Rect * velocities
Definition: testsprite2.c:37
SDL_BlendMode
SDL_BlendMode
The blend mode used in SDL_RenderCopy() and drawing operations.
Definition: SDL_blendmode.h:40
SDLTest_CommonCreateState
SDLTest_CommonState * SDLTest_CommonCreateState(char **argv, Uint32 flags)
Parse command line parameters and create common state.
Definition: SDL_test_common.c:36
SDL_RenderFillRect
#define SDL_RenderFillRect
Definition: SDL_dynapi_overrides.h:347
NUM_SPRITES
#define NUM_SPRITES
Definition: testsprite2.c:25
SDLTest_CommonArg
int SDLTest_CommonArg(SDLTest_CommonState *state, int index)
Process one common argument.
Definition: SDL_test_common.c:83
SDLTest_CommonState::window_w
int window_w
Definition: SDL_test_common.h:66
SDL_Surface
A collection of pixels used in software blitting.
Definition: SDL_surface.h:69
cycle_color
static SDL_bool cycle_color
Definition: testsprite2.c:31
SDL_SetTextureBlendMode
#define SDL_SetTextureBlendMode
Definition: SDL_dynapi_overrides.h:319
SDL_Renderer
Definition: SDL_sysrender.h:76
sprite_h
static int sprite_h
Definition: testsprite2.c:38
iterations
static int iterations
Definition: testsprite2.c:43
state
static SDLTest_CommonState * state
Definition: testsprite2.c:28
done
int done
Definition: testsprite2.c:45
SDL_strcasecmp
#define SDL_strcasecmp
Definition: SDL_dynapi_overrides.h:425
SDL_Surface::w
int w
Definition: SDL_surface.h:73
SDL_test_common.h
SDLTest_CommonInit
SDL_bool SDLTest_CommonInit(SDLTest_CommonState *state)
Open test window.
Definition: SDL_test_common.c:645
Uint64
uint64_t Uint64
An unsigned 64-bit integer type.
Definition: SDL_stdinc.h:166
SDL_Texture
Definition: SDL_sysrender.h:49
SDL_BLENDMODE_MOD
Definition: SDL_blendmode.h:50
SDLTest_CommonState::windows
SDL_Window ** windows
Definition: SDL_test_common.h:78
num_sprites
static int num_sprites
Definition: testsprite2.c:29
MAX_SPEED
#define MAX_SPEED
Definition: testsprite2.c:26
SDL_LogError
#define SDL_LogError
Definition: SDL_dynapi_overrides.h:42
SDL_bool
SDL_bool
Definition: SDL_stdinc.h:126
SDLTest_CommonState::num_windows
int num_windows
Definition: SDL_test_common.h:77
SDL_RenderCopy
#define SDL_RenderCopy
Definition: SDL_dynapi_overrides.h:349
renderer
SDL_Renderer * renderer
Definition: testautomation_render.c:27
SDL_Log
#define SDL_Log
Definition: SDL_dynapi_overrides.h:37
SDL_CreateTextureFromSurface
#define SDL_CreateTextureFromSurface
Definition: SDL_dynapi_overrides.h:313
LoadSprite
int LoadSprite(const char *file)
Definition: testsprite2.c:59
SDLTest_CommonEvent
void SDLTest_CommonEvent(SDLTest_CommonState *state, SDL_Event *event, int *done)
Common event handler for test windows.
Definition: SDL_test_common.c:1295
y
GLint GLint GLint GLint GLint GLint y
Definition: SDL_opengl.h:1567
SDL_isdigit
#define SDL_isdigit
Definition: SDL_dynapi_overrides.h:388
SDL_GetTicks
Uint32 SDL_GetTicks(void)
Get the number of milliseconds since the SDL library initialization.
SDL_Surface::pixels
void * pixels
Definition: SDL_surface.h:75
SDL_FreeSurface
#define SDL_FreeSurface
Definition: SDL_dynapi_overrides.h:450
Uint8
uint8_t Uint8
An unsigned 8-bit integer type.
Definition: SDL_stdinc.h:139
event
struct _cl_event * event
Definition: SDL_opengl_glext.h:2649
SDL_PixelFormat::BitsPerPixel
Uint8 BitsPerPixel
Definition: SDL_pixels.h:303
SDL_free
void SDL_free(void *mem)
current_alpha
static int current_alpha
Definition: testsprite2.c:34
sprite_w
static int sprite_w
Definition: testsprite2.c:38
SDLTest_CommonState::window_h
int window_h
Definition: SDL_test_common.h:67
SDL_RenderGetViewport
#define SDL_RenderGetViewport
Definition: SDL_dynapi_overrides.h:331
SDL_SetColorKey
#define SDL_SetColorKey
Definition: SDL_dynapi_overrides.h:457
SDL_SetTextureColorMod
#define SDL_SetTextureColorMod
Definition: SDL_dynapi_overrides.h:315
SDL_Rect::x
int x
Definition: SDL_rect.h:66
SDL_TRUE
Definition: SDL_stdinc.h:129
SDLTest_CommonUsage
const char * SDLTest_CommonUsage(SDLTest_CommonState *state)
Returns common usage information.
Definition: SDL_test_common.c:451
SDL_Rect::w
int w
Definition: SDL_rect.h:67
SDL_atoi
#define SDL_atoi
Definition: SDL_dynapi_overrides.h:416
SDLTest_CommonState
Definition: SDL_test_common.h:51
cycle_alpha
static SDL_bool cycle_alpha
Definition: testsprite2.c:32
SDLTest_CommonState::renderers
SDL_Renderer ** renderers
Definition: SDL_test_common.h:84
i
return Display return Display Bool Bool int int int return Display XEvent Bool(*) XPointer return Display return Display Drawable _Xconst char unsigned int unsigned int return Display Pixmap Pixmap XColor XColor unsigned int unsigned int return Display _Xconst char char int char return Display Visual unsigned int int int char unsigned int unsigned int in i)
Definition: SDL_x11sym.h:42
NULL
#define NULL
Definition: begin_code.h:143
SDL_Surface::format
SDL_PixelFormat * format
Definition: SDL_surface.h:72
SDL_RenderClear
#define SDL_RenderClear
Definition: SDL_dynapi_overrides.h:340
SDL_Rect::h
int h
Definition: SDL_rect.h:67
sprite
static SDL_Texture * sprite
Definition: testspriteminimal.c:29
SDL_BLENDMODE_ADD
Definition: SDL_blendmode.h:47
viewport
SDL_Rect viewport
Definition: testviewport.c:28
SDL_FALSE
Definition: SDL_stdinc.h:128
positions
static SDL_Rect * positions
Definition: testsprite2.c:36
main
int main(int argc, char *argv[])
Definition: testsprite2.c:262
Uint16
uint16_t Uint16
An unsigned 16-bit integer type.
Definition: SDL_stdinc.h:147
SDL_Event
General event structure.
Definition: SDL_events.h:521
SDL_malloc
#define SDL_malloc
Definition: SDL_dynapi_overrides.h:380
SDL_SetRenderDrawColor
#define SDL_SetRenderDrawColor
Definition: SDL_dynapi_overrides.h:336
SDL_PixelFormat::palette
SDL_Palette * palette
Definition: SDL_pixels.h:302
cycle_direction
static int cycle_direction
Definition: testsprite2.c:33
SDLTest_FuzzerInit
void SDLTest_FuzzerInit(Uint64 execKey)
Definition: SDL_test_fuzzer.c:62
MoveSprites
void MoveSprites(SDL_Renderer *renderer, SDL_Texture *sprite)
Definition: testsprite2.c:111
blendMode
static SDL_BlendMode blendMode
Definition: testsprite2.c:39
current_color
static int current_color
Definition: testsprite2.c:35
loop
void loop()
Definition: testsprite2.c:240
SDL_RenderDrawLine
#define SDL_RenderDrawLine
Definition: SDL_dynapi_overrides.h:343
SDL_LOG_CATEGORY_APPLICATION
Definition: SDL_log.h:66
SDL_Rect::y
int y
Definition: SDL_rect.h:66
SDLTest_CommonQuit
void SDLTest_CommonQuit(SDLTest_CommonState *state)
Close test window.
Definition: SDL_test_common.c:1560
SDL_INIT_VIDEO
#define SDL_INIT_VIDEO
Definition: SDL.h:77
SDL_Rect
A rectangle, with the origin at the upper left.
Definition: SDL_rect.h:64
SDL_RenderPresent
#define SDL_RenderPresent
Definition: SDL_dynapi_overrides.h:352
SDL_SetTextureAlphaMod
#define SDL_SetTextureAlphaMod
Definition: SDL_dynapi_overrides.h:317
SDL_BLENDMODE_BLEND
Definition: SDL_blendmode.h:44