test/testsprite2.c
author Sam Lantinga <slouken@libsdl.org>
Sat, 20 Dec 2008 12:00:00 +0000
changeset 2884 9dde605c7540
parent 2834 feb6ccdb888f
child 3183 d1436442215f
permissions -rw-r--r--
Date: Fri, 19 Dec 2008 20:17:35 +0100
From: Couriersud
Subject: Re: Aw: Experience using SDL1.3 in sdlmame/Proposal for api additions

> For consistency you'd probably want:
> SDL_SetRenderDrawColor(Uint8 r, Uint8 g, Uint8 b, Uint8 a);
> SDL_SetRenderDrawBlendMode(SDL_BlendMode blendMode);
> SDL_RenderLine(int x1, int y1, int x2, int y2);
> SDL_RenderFill(SDL_Rect *rect);
>
> You probably also want to add API functions query the current state.
>

I have implemented the above api for the opengl, x11, directfb and
software renderers. I have also renamed *TEXTUREBLENDMODE* constants to
BLENDMODE*. The unix build compiles. The windows renderer still needs to
be updated, but I have no windows development machine at hand. Have a
look at the x11 renderer for a sample.

Vector games now run at 90% both on opengl and directfb in comparison to
sdlmame's own opengl renderer. The same applies to raster games.

The diff also includes

a) Changed XDrawRect to XFillRect in x11 renderer
b) A number of changes to fix blending and modulation issues in the
directfb renderer.
slouken@1895
     1
/* Simple program:  Move N sprites around on the screen as fast as possible */
slouken@1895
     2
slouken@1895
     3
#include <stdlib.h>
slouken@1907
     4
#include <stdio.h>
slouken@1895
     5
#include <time.h>
slouken@1895
     6
slouken@1914
     7
#include "common.h"
slouken@1895
     8
slouken@1895
     9
#define NUM_SPRITES	100
slouken@1895
    10
#define MAX_SPEED 	1
slouken@1895
    11
slouken@1914
    12
static CommonState *state;
slouken@1895
    13
static int num_sprites;
slouken@1895
    14
static SDL_TextureID *sprites;
slouken@1985
    15
static SDL_bool cycle_color;
slouken@1985
    16
static SDL_bool cycle_alpha;
slouken@1985
    17
static int cycle_direction = 1;
slouken@1985
    18
static int current_alpha = 0;
slouken@1985
    19
static int current_color = 0;
slouken@1895
    20
static SDL_Rect *positions;
slouken@1895
    21
static SDL_Rect *velocities;
slouken@1895
    22
static int sprite_w, sprite_h;
slouken@2884
    23
static SDL_BlendMode blendMode = SDL_BLENDMODE_MASK;
slouken@1965
    24
static SDL_TextureScaleMode scaleMode = SDL_TEXTURESCALEMODE_NONE;
slouken@1895
    25
slouken@1895
    26
/* Call this instead of exit(), so we can clean up SDL: atexit() is evil. */
slouken@1895
    27
static void
slouken@1895
    28
quit(int rc)
slouken@1895
    29
{
slouken@1895
    30
    if (sprites) {
slouken@1895
    31
        SDL_free(sprites);
slouken@1895
    32
    }
slouken@1895
    33
    if (positions) {
slouken@1895
    34
        SDL_free(positions);
slouken@1895
    35
    }
slouken@1895
    36
    if (velocities) {
slouken@1895
    37
        SDL_free(velocities);
slouken@1895
    38
    }
slouken@1914
    39
    CommonQuit(state);
slouken@1895
    40
    exit(rc);
slouken@1895
    41
}
slouken@1895
    42
slouken@1895
    43
int
slouken@1895
    44
LoadSprite(char *file)
slouken@1895
    45
{
slouken@1895
    46
    int i;
slouken@1895
    47
    SDL_Surface *temp;
slouken@1895
    48
slouken@1895
    49
    /* Load the sprite image */
slouken@1895
    50
    temp = SDL_LoadBMP(file);
slouken@1895
    51
    if (temp == NULL) {
slouken@1895
    52
        fprintf(stderr, "Couldn't load %s: %s", file, SDL_GetError());
slouken@1895
    53
        return (-1);
slouken@1895
    54
    }
slouken@1895
    55
    sprite_w = temp->w;
slouken@1895
    56
    sprite_h = temp->h;
slouken@1895
    57
slouken@1895
    58
    /* Set transparent pixel as the pixel at (0,0) */
slouken@1895
    59
    if (temp->format->palette) {
slouken@1895
    60
        SDL_SetColorKey(temp, SDL_SRCCOLORKEY, *(Uint8 *) temp->pixels);
slouken@1895
    61
    }
slouken@1895
    62
slouken@1895
    63
    /* Create textures from the image */
slouken@1914
    64
    for (i = 0; i < state->num_windows; ++i) {
slouken@1914
    65
        SDL_SelectRenderer(state->windows[i]);
slouken@2222
    66
        sprites[i] = SDL_CreateTextureFromSurface(0, temp);
slouken@1895
    67
        if (!sprites[i]) {
slouken@1895
    68
            fprintf(stderr, "Couldn't create texture: %s\n", SDL_GetError());
slouken@1895
    69
            SDL_FreeSurface(temp);
slouken@1895
    70
            return (-1);
slouken@1895
    71
        }
slouken@1985
    72
        SDL_SetTextureBlendMode(sprites[i], blendMode);
slouken@1985
    73
        SDL_SetTextureScaleMode(sprites[i], scaleMode);
slouken@1895
    74
    }
slouken@1895
    75
    SDL_FreeSurface(temp);
slouken@1895
    76
slouken@1895
    77
    /* We're ready to roll. :) */
slouken@1895
    78
    return (0);
slouken@1895
    79
}
slouken@1895
    80
slouken@1895
    81
void
slouken@1895
    82
MoveSprites(SDL_WindowID window, SDL_TextureID sprite)
slouken@1895
    83
{
slouken@1895
    84
    int i, n;
slouken@1895
    85
    int window_w, window_h;
slouken@2783
    86
    SDL_Rect *position, *velocity;
slouken@1895
    87
slouken@1895
    88
    SDL_SelectRenderer(window);
slouken@1895
    89
slouken@1895
    90
    /* Query the sizes */
slouken@1895
    91
    SDL_GetWindowSize(window, &window_w, &window_h);
slouken@1895
    92
slouken@1985
    93
    /* Cycle the color and alpha, if desired */
slouken@1985
    94
    if (cycle_color) {
slouken@1985
    95
        current_color += cycle_direction;
slouken@1985
    96
        if (current_color < 0) {
slouken@1985
    97
            current_color = 0;
slouken@1985
    98
            cycle_direction = -cycle_direction;
slouken@1985
    99
        }
slouken@1985
   100
        if (current_color > 255) {
slouken@1985
   101
            current_color = 255;
slouken@1985
   102
            cycle_direction = -cycle_direction;
slouken@1985
   103
        }
slouken@1985
   104
        SDL_SetTextureColorMod(sprite, 255, (Uint8) current_color,
slouken@1985
   105
                               (Uint8) current_color);
slouken@1985
   106
    }
slouken@1985
   107
    if (cycle_alpha) {
slouken@1985
   108
        current_alpha += cycle_direction;
slouken@1985
   109
        if (current_alpha < 0) {
slouken@1985
   110
            current_alpha = 0;
slouken@1985
   111
            cycle_direction = -cycle_direction;
slouken@1985
   112
        }
slouken@1985
   113
        if (current_alpha > 255) {
slouken@1985
   114
            current_alpha = 255;
slouken@1985
   115
            cycle_direction = -cycle_direction;
slouken@1985
   116
        }
slouken@1985
   117
        SDL_SetTextureAlphaMod(sprite, (Uint8) current_alpha);
slouken@1985
   118
    }
slouken@1985
   119
slouken@1895
   120
    /* Move the sprite, bounce at the wall, and draw */
slouken@1895
   121
    n = 0;
slouken@2884
   122
    SDL_SetRenderDrawColor(0xA0, 0xA0, 0xA0, 0xFF);
slouken@2884
   123
    SDL_RenderFill(NULL);
slouken@1895
   124
    for (i = 0; i < num_sprites; ++i) {
slouken@1895
   125
        position = &positions[i];
slouken@1895
   126
        velocity = &velocities[i];
slouken@1895
   127
        position->x += velocity->x;
slouken@1895
   128
        if ((position->x < 0) || (position->x >= (window_w - sprite_w))) {
slouken@1895
   129
            velocity->x = -velocity->x;
slouken@1895
   130
            position->x += velocity->x;
slouken@1895
   131
        }
slouken@1895
   132
        position->y += velocity->y;
slouken@2834
   133
        if ((position->y < 0) || (position->y >= (window_h - sprite_h))) {
slouken@1895
   134
            velocity->y = -velocity->y;
slouken@1895
   135
            position->y += velocity->y;
slouken@1895
   136
        }
slouken@1895
   137
slouken@1895
   138
        /* Blit the sprite onto the screen */
slouken@1985
   139
        SDL_RenderCopy(sprite, NULL, position);
slouken@1895
   140
    }
slouken@1895
   141
slouken@1895
   142
    /* Update the screen! */
slouken@1895
   143
    SDL_RenderPresent();
slouken@1895
   144
}
slouken@1895
   145
slouken@1895
   146
int
slouken@1895
   147
main(int argc, char *argv[])
slouken@1895
   148
{
slouken@1895
   149
    int i, done;
slouken@1895
   150
    SDL_Event event;
slouken@1895
   151
    Uint32 then, now, frames;
slouken@1895
   152
slouken@1914
   153
    /* Initialize parameters */
slouken@1914
   154
    num_sprites = NUM_SPRITES;
slouken@1914
   155
slouken@1914
   156
    /* Initialize test framework */
slouken@1914
   157
    state = CommonCreateState(argv, SDL_INIT_VIDEO);
slouken@1914
   158
    if (!state) {
slouken@1914
   159
        return 1;
slouken@1895
   160
    }
slouken@1914
   161
    for (i = 1; i < argc;) {
slouken@1914
   162
        int consumed;
slouken@1895
   163
slouken@1914
   164
        consumed = CommonArg(state, i);
slouken@1915
   165
        if (consumed == 0) {
slouken@1916
   166
            consumed = -1;
slouken@1916
   167
            if (SDL_strcasecmp(argv[i], "--blend") == 0) {
slouken@1916
   168
                if (argv[i + 1]) {
slouken@1916
   169
                    if (SDL_strcasecmp(argv[i + 1], "none") == 0) {
slouken@2884
   170
                        blendMode = SDL_BLENDMODE_NONE;
slouken@1916
   171
                        consumed = 2;
slouken@1917
   172
                    } else if (SDL_strcasecmp(argv[i + 1], "mask") == 0) {
slouken@2884
   173
                        blendMode = SDL_BLENDMODE_MASK;
slouken@1917
   174
                        consumed = 2;
slouken@1916
   175
                    } else if (SDL_strcasecmp(argv[i + 1], "blend") == 0) {
slouken@2884
   176
                        blendMode = SDL_BLENDMODE_BLEND;
slouken@1916
   177
                        consumed = 2;
slouken@1916
   178
                    } else if (SDL_strcasecmp(argv[i + 1], "add") == 0) {
slouken@2884
   179
                        blendMode = SDL_BLENDMODE_ADD;
slouken@1916
   180
                        consumed = 2;
slouken@1916
   181
                    } else if (SDL_strcasecmp(argv[i + 1], "mod") == 0) {
slouken@2884
   182
                        blendMode = SDL_BLENDMODE_MOD;
slouken@1916
   183
                        consumed = 2;
slouken@1916
   184
                    }
slouken@1916
   185
                }
slouken@1917
   186
            } else if (SDL_strcasecmp(argv[i], "--scale") == 0) {
slouken@1917
   187
                if (argv[i + 1]) {
slouken@1917
   188
                    if (SDL_strcasecmp(argv[i + 1], "none") == 0) {
slouken@1965
   189
                        scaleMode = SDL_TEXTURESCALEMODE_NONE;
slouken@1917
   190
                        consumed = 2;
slouken@1917
   191
                    } else if (SDL_strcasecmp(argv[i + 1], "fast") == 0) {
slouken@1965
   192
                        scaleMode = SDL_TEXTURESCALEMODE_FAST;
slouken@1917
   193
                        consumed = 2;
slouken@1917
   194
                    } else if (SDL_strcasecmp(argv[i + 1], "slow") == 0) {
slouken@1965
   195
                        scaleMode = SDL_TEXTURESCALEMODE_SLOW;
slouken@1917
   196
                        consumed = 2;
slouken@1917
   197
                    } else if (SDL_strcasecmp(argv[i + 1], "best") == 0) {
slouken@1965
   198
                        scaleMode = SDL_TEXTURESCALEMODE_BEST;
slouken@1917
   199
                        consumed = 2;
slouken@1917
   200
                    }
slouken@1917
   201
                }
slouken@1985
   202
            } else if (SDL_strcasecmp(argv[i], "--cyclecolor") == 0) {
slouken@1985
   203
                cycle_color = SDL_TRUE;
slouken@1985
   204
                consumed = 1;
slouken@1985
   205
            } else if (SDL_strcasecmp(argv[i], "--cyclealpha") == 0) {
slouken@1985
   206
                cycle_alpha = SDL_TRUE;
slouken@1985
   207
                consumed = 1;
slouken@1916
   208
            } else if (SDL_isdigit(*argv[i])) {
slouken@1916
   209
                num_sprites = SDL_atoi(argv[i]);
slouken@1916
   210
                consumed = 1;
slouken@1916
   211
            }
slouken@1915
   212
        }
slouken@1914
   213
        if (consumed < 0) {
slouken@1917
   214
            fprintf(stderr,
slouken@1985
   215
                    "Usage: %s %s [--blend none|mask|blend|add|mod] [--scale none|fast|slow|best] [--cyclecolor] [--cyclealpha]\n",
slouken@1916
   216
                    argv[0], CommonUsage(state));
slouken@1895
   217
            quit(1);
slouken@1895
   218
        }
slouken@1914
   219
        i += consumed;
slouken@1895
   220
    }
slouken@1914
   221
    if (!CommonInit(state)) {
slouken@1914
   222
        quit(2);
slouken@1895
   223
    }
slouken@1895
   224
slouken@1895
   225
    /* Create the windows, initialize the renderers, and load the textures */
slouken@1914
   226
    sprites =
slouken@1914
   227
        (SDL_TextureID *) SDL_malloc(state->num_windows * sizeof(*sprites));
slouken@1914
   228
    if (!sprites) {
slouken@1895
   229
        fprintf(stderr, "Out of memory!\n");
slouken@1895
   230
        quit(2);
slouken@1895
   231
    }
slouken@1914
   232
    for (i = 0; i < state->num_windows; ++i) {
slouken@1914
   233
        SDL_SelectRenderer(state->windows[i]);
slouken@2884
   234
        SDL_SetRenderDrawColor(0xA0, 0xA0, 0xA0, 0xFF);
slouken@2884
   235
        SDL_RenderFill(NULL);
slouken@1895
   236
    }
slouken@1895
   237
    if (LoadSprite("icon.bmp") < 0) {
slouken@1895
   238
        quit(2);
slouken@1895
   239
    }
slouken@1895
   240
slouken@1895
   241
    /* Allocate memory for the sprite info */
slouken@1895
   242
    positions = (SDL_Rect *) SDL_malloc(num_sprites * sizeof(SDL_Rect));
slouken@1895
   243
    velocities = (SDL_Rect *) SDL_malloc(num_sprites * sizeof(SDL_Rect));
slouken@1895
   244
    if (!positions || !velocities) {
slouken@1895
   245
        fprintf(stderr, "Out of memory!\n");
slouken@1895
   246
        quit(2);
slouken@1895
   247
    }
slouken@1895
   248
    srand(time(NULL));
slouken@1965
   249
    if (scaleMode != SDL_TEXTURESCALEMODE_NONE) {
slouken@1917
   250
        sprite_w += sprite_w / 2;
slouken@1917
   251
        sprite_h += sprite_h / 2;
slouken@1917
   252
    }
slouken@1895
   253
    for (i = 0; i < num_sprites; ++i) {
slouken@1914
   254
        positions[i].x = rand() % (state->window_w - sprite_w);
slouken@1914
   255
        positions[i].y = rand() % (state->window_h - sprite_h);
slouken@1895
   256
        positions[i].w = sprite_w;
slouken@1895
   257
        positions[i].h = sprite_h;
slouken@1895
   258
        velocities[i].x = 0;
slouken@1895
   259
        velocities[i].y = 0;
slouken@1895
   260
        while (!velocities[i].x && !velocities[i].y) {
slouken@1895
   261
            velocities[i].x = (rand() % (MAX_SPEED * 2 + 1)) - MAX_SPEED;
slouken@1895
   262
            velocities[i].y = (rand() % (MAX_SPEED * 2 + 1)) - MAX_SPEED;
slouken@1895
   263
        }
slouken@1895
   264
    }
slouken@1895
   265
slouken@1915
   266
    /* Main render loop */
slouken@1895
   267
    frames = 0;
slouken@1895
   268
    then = SDL_GetTicks();
slouken@1895
   269
    done = 0;
slouken@1895
   270
    while (!done) {
slouken@1895
   271
        /* Check for events */
slouken@1895
   272
        ++frames;
slouken@1895
   273
        while (SDL_PollEvent(&event)) {
slouken@1914
   274
            CommonEvent(state, &event, &done);
slouken@1895
   275
            switch (event.type) {
slouken@1895
   276
            case SDL_WINDOWEVENT:
slouken@1895
   277
                switch (event.window.event) {
slouken@1895
   278
                case SDL_WINDOWEVENT_EXPOSED:
slouken@1895
   279
                    SDL_SelectRenderer(event.window.windowID);
slouken@2884
   280
                    SDL_SetRenderDrawColor(0xA0, 0xA0, 0xA0, 0xFF);
slouken@2884
   281
                    SDL_RenderFill(NULL);
slouken@1895
   282
                    break;
slouken@1895
   283
                }
slouken@1895
   284
                break;
slouken@1895
   285
            default:
slouken@1895
   286
                break;
slouken@1895
   287
            }
slouken@1895
   288
        }
slouken@1914
   289
        for (i = 0; i < state->num_windows; ++i) {
slouken@1914
   290
            MoveSprites(state->windows[i], sprites[i]);
slouken@1895
   291
        }
slouken@1895
   292
    }
slouken@1895
   293
slouken@1895
   294
    /* Print out some timing information */
slouken@1895
   295
    now = SDL_GetTicks();
slouken@1895
   296
    if (now > then) {
slouken@2786
   297
        double fps = ((double) frames * 1000) / (now - then);
slouken@2783
   298
        printf("%2.2f frames per second\n", fps);
slouken@1895
   299
    }
slouken@1895
   300
    quit(0);
slouken@1895
   301
}
slouken@1895
   302
slouken@1895
   303
/* vi: set ts=4 sw=4 expandtab: */