Xcode-iPhoneOS/Demos/src/fireworks.c
author Sam Lantinga <slouken@libsdl.org>
Sun, 13 Mar 2011 11:17:11 -0700
changeset 5483 ccec742c9b7d
parent 5365 db3c6ebcc954
permissions -rw-r--r--
Removed unreferenced variable
slouken@3277
     1
/*
slouken@3277
     2
 *	fireworks.c
slouken@3277
     3
 *	written by Holmes Futrell
slouken@3277
     4
 *	use however you want
slouken@3277
     5
 */
slouken@3277
     6
slouken@3277
     7
#include "SDL.h"
slouken@3277
     8
#include "SDL_opengles.h"
slouken@3277
     9
#include "common.h"
slouken@3277
    10
#include <math.h>
slouken@3277
    11
#include <time.h>
slouken@3277
    12
slouken@3277
    13
#define MILLESECONDS_PER_FRAME 16       /* about 60 frames per second */
slouken@3277
    14
#define ACCEL 0.0001f           /* acceleration due to gravity, units in pixels per millesecond squared */
slouken@3277
    15
#define WIND_RESISTANCE 0.00005f        /* acceleration per unit velocity due to wind resistance */
slouken@3277
    16
#define MAX_PARTICLES 2000      /* maximum number of particles displayed at once */
slouken@3277
    17
slouken@3277
    18
static GLuint particleTextureID;        /* OpenGL particle texture id */
slouken@3277
    19
static SDL_bool pointSizeExtensionSupported;    /* is GL_OES_point_size_array supported ? */
slouken@3277
    20
/* 
slouken@3277
    21
	used to describe what type of particle a given struct particle is.
slouken@3277
    22
	emitter - this particle flies up, shooting off trail particles, then finally explodes into dust particles.
slouken@3277
    23
	trail	- shoots off, following emitter particle
slouken@3277
    24
	dust	- radiates outwards from emitter explosion
slouken@3277
    25
*/
slouken@3277
    26
enum particleType
slouken@3277
    27
{
slouken@3277
    28
    emitter = 0,
slouken@3277
    29
    trail,
slouken@3277
    30
    dust
slouken@3277
    31
};
slouken@3277
    32
/*
slouken@3277
    33
	struct particle is used to describe each particle displayed on screen
slouken@3277
    34
*/
slouken@3277
    35
struct particle
slouken@3277
    36
{
slouken@3277
    37
    GLfloat x;                  /* x position of particle */
slouken@3277
    38
    GLfloat y;                  /* y position of particle */
slouken@3277
    39
    GLubyte color[4];           /* rgba color of particle */
slouken@3277
    40
    GLfloat size;               /* size of particle in pixels */
slouken@3277
    41
    GLfloat xvel;               /* x velocity of particle in pixels per milesecond */
slouken@3277
    42
    GLfloat yvel;               /* y velocity of particle in pixels per millescond */
slouken@3277
    43
    int isActive;               /* if not active, then particle is overwritten */
slouken@3277
    44
    enum particleType type;     /* see enum particleType */
slouken@3277
    45
} particles[MAX_PARTICLES];     /* this array holds all our particles */
slouken@3277
    46
slouken@3277
    47
static int num_active_particles;        /* how many members of the particle array are actually being drawn / animated? */
slouken@5365
    48
static int screen_w, screen_h;
slouken@3277
    49
slouken@3277
    50
/* function declarations */
slouken@3277
    51
void spawnTrailFromEmitter(struct particle *emitter);
slouken@3277
    52
void spawnEmitterParticle(GLfloat x, GLfloat y);
slouken@3277
    53
void explodeEmitter(struct particle *emitter);
slouken@3277
    54
void initializeParticles(void);
slouken@3277
    55
void initializeTexture();
slouken@3277
    56
int nextPowerOfTwo(int x);
slouken@3277
    57
void drawParticles();
slouken@3277
    58
void stepParticles(void);
slouken@3277
    59
slouken@3277
    60
/*	helper function (used in texture loading)
slouken@3277
    61
	returns next power of two greater than or equal to x
slouken@3277
    62
*/
slouken@3277
    63
int
slouken@3277
    64
nextPowerOfTwo(int x)
slouken@3277
    65
{
slouken@3277
    66
    int val = 1;
slouken@3277
    67
    while (val < x) {
slouken@3277
    68
        val *= 2;
slouken@3277
    69
    }
slouken@3277
    70
    return val;
slouken@3277
    71
}
slouken@3277
    72
slouken@3277
    73
/*	
slouken@3277
    74
	steps each active particle by timestep MILLESECONDS_PER_FRAME
slouken@3277
    75
*/
slouken@3277
    76
void
slouken@3277
    77
stepParticles(void)
slouken@3277
    78
{
slouken@3277
    79
    int i;
slouken@3277
    80
    struct particle *slot = particles;
slouken@3277
    81
    struct particle *curr = particles;
slouken@3277
    82
    for (i = 0; i < num_active_particles; i++) {
slouken@3277
    83
        /* is the particle actually active, or is it marked for deletion? */
slouken@3277
    84
        if (curr->isActive) {
slouken@3277
    85
            /* is the particle off the screen? */
slouken@5365
    86
            if (curr->y > screen_h)
slouken@3277
    87
                curr->isActive = 0;
slouken@3277
    88
            else if (curr->y < 0)
slouken@3277
    89
                curr->isActive = 0;
slouken@5365
    90
            if (curr->x > screen_w)
slouken@3277
    91
                curr->isActive = 0;
slouken@3277
    92
            else if (curr->x < 0)
slouken@3277
    93
                curr->isActive = 0;
slouken@3277
    94
slouken@3277
    95
            /* step velocity, then step position */
slouken@3277
    96
            curr->yvel += ACCEL * MILLESECONDS_PER_FRAME;
slouken@3277
    97
            curr->xvel += 0.0f;
slouken@3277
    98
            curr->y += curr->yvel * MILLESECONDS_PER_FRAME;
slouken@3277
    99
            curr->x += curr->xvel * MILLESECONDS_PER_FRAME;
slouken@3277
   100
slouken@3277
   101
            /* particle behavior */
slouken@3277
   102
            if (curr->type == emitter) {
slouken@3277
   103
                /* if we're an emitter, spawn a trail */
slouken@3277
   104
                spawnTrailFromEmitter(curr);
slouken@3277
   105
                /* if we've reached our peak, explode */
slouken@3277
   106
                if (curr->yvel > 0.0) {
slouken@3277
   107
                    explodeEmitter(curr);
slouken@3277
   108
                }
slouken@3277
   109
            } else {
slouken@3277
   110
                float speed =
slouken@3277
   111
                    sqrt(curr->xvel * curr->xvel + curr->yvel * curr->yvel);
slouken@3277
   112
                /*      if wind resistance is not powerful enough to stop us completely,
slouken@3277
   113
                   then apply winde resistance, otherwise just stop us completely */
slouken@3277
   114
                if (WIND_RESISTANCE * MILLESECONDS_PER_FRAME < speed) {
slouken@3277
   115
                    float normx = curr->xvel / speed;
slouken@3277
   116
                    float normy = curr->yvel / speed;
slouken@3277
   117
                    curr->xvel -=
slouken@3277
   118
                        normx * WIND_RESISTANCE * MILLESECONDS_PER_FRAME;
slouken@3277
   119
                    curr->yvel -=
slouken@3277
   120
                        normy * WIND_RESISTANCE * MILLESECONDS_PER_FRAME;
slouken@3277
   121
                } else {
slouken@3277
   122
                    curr->xvel = curr->yvel = 0;        /* stop particle */
slouken@3277
   123
                }
slouken@3277
   124
slouken@3277
   125
                if (curr->color[3] <= MILLESECONDS_PER_FRAME * 0.1275f) {
slouken@3277
   126
                    /* if this next step will cause us to fade out completely
slouken@3277
   127
                       then just mark for deletion */
slouken@3277
   128
                    curr->isActive = 0;
slouken@3277
   129
                } else {
slouken@3277
   130
                    /* otherwise, let's fade a bit more */
slouken@3277
   131
                    curr->color[3] -= MILLESECONDS_PER_FRAME * 0.1275f;
slouken@3277
   132
                }
slouken@3277
   133
slouken@3277
   134
                /* if we're a dust particle, shrink our size */
slouken@3277
   135
                if (curr->type == dust)
slouken@3277
   136
                    curr->size -= MILLESECONDS_PER_FRAME * 0.010f;
slouken@3277
   137
slouken@3277
   138
            }
slouken@3277
   139
slouken@3277
   140
            /* if we're still active, pack ourselves in the array next
slouken@3277
   141
               to the last active guy (pack the array tightly) */
slouken@3277
   142
            if (curr->isActive)
slouken@3277
   143
                *(slot++) = *curr;
slouken@3277
   144
        }                       /* endif (curr->isActive) */
slouken@3277
   145
        curr++;
slouken@3277
   146
    }
slouken@3277
   147
    /* the number of active particles is computed as the difference between
slouken@3277
   148
       old number of active particles, where slot points, and the 
slouken@3277
   149
       new size of the array, where particles points */
slouken@3277
   150
    num_active_particles = slot - particles;
slouken@3277
   151
}
slouken@3277
   152
slouken@3277
   153
/*
slouken@3277
   154
	This draws all the particles shown on screen
slouken@3277
   155
*/
slouken@3277
   156
void
slouken@3277
   157
drawParticles()
slouken@3277
   158
{
slouken@3277
   159
slouken@3277
   160
    /* draw the background */
slouken@3277
   161
    glClear(GL_COLOR_BUFFER_BIT);
slouken@3277
   162
slouken@3277
   163
    /* set up the position and color pointers */
slouken@3277
   164
    glVertexPointer(2, GL_FLOAT, sizeof(struct particle), particles);
slouken@3277
   165
    glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(struct particle),
slouken@3277
   166
                   particles[0].color);
slouken@3277
   167
slouken@3277
   168
    if (pointSizeExtensionSupported) {
slouken@3277
   169
        /* pass in our array of point sizes */
slouken@3277
   170
        glPointSizePointerOES(GL_FLOAT, sizeof(struct particle),
slouken@3277
   171
                              &(particles[0].size));
slouken@3277
   172
    }
slouken@3277
   173
slouken@3277
   174
    /* draw our particles! */
slouken@3277
   175
    glDrawArrays(GL_POINTS, 0, num_active_particles);
slouken@3277
   176
slouken@3277
   177
}
slouken@3277
   178
slouken@3277
   179
/*
slouken@3277
   180
	This causes an emitter to explode in a circular bloom of dust particles
slouken@3277
   181
*/
slouken@3277
   182
void
slouken@3277
   183
explodeEmitter(struct particle *emitter)
slouken@3277
   184
{
slouken@3277
   185
    /* first off, we're done with this particle, so turn active off */
slouken@3277
   186
    emitter->isActive = 0;
slouken@3277
   187
    int i;
slouken@3277
   188
    for (i = 0; i < 200; i++) {
slouken@3277
   189
slouken@3277
   190
        if (num_active_particles >= MAX_PARTICLES)
slouken@3277
   191
            return;
slouken@3277
   192
slouken@3277
   193
        /* come up with a random angle and speed for new particle */
slouken@3277
   194
        float theta = randomFloat(0, 2.0f * 3.141592);
slouken@3277
   195
        float exponent = 3.0f;
slouken@3277
   196
        float speed = randomFloat(0.00, powf(0.17, exponent));
slouken@3277
   197
        speed = powf(speed, 1.0f / exponent);
slouken@3277
   198
slouken@3277
   199
        /*select the particle at the end of our array */
slouken@3277
   200
        struct particle *p = &particles[num_active_particles];
slouken@3277
   201
slouken@3277
   202
        /* set the particles properties */
slouken@3277
   203
        p->xvel = speed * cos(theta);
slouken@3277
   204
        p->yvel = speed * sin(theta);
slouken@3277
   205
        p->x = emitter->x + emitter->xvel;
slouken@3277
   206
        p->y = emitter->y + emitter->yvel;
slouken@3277
   207
        p->isActive = 1;
slouken@3277
   208
        p->type = dust;
slouken@3277
   209
        p->size = 15;
slouken@3277
   210
        /* inherit emitter's color */
slouken@3277
   211
        p->color[0] = emitter->color[0];
slouken@3277
   212
        p->color[1] = emitter->color[1];
slouken@3277
   213
        p->color[2] = emitter->color[2];
slouken@3277
   214
        p->color[3] = 255;
slouken@3277
   215
        /* our array has expanded at the end */
slouken@3277
   216
        num_active_particles++;
slouken@3277
   217
    }
slouken@3277
   218
slouken@3277
   219
}
slouken@3277
   220
slouken@3277
   221
/*
slouken@3277
   222
	This spawns a trail particle from an emitter
slouken@3277
   223
*/
slouken@3277
   224
void
slouken@3277
   225
spawnTrailFromEmitter(struct particle *emitter)
slouken@3277
   226
{
slouken@3277
   227
slouken@3277
   228
    if (num_active_particles >= MAX_PARTICLES)
slouken@3277
   229
        return;
slouken@3277
   230
slouken@3277
   231
    /* select the particle at the slot at the end of our array */
slouken@3277
   232
    struct particle *p = &particles[num_active_particles];
slouken@3277
   233
slouken@3277
   234
    /* set position and velocity to roughly that of the emitter */
slouken@3277
   235
    p->x = emitter->x + randomFloat(-3.0, 3.0);
slouken@3277
   236
    p->y = emitter->y + emitter->size / 2.0f;
slouken@3277
   237
    p->xvel = emitter->xvel + randomFloat(-0.005, 0.005);
slouken@3277
   238
    p->yvel = emitter->yvel + 0.1;
slouken@3277
   239
slouken@3277
   240
    /* set the color to a random-ish orangy type color */
slouken@3277
   241
    p->color[0] = (0.8f + randomFloat(-0.1, 0.0)) * 255;
slouken@3277
   242
    p->color[1] = (0.4f + randomFloat(-0.1, 0.1)) * 255;
slouken@3277
   243
    p->color[2] = (0.0f + randomFloat(0.0, 0.2)) * 255;
slouken@3277
   244
    p->color[3] = (0.7f) * 255;
slouken@3277
   245
slouken@3277
   246
    /* set other attributes */
slouken@3277
   247
    p->size = 10;
slouken@3277
   248
    p->type = trail;
slouken@3277
   249
    p->isActive = 1;
slouken@3277
   250
slouken@3277
   251
    /* our array has expanded at the end */
slouken@3277
   252
    num_active_particles++;
slouken@3277
   253
slouken@3277
   254
}
slouken@3277
   255
slouken@3277
   256
/*
slouken@3277
   257
	spawns a new emitter particle at the bottom of the screen
slouken@3277
   258
    destined for the point (x,y).
slouken@3277
   259
*/
slouken@3277
   260
void
slouken@3277
   261
spawnEmitterParticle(GLfloat x, GLfloat y)
slouken@3277
   262
{
slouken@3277
   263
slouken@3277
   264
    if (num_active_particles >= MAX_PARTICLES)
slouken@3277
   265
        return;
slouken@3277
   266
slouken@3277
   267
    /* find particle at endpoint of array */
slouken@3277
   268
    struct particle *p = &particles[num_active_particles];
slouken@3277
   269
slouken@3277
   270
    /* set the color randomly */
slouken@3277
   271
    switch (rand() % 4) {
slouken@3277
   272
    case 0:
slouken@3277
   273
        p->color[0] = 255;
slouken@3277
   274
        p->color[1] = 100;
slouken@3277
   275
        p->color[2] = 100;
slouken@3277
   276
        break;
slouken@3277
   277
    case 1:
slouken@3277
   278
        p->color[0] = 100;
slouken@3277
   279
        p->color[1] = 255;
slouken@3277
   280
        p->color[2] = 100;
slouken@3277
   281
        break;
slouken@3277
   282
    case 2:
slouken@3277
   283
        p->color[0] = 100;
slouken@3277
   284
        p->color[1] = 100;
slouken@3277
   285
        p->color[2] = 255;
slouken@3277
   286
        break;
slouken@3277
   287
    case 3:
slouken@3277
   288
        p->color[0] = 255;
slouken@3277
   289
        p->color[1] = 150;
slouken@3277
   290
        p->color[2] = 50;
slouken@3277
   291
        break;
slouken@3277
   292
    }
slouken@3277
   293
    p->color[3] = 255;
slouken@5365
   294
    /* set position to (x, screen_h) */
slouken@3277
   295
    p->x = x;
slouken@5365
   296
    p->y = screen_h;
slouken@3277
   297
    /* set velocity so that terminal point is (x,y) */
slouken@3277
   298
    p->xvel = 0;
slouken@5365
   299
    p->yvel = -sqrt(2 * ACCEL * (screen_h - y));
slouken@3277
   300
    /* set other attributes */
slouken@3277
   301
    p->size = 10;
slouken@3277
   302
    p->type = emitter;
slouken@3277
   303
    p->isActive = 1;
slouken@3277
   304
    /* our array has expanded at the end */
slouken@3277
   305
    num_active_particles++;
slouken@3277
   306
}
slouken@3277
   307
slouken@3277
   308
/* just sets the endpoint of the particle array to element zero */
slouken@3277
   309
void
slouken@3277
   310
initializeParticles(void)
slouken@3277
   311
{
slouken@3277
   312
    num_active_particles = 0;
slouken@3277
   313
}
slouken@3277
   314
slouken@3277
   315
/*
slouken@3277
   316
	loads the particle texture
slouken@3277
   317
 */
slouken@3277
   318
void
slouken@3277
   319
initializeTexture()
slouken@3277
   320
{
slouken@3277
   321
slouken@3277
   322
    int bpp;                    /* texture bits per pixel */
slouken@3277
   323
    Uint32 Rmask, Gmask, Bmask, Amask;  /* masks for pixel format passed into OpenGL */
slouken@3277
   324
    SDL_Surface *bmp_surface;   /* the bmp is loaded here */
slouken@3277
   325
    SDL_Surface *bmp_surface_rgba8888;  /* this serves as a destination to convert the BMP
slouken@3277
   326
                                           to format passed into OpenGL */
slouken@3277
   327
slouken@3277
   328
    bmp_surface = SDL_LoadBMP("stroke.bmp");
slouken@3277
   329
    if (bmp_surface == NULL) {
slouken@3277
   330
        fatalError("could not load stroke.bmp");
slouken@3277
   331
    }
slouken@3277
   332
slouken@3277
   333
    /* Grab info about format that will be passed into OpenGL */
slouken@3277
   334
    SDL_PixelFormatEnumToMasks(SDL_PIXELFORMAT_ABGR8888, &bpp, &Rmask, &Gmask,
slouken@3277
   335
                               &Bmask, &Amask);
slouken@3277
   336
    /* Create surface that will hold pixels passed into OpenGL */
slouken@3277
   337
    bmp_surface_rgba8888 =
slouken@3277
   338
        SDL_CreateRGBSurface(0, bmp_surface->w, bmp_surface->h, bpp, Rmask,
slouken@3277
   339
                             Gmask, Bmask, Amask);
slouken@3277
   340
    /* Blit to this surface, effectively converting the format */
slouken@3277
   341
    SDL_BlitSurface(bmp_surface, NULL, bmp_surface_rgba8888, NULL);
slouken@3277
   342
slouken@3277
   343
    glGenTextures(1, &particleTextureID);
slouken@3277
   344
    glBindTexture(GL_TEXTURE_2D, particleTextureID);
slouken@3277
   345
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,
slouken@3277
   346
                 nextPowerOfTwo(bmp_surface->w),
slouken@3277
   347
                 nextPowerOfTwo(bmp_surface->h),
slouken@3277
   348
                 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
slouken@3277
   349
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
slouken@3277
   350
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
slouken@3277
   351
    /* this is where we actually pass in the pixel data */
slouken@3277
   352
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, bmp_surface->w, bmp_surface->h, 0,
slouken@3277
   353
                 GL_RGBA, GL_UNSIGNED_BYTE, bmp_surface_rgba8888->pixels);
slouken@3277
   354
slouken@3277
   355
    /* free bmp surface and converted bmp surface */
slouken@3277
   356
    SDL_FreeSurface(bmp_surface);
slouken@3277
   357
    SDL_FreeSurface(bmp_surface_rgba8888);
slouken@3277
   358
slouken@3277
   359
}
slouken@3277
   360
slouken@3277
   361
int
slouken@3277
   362
main(int argc, char *argv[])
slouken@3277
   363
{
slouken@3685
   364
    SDL_Window *window;         /* main window */
slouken@5365
   365
    SDL_GLContext context;
slouken@5365
   366
    int w, h;
slouken@3277
   367
    Uint32 startFrame;          /* time frame began to process */
slouken@3277
   368
    Uint32 endFrame;            /* time frame ended processing */
slouken@3277
   369
    Uint32 delay;               /* time to pause waiting to draw next frame */
slouken@3277
   370
    int done;                   /* should we clean up and exit? */
slouken@3277
   371
slouken@3277
   372
    /* initialize SDL */
slouken@3277
   373
    if (SDL_Init(SDL_INIT_VIDEO) < 0) {
slouken@3277
   374
        fatalError("Could not initialize SDL");
slouken@3277
   375
    }
slouken@3277
   376
    /* seed the random number generator */
slouken@3277
   377
    srand(time(NULL));
slouken@3277
   378
    /*      
slouken@3277
   379
       request some OpenGL parameters
slouken@3277
   380
       that may speed drawing
slouken@3277
   381
     */
slouken@3277
   382
    SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 5);
slouken@3277
   383
    SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 6);
slouken@3277
   384
    SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 5);
slouken@3277
   385
    SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 0);
slouken@3277
   386
    SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 0);
slouken@3277
   387
    SDL_GL_SetAttribute(SDL_GL_RETAINED_BACKING, 0);
slouken@3277
   388
    SDL_GL_SetAttribute(SDL_GL_ACCELERATED_VISUAL, 1);
slouken@3277
   389
slouken@3277
   390
    /* create main window and renderer */
slouken@3685
   391
    window = SDL_CreateWindow(NULL, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT,
slouken@3277
   392
                                SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN |
slouken@3277
   393
                                SDL_WINDOW_BORDERLESS);
slouken@5365
   394
    context = SDL_GL_CreateContext(window);
slouken@3277
   395
slouken@3277
   396
    /* load the particle texture */
slouken@3277
   397
    initializeTexture();
slouken@3277
   398
slouken@3277
   399
    /*      check if GL_POINT_SIZE_ARRAY_OES is supported
slouken@3277
   400
       this is used to give each particle its own size
slouken@3277
   401
     */
slouken@3277
   402
    pointSizeExtensionSupported =
slouken@3277
   403
        SDL_GL_ExtensionSupported("GL_OES_point_size_array");
slouken@3277
   404
slouken@3277
   405
    /* set up some OpenGL state */
slouken@5365
   406
    glDisable(GL_DEPTH_TEST);
slouken@5365
   407
    glDisable(GL_CULL_FACE);
slouken@5365
   408
slouken@5365
   409
    glMatrixMode(GL_MODELVIEW);
slouken@5365
   410
    glLoadIdentity();
slouken@5365
   411
slouken@5365
   412
    SDL_GetWindowSize(window, &screen_w, &screen_h);
slouken@5365
   413
    glViewport(0, 0, screen_w, screen_h);
slouken@5365
   414
slouken@5365
   415
    glMatrixMode(GL_PROJECTION);
slouken@5365
   416
    glLoadIdentity();
slouken@5365
   417
    glOrthof((GLfloat) 0,
slouken@5365
   418
             (GLfloat) screen_w,
slouken@5365
   419
             (GLfloat) screen_h,
slouken@5365
   420
             (GLfloat) 0, 0.0, 1.0);
slouken@5365
   421
slouken@3277
   422
    glEnable(GL_TEXTURE_2D);
slouken@3277
   423
    glEnable(GL_BLEND);
slouken@3277
   424
    glBlendFunc(GL_SRC_ALPHA, GL_ONE);
slouken@3277
   425
    glEnableClientState(GL_VERTEX_ARRAY);
slouken@3277
   426
    glEnableClientState(GL_COLOR_ARRAY);
slouken@3277
   427
slouken@3277
   428
    glEnable(GL_POINT_SPRITE_OES);
slouken@3277
   429
    glTexEnvi(GL_POINT_SPRITE_OES, GL_COORD_REPLACE_OES, 1);
slouken@3277
   430
slouken@3277
   431
    if (pointSizeExtensionSupported) {
slouken@3277
   432
        /* we use this to set the sizes of all the particles */
slouken@3277
   433
        glEnableClientState(GL_POINT_SIZE_ARRAY_OES);
slouken@3277
   434
    } else {
slouken@3277
   435
        /* if extension not available then all particles have size 10 */
slouken@3277
   436
        glPointSize(10);
slouken@3277
   437
    }
slouken@3277
   438
slouken@3277
   439
    done = 0;
slouken@3277
   440
    /* enter main loop */
slouken@3277
   441
    while (!done) {
slouken@3277
   442
        startFrame = SDL_GetTicks();
slouken@3277
   443
        SDL_Event event;
slouken@3277
   444
        while (SDL_PollEvent(&event)) {
slouken@3277
   445
            if (event.type == SDL_QUIT) {
slouken@3277
   446
                done = 1;
slouken@3277
   447
            }
slouken@3277
   448
            if (event.type == SDL_MOUSEBUTTONDOWN) {
slouken@3277
   449
                int x, y;
slouken@3277
   450
                SDL_GetMouseState(&x, &y);
slouken@3277
   451
                spawnEmitterParticle(x, y);
slouken@3277
   452
            }
slouken@3277
   453
        }
slouken@3277
   454
        stepParticles();
slouken@3277
   455
        drawParticles();
slouken@5365
   456
        SDL_GL_SwapWindow(window);
slouken@3277
   457
        endFrame = SDL_GetTicks();
slouken@3277
   458
slouken@3277
   459
        /* figure out how much time we have left, and then sleep */
slouken@3277
   460
        delay = MILLESECONDS_PER_FRAME - (endFrame - startFrame);
slouken@3277
   461
        if (delay > MILLESECONDS_PER_FRAME) {
slouken@3277
   462
            delay = MILLESECONDS_PER_FRAME;
slouken@3277
   463
        }
slouken@3277
   464
        if (delay > 0) {
slouken@3277
   465
            SDL_Delay(delay);
slouken@3277
   466
        }
slouken@3277
   467
    }
slouken@3277
   468
slouken@3277
   469
    /* delete textures */
slouken@3277
   470
    glDeleteTextures(1, &particleTextureID);
slouken@3277
   471
    /* shutdown SDL */
slouken@3277
   472
    SDL_Quit();
slouken@3277
   473
slouken@3277
   474
    return 0;
slouken@3277
   475
}