test/testsprite2.c
author Sam Lantinga <slouken@libsdl.org>
Thu, 07 Dec 2017 16:08:09 -0800
changeset 11730 ac6c607e065c
parent 11282 180e8906dc3c
child 11811 5d94cb6b24d3
permissions -rw-r--r--
Enable building the Metal renderer by default, and weak link the Metal framework so the SDL library is safe to use on older Macs
Also generate iOS versions of the Metal shaders
slouken@5535
     1
/*
slouken@10737
     2
  Copyright (C) 1997-2017 Sam Lantinga <slouken@libsdl.org>
slouken@5535
     3
slouken@5535
     4
  This software is provided 'as-is', without any express or implied
slouken@5535
     5
  warranty.  In no event will the authors be held liable for any damages
slouken@5535
     6
  arising from the use of this software.
slouken@5535
     7
slouken@5535
     8
  Permission is granted to anyone to use this software for any purpose,
slouken@5535
     9
  including commercial applications, and to alter it and redistribute it
slouken@5535
    10
  freely.
slouken@5535
    11
*/
slouken@1895
    12
/* Simple program:  Move N sprites around on the screen as fast as possible */
slouken@1895
    13
slouken@1895
    14
#include <stdlib.h>
slouken@1907
    15
#include <stdio.h>
slouken@1895
    16
#include <time.h>
slouken@1895
    17
icculus@9278
    18
#ifdef __EMSCRIPTEN__
icculus@9278
    19
#include <emscripten/emscripten.h>
icculus@9278
    20
#endif
icculus@9278
    21
aschiffler@7315
    22
#include "SDL_test.h"
slouken@6785
    23
#include "SDL_test_common.h"
slouken@1895
    24
slouken@5147
    25
#define NUM_SPRITES    100
slouken@5147
    26
#define MAX_SPEED     1
slouken@1895
    27
slouken@6785
    28
static SDLTest_CommonState *state;
slouken@1895
    29
static int num_sprites;
slouken@3685
    30
static SDL_Texture **sprites;
slouken@1985
    31
static SDL_bool cycle_color;
slouken@1985
    32
static SDL_bool cycle_alpha;
slouken@1985
    33
static int cycle_direction = 1;
slouken@1985
    34
static int current_alpha = 0;
slouken@1985
    35
static int current_color = 0;
slouken@1895
    36
static SDL_Rect *positions;
slouken@1895
    37
static SDL_Rect *velocities;
slouken@1895
    38
static int sprite_w, sprite_h;
slouken@5140
    39
static SDL_BlendMode blendMode = SDL_BLENDMODE_BLEND;
slouken@1895
    40
aschiffler@7315
    41
/* Number of iterations to move sprites - used for visual tests. */
aschiffler@7315
    42
/* -1: infinite random moves (default); >=0: enables N deterministic moves */
aschiffler@7315
    43
static int iterations = -1;
aschiffler@7315
    44
icculus@9278
    45
int done;
icculus@9278
    46
slouken@1895
    47
/* Call this instead of exit(), so we can clean up SDL: atexit() is evil. */
slouken@1895
    48
static void
slouken@1895
    49
quit(int rc)
slouken@1895
    50
{
slouken@7719
    51
    SDL_free(sprites);
slouken@7719
    52
    SDL_free(positions);
slouken@7719
    53
    SDL_free(velocities);
slouken@6785
    54
    SDLTest_CommonQuit(state);
slouken@1895
    55
    exit(rc);
slouken@1895
    56
}
slouken@1895
    57
slouken@1895
    58
int
slouken@7502
    59
LoadSprite(const char *file)
slouken@1895
    60
{
slouken@1895
    61
    int i;
slouken@1895
    62
    SDL_Surface *temp;
slouken@1895
    63
slouken@1895
    64
    /* Load the sprite image */
slouken@1895
    65
    temp = SDL_LoadBMP(file);
slouken@1895
    66
    if (temp == NULL) {
aschiffler@7639
    67
        SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't load %s: %s", file, SDL_GetError());
slouken@1895
    68
        return (-1);
slouken@1895
    69
    }
slouken@1895
    70
    sprite_w = temp->w;
slouken@1895
    71
    sprite_h = temp->h;
slouken@1895
    72
slouken@1895
    73
    /* Set transparent pixel as the pixel at (0,0) */
slouken@1895
    74
    if (temp->format->palette) {
slouken@3560
    75
        SDL_SetColorKey(temp, 1, *(Uint8 *) temp->pixels);
lestat@3183
    76
    } else {
lestat@3183
    77
        switch (temp->format->BitsPerPixel) {
lestat@3183
    78
        case 15:
slouken@3560
    79
            SDL_SetColorKey(temp, 1, (*(Uint16 *) temp->pixels) & 0x00007FFF);
lestat@3183
    80
            break;
lestat@3183
    81
        case 16:
slouken@3560
    82
            SDL_SetColorKey(temp, 1, *(Uint16 *) temp->pixels);
lestat@3183
    83
            break;
lestat@3183
    84
        case 24:
slouken@3560
    85
            SDL_SetColorKey(temp, 1, (*(Uint32 *) temp->pixels) & 0x00FFFFFF);
lestat@3183
    86
            break;
lestat@3183
    87
        case 32:
slouken@3560
    88
            SDL_SetColorKey(temp, 1, *(Uint32 *) temp->pixels);
lestat@3183
    89
            break;
lestat@3183
    90
        }
slouken@1895
    91
    }
slouken@1895
    92
slouken@1895
    93
    /* Create textures from the image */
slouken@1914
    94
    for (i = 0; i < state->num_windows; ++i) {
slouken@5147
    95
        SDL_Renderer *renderer = state->renderers[i];
slouken@5158
    96
        sprites[i] = SDL_CreateTextureFromSurface(renderer, temp);
slouken@3285
    97
        if (!sprites[i]) {
aschiffler@7639
    98
            SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't create texture: %s\n", SDL_GetError());
slouken@1895
    99
            SDL_FreeSurface(temp);
slouken@1895
   100
            return (-1);
slouken@1895
   101
        }
slouken@11282
   102
        if (SDL_SetTextureBlendMode(sprites[i], blendMode) < 0) {
slouken@11282
   103
            SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't set blend mode: %s\n", SDL_GetError());
slouken@11282
   104
            SDL_FreeSurface(temp);
slouken@11282
   105
            SDL_DestroyTexture(sprites[i]);
slouken@11282
   106
            return (-1);
slouken@11282
   107
        }
slouken@1895
   108
    }
slouken@1895
   109
    SDL_FreeSurface(temp);
slouken@1895
   110
slouken@1895
   111
    /* We're ready to roll. :) */
slouken@1895
   112
    return (0);
slouken@1895
   113
}
slouken@1895
   114
slouken@1895
   115
void
slouken@5297
   116
MoveSprites(SDL_Renderer * renderer, SDL_Texture * sprite)
slouken@1895
   117
{
aschiffler@7315
   118
    int i;
slouken@5297
   119
    SDL_Rect viewport, temp;
slouken@2783
   120
    SDL_Rect *position, *velocity;
slouken@1895
   121
slouken@1895
   122
    /* Query the sizes */
slouken@5297
   123
    SDL_RenderGetViewport(renderer, &viewport);
slouken@1895
   124
slouken@1985
   125
    /* Cycle the color and alpha, if desired */
slouken@1985
   126
    if (cycle_color) {
slouken@1985
   127
        current_color += cycle_direction;
slouken@1985
   128
        if (current_color < 0) {
slouken@1985
   129
            current_color = 0;
slouken@1985
   130
            cycle_direction = -cycle_direction;
slouken@1985
   131
        }
slouken@1985
   132
        if (current_color > 255) {
slouken@1985
   133
            current_color = 255;
slouken@1985
   134
            cycle_direction = -cycle_direction;
slouken@1985
   135
        }
slouken@1985
   136
        SDL_SetTextureColorMod(sprite, 255, (Uint8) current_color,
slouken@1985
   137
                               (Uint8) current_color);
slouken@1985
   138
    }
slouken@1985
   139
    if (cycle_alpha) {
slouken@1985
   140
        current_alpha += cycle_direction;
slouken@1985
   141
        if (current_alpha < 0) {
slouken@1985
   142
            current_alpha = 0;
slouken@1985
   143
            cycle_direction = -cycle_direction;
slouken@1985
   144
        }
slouken@1985
   145
        if (current_alpha > 255) {
slouken@1985
   146
            current_alpha = 255;
slouken@1985
   147
            cycle_direction = -cycle_direction;
slouken@1985
   148
        }
slouken@1985
   149
        SDL_SetTextureAlphaMod(sprite, (Uint8) current_alpha);
slouken@1985
   150
    }
slouken@1985
   151
slouken@3264
   152
    /* Draw a gray background */
slouken@5147
   153
    SDL_SetRenderDrawColor(renderer, 0xA0, 0xA0, 0xA0, 0xFF);
slouken@5147
   154
    SDL_RenderClear(renderer);
slouken@3264
   155
slouken@3265
   156
    /* Test points */
slouken@5147
   157
    SDL_SetRenderDrawColor(renderer, 0xFF, 0x00, 0x00, 0xFF);
slouken@5147
   158
    SDL_RenderDrawPoint(renderer, 0, 0);
slouken@5297
   159
    SDL_RenderDrawPoint(renderer, viewport.w-1, 0);
slouken@5297
   160
    SDL_RenderDrawPoint(renderer, 0, viewport.h-1);
slouken@5297
   161
    SDL_RenderDrawPoint(renderer, viewport.w-1, viewport.h-1);
slouken@3264
   162
slouken@3265
   163
    /* Test horizontal and vertical lines */
slouken@5147
   164
    SDL_SetRenderDrawColor(renderer, 0x00, 0xFF, 0x00, 0xFF);
slouken@5297
   165
    SDL_RenderDrawLine(renderer, 1, 0, viewport.w-2, 0);
slouken@5297
   166
    SDL_RenderDrawLine(renderer, 1, viewport.h-1, viewport.w-2, viewport.h-1);
slouken@5297
   167
    SDL_RenderDrawLine(renderer, 0, 1, 0, viewport.h-2);
slouken@5297
   168
    SDL_RenderDrawLine(renderer, viewport.w-1, 1, viewport.w-1, viewport.h-2);
slouken@3265
   169
slouken@3266
   170
    /* Test fill and copy */
slouken@5147
   171
    SDL_SetRenderDrawColor(renderer, 0xFF, 0xFF, 0xFF, 0xFF);
slouken@3266
   172
    temp.x = 1;
slouken@3266
   173
    temp.y = 1;
slouken@3266
   174
    temp.w = sprite_w;
slouken@3266
   175
    temp.h = sprite_h;
slouken@5147
   176
    SDL_RenderFillRect(renderer, &temp);
slouken@5147
   177
    SDL_RenderCopy(renderer, sprite, NULL, &temp);
slouken@5297
   178
    temp.x = viewport.w-sprite_w-1;
slouken@3265
   179
    temp.y = 1;
slouken@3265
   180
    temp.w = sprite_w;
slouken@3265
   181
    temp.h = sprite_h;
slouken@5147
   182
    SDL_RenderFillRect(renderer, &temp);
slouken@5147
   183
    SDL_RenderCopy(renderer, sprite, NULL, &temp);
slouken@3265
   184
    temp.x = 1;
slouken@5297
   185
    temp.y = viewport.h-sprite_h-1;
slouken@3265
   186
    temp.w = sprite_w;
slouken@3265
   187
    temp.h = sprite_h;
slouken@5147
   188
    SDL_RenderFillRect(renderer, &temp);
slouken@5147
   189
    SDL_RenderCopy(renderer, sprite, NULL, &temp);
slouken@5297
   190
    temp.x = viewport.w-sprite_w-1;
slouken@5297
   191
    temp.y = viewport.h-sprite_h-1;
slouken@3265
   192
    temp.w = sprite_w;
slouken@3265
   193
    temp.h = sprite_h;
slouken@5147
   194
    SDL_RenderFillRect(renderer, &temp);
slouken@5147
   195
    SDL_RenderCopy(renderer, sprite, NULL, &temp);
slouken@3265
   196
slouken@3265
   197
    /* Test diagonal lines */
slouken@5147
   198
    SDL_SetRenderDrawColor(renderer, 0x00, 0xFF, 0x00, 0xFF);
slouken@5147
   199
    SDL_RenderDrawLine(renderer, sprite_w, sprite_h,
slouken@5297
   200
                       viewport.w-sprite_w-2, viewport.h-sprite_h-2);
slouken@5297
   201
    SDL_RenderDrawLine(renderer, viewport.w-sprite_w-2, sprite_h,
slouken@5297
   202
                       sprite_w, viewport.h-sprite_h-2);
slouken@3265
   203
aschiffler@7315
   204
    /* Conditionally move the sprites, bounce at the wall */
aschiffler@7315
   205
    if (iterations == -1 || iterations > 0) {
aschiffler@7315
   206
        for (i = 0; i < num_sprites; ++i) {
aschiffler@7315
   207
            position = &positions[i];
aschiffler@7315
   208
            velocity = &velocities[i];
aschiffler@7315
   209
            position->x += velocity->x;
aschiffler@7315
   210
            if ((position->x < 0) || (position->x >= (viewport.w - sprite_w))) {
philipp@9922
   211
                velocity->x = -velocity->x;
philipp@9922
   212
                position->x += velocity->x;
aschiffler@7315
   213
            }
aschiffler@7315
   214
            position->y += velocity->y;
aschiffler@7315
   215
            if ((position->y < 0) || (position->y >= (viewport.h - sprite_h))) {
philipp@9922
   216
                velocity->y = -velocity->y;
philipp@9922
   217
                position->y += velocity->y;
aschiffler@7315
   218
            }
aschiffler@7315
   219
aschiffler@7315
   220
        }
aschiffler@7315
   221
        
aschiffler@7315
   222
        /* Countdown sprite-move iterations and disable color changes at iteration end - used for visual tests. */
aschiffler@7315
   223
        if (iterations > 0) {
aschiffler@7315
   224
            iterations--;
aschiffler@7315
   225
            if (iterations == 0) {
aschiffler@7315
   226
                cycle_alpha = SDL_FALSE;
aschiffler@7315
   227
                cycle_color = SDL_FALSE;
aschiffler@7315
   228
            }
aschiffler@7315
   229
        }
aschiffler@7315
   230
    }
aschiffler@7315
   231
aschiffler@7315
   232
    /* Draw sprites */
slouken@1895
   233
    for (i = 0; i < num_sprites; ++i) {
slouken@1895
   234
        position = &positions[i];
philipp@9922
   235
slouken@1895
   236
        /* Blit the sprite onto the screen */
slouken@5147
   237
        SDL_RenderCopy(renderer, sprite, NULL, position);
slouken@1895
   238
    }
slouken@1895
   239
slouken@1895
   240
    /* Update the screen! */
slouken@5147
   241
    SDL_RenderPresent(renderer);
slouken@1895
   242
}
slouken@1895
   243
icculus@9278
   244
void
icculus@9278
   245
loop()
icculus@9278
   246
{
icculus@9278
   247
    int i;
icculus@9278
   248
    SDL_Event event;
icculus@9278
   249
icculus@9278
   250
    /* Check for events */
icculus@9278
   251
    while (SDL_PollEvent(&event)) {
icculus@9278
   252
        SDLTest_CommonEvent(state, &event, &done);
icculus@9278
   253
    }
icculus@9278
   254
    for (i = 0; i < state->num_windows; ++i) {
icculus@9278
   255
        if (state->windows[i] == NULL)
icculus@9278
   256
            continue;
icculus@9278
   257
        MoveSprites(state->renderers[i], sprites[i]);
icculus@9278
   258
    }
philipp@9607
   259
#ifdef __EMSCRIPTEN__
philipp@9607
   260
    if (done) {
philipp@9607
   261
        emscripten_cancel_main_loop();
philipp@9607
   262
    }
philipp@9607
   263
#endif
icculus@9278
   264
}
icculus@9278
   265
slouken@1895
   266
int
slouken@1895
   267
main(int argc, char *argv[])
slouken@1895
   268
{
icculus@9278
   269
    int i;
slouken@1895
   270
    Uint32 then, now, frames;
philipp@9922
   271
    Uint64 seed;
slouken@7502
   272
    const char *icon = "icon.bmp";
slouken@1895
   273
slouken@1914
   274
    /* Initialize parameters */
slouken@1895
   275
    num_sprites = NUM_SPRITES;
slouken@1914
   276
slouken@1914
   277
    /* Initialize test framework */
slouken@6785
   278
    state = SDLTest_CommonCreateState(argv, SDL_INIT_VIDEO);
slouken@1914
   279
    if (!state) {
slouken@1914
   280
        return 1;
slouken@1914
   281
    }
icculus@5520
   282
slouken@1914
   283
    for (i = 1; i < argc;) {
slouken@1914
   284
        int consumed;
slouken@1914
   285
slouken@6785
   286
        consumed = SDLTest_CommonArg(state, i);
slouken@1915
   287
        if (consumed == 0) {
slouken@1916
   288
            consumed = -1;
slouken@1916
   289
            if (SDL_strcasecmp(argv[i], "--blend") == 0) {
slouken@1916
   290
                if (argv[i + 1]) {
slouken@1916
   291
                    if (SDL_strcasecmp(argv[i + 1], "none") == 0) {
slouken@2884
   292
                        blendMode = SDL_BLENDMODE_NONE;
slouken@1916
   293
                        consumed = 2;
slouken@1916
   294
                    } else if (SDL_strcasecmp(argv[i + 1], "blend") == 0) {
slouken@2884
   295
                        blendMode = SDL_BLENDMODE_BLEND;
slouken@1916
   296
                        consumed = 2;
slouken@1916
   297
                    } else if (SDL_strcasecmp(argv[i + 1], "add") == 0) {
slouken@2884
   298
                        blendMode = SDL_BLENDMODE_ADD;
slouken@1916
   299
                        consumed = 2;
slouken@5184
   300
                    } else if (SDL_strcasecmp(argv[i + 1], "mod") == 0) {
slouken@5184
   301
                        blendMode = SDL_BLENDMODE_MOD;
slouken@5184
   302
                        consumed = 2;
slouken@11282
   303
                    } else if (SDL_strcasecmp(argv[i + 1], "sub") == 0) {
slouken@11282
   304
                        blendMode = SDL_ComposeCustomBlendMode(SDL_BLENDFACTOR_SRC_ALPHA, SDL_BLENDFACTOR_ONE, SDL_BLENDOPERATION_SUBTRACT, SDL_BLENDFACTOR_ZERO, SDL_BLENDFACTOR_ONE, SDL_BLENDOPERATION_SUBTRACT);
slouken@11282
   305
                        consumed = 2;
slouken@1916
   306
                    }
slouken@1916
   307
                }
aschiffler@7315
   308
            } else if (SDL_strcasecmp(argv[i], "--iterations") == 0) {
aschiffler@7315
   309
                if (argv[i + 1]) {
aschiffler@7315
   310
                    iterations = SDL_atoi(argv[i + 1]);
aschiffler@7315
   311
                    if (iterations < -1) iterations = -1;
aschiffler@7315
   312
                    consumed = 2;
aschiffler@7315
   313
                }
slouken@1985
   314
            } else if (SDL_strcasecmp(argv[i], "--cyclecolor") == 0) {
slouken@1985
   315
                cycle_color = SDL_TRUE;
slouken@1985
   316
                consumed = 1;
slouken@1985
   317
            } else if (SDL_strcasecmp(argv[i], "--cyclealpha") == 0) {
slouken@1985
   318
                cycle_alpha = SDL_TRUE;
slouken@1985
   319
                consumed = 1;
slouken@1916
   320
            } else if (SDL_isdigit(*argv[i])) {
slouken@1916
   321
                num_sprites = SDL_atoi(argv[i]);
slouken@1916
   322
                consumed = 1;
slouken@7502
   323
            } else if (argv[i][0] != '-') {
slouken@7502
   324
                icon = argv[i];
slouken@7502
   325
                consumed = 1;
slouken@1916
   326
            }
slouken@1915
   327
        }
slouken@1914
   328
        if (consumed < 0) {
aschiffler@7639
   329
            SDL_Log("Usage: %s %s [--blend none|blend|add|mod] [--cyclecolor] [--cyclealpha] [--iterations N] [num_sprites] [icon.bmp]\n",
slouken@6785
   330
                    argv[0], SDLTest_CommonUsage(state));
slouken@1895
   331
            quit(1);
slouken@1895
   332
        }
slouken@1914
   333
        i += consumed;
slouken@1895
   334
    }
slouken@6785
   335
    if (!SDLTest_CommonInit(state)) {
slouken@1914
   336
        quit(2);
slouken@1895
   337
    }
slouken@1895
   338
slouken@1895
   339
    /* Create the windows, initialize the renderers, and load the textures */
slouken@1914
   340
    sprites =
slouken@3685
   341
        (SDL_Texture **) SDL_malloc(state->num_windows * sizeof(*sprites));
slouken@1914
   342
    if (!sprites) {
aschiffler@7639
   343
        SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Out of memory!\n");
slouken@1895
   344
        quit(2);
slouken@1895
   345
    }
slouken@1914
   346
    for (i = 0; i < state->num_windows; ++i) {
slouken@5147
   347
        SDL_Renderer *renderer = state->renderers[i];
slouken@5147
   348
        SDL_SetRenderDrawColor(renderer, 0xA0, 0xA0, 0xA0, 0xFF);
slouken@5147
   349
        SDL_RenderClear(renderer);
slouken@1895
   350
    }
slouken@7502
   351
    if (LoadSprite(icon) < 0) {
slouken@1895
   352
        quit(2);
slouken@1895
   353
    }
slouken@1895
   354
slouken@1895
   355
    /* Allocate memory for the sprite info */
slouken@1895
   356
    positions = (SDL_Rect *) SDL_malloc(num_sprites * sizeof(SDL_Rect));
slouken@1895
   357
    velocities = (SDL_Rect *) SDL_malloc(num_sprites * sizeof(SDL_Rect));
slouken@1895
   358
    if (!positions || !velocities) {
aschiffler@7639
   359
        SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Out of memory!\n");
slouken@1895
   360
        quit(2);
slouken@1895
   361
    }
aschiffler@7315
   362
aschiffler@7315
   363
    /* Position sprites and set their velocities using the fuzzer */ 
aschiffler@7315
   364
    if (iterations >= 0) {
aschiffler@7315
   365
        /* Deterministic seed - used for visual tests */
aschiffler@7315
   366
        seed = (Uint64)iterations;
aschiffler@7315
   367
    } else {
aschiffler@7315
   368
        /* Pseudo-random seed generated from the time */
aschiffler@7315
   369
        seed = (Uint64)time(NULL);
aschiffler@7315
   370
    }
aschiffler@7315
   371
    SDLTest_FuzzerInit(seed);
slouken@1895
   372
    for (i = 0; i < num_sprites; ++i) {
aschiffler@7315
   373
        positions[i].x = SDLTest_RandomIntegerInRange(0, state->window_w - sprite_w);
aschiffler@7315
   374
        positions[i].y = SDLTest_RandomIntegerInRange(0, state->window_h - sprite_h);
slouken@1895
   375
        positions[i].w = sprite_w;
slouken@1895
   376
        positions[i].h = sprite_h;
slouken@1895
   377
        velocities[i].x = 0;
slouken@1895
   378
        velocities[i].y = 0;
slouken@1895
   379
        while (!velocities[i].x && !velocities[i].y) {
aschiffler@7315
   380
            velocities[i].x = SDLTest_RandomIntegerInRange(-MAX_SPEED, MAX_SPEED);
aschiffler@7315
   381
            velocities[i].y = SDLTest_RandomIntegerInRange(-MAX_SPEED, MAX_SPEED);
slouken@1895
   382
        }
slouken@1895
   383
    }
slouken@1895
   384
slouken@1915
   385
    /* Main render loop */
slouken@1895
   386
    frames = 0;
slouken@1895
   387
    then = SDL_GetTicks();
slouken@1895
   388
    done = 0;
icculus@9278
   389
icculus@9278
   390
#ifdef __EMSCRIPTEN__
icculus@9278
   391
    emscripten_set_main_loop(loop, 0, 1);
icculus@9278
   392
#else
slouken@1895
   393
    while (!done) {
slouken@1895
   394
        ++frames;
icculus@9278
   395
        loop();
slouken@1895
   396
    }
icculus@9278
   397
#endif
slouken@1895
   398
slouken@1895
   399
    /* Print out some timing information */
slouken@1895
   400
    now = SDL_GetTicks();
slouken@1895
   401
    if (now > then) {
slouken@2786
   402
        double fps = ((double) frames * 1000) / (now - then);
aschiffler@7639
   403
        SDL_Log("%2.2f frames per second\n", fps);
slouken@1895
   404
    }
slouken@1895
   405
    quit(0);
slouken@5147
   406
    return 0;
slouken@1895
   407
}
slouken@1895
   408
slouken@1895
   409
/* vi: set ts=4 sw=4 expandtab: */