Xcode-iPhoneOS/Demos/src/accelerometer.c
author Sam Lantinga <slouken@libsdl.org>
Sun, 13 Mar 2011 11:17:11 -0700
changeset 5483 ccec742c9b7d
parent 5208 78db79f5a4e2
permissions -rw-r--r--
Removed unreferenced variable
slouken@3277
     1
/*
slouken@3277
     2
 *	accelerometer.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 "math.h"
slouken@3277
     9
#include "common.h"
slouken@3277
    10
slouken@3277
    11
#define MILLESECONDS_PER_FRAME 16       /* about 60 frames per second */
slouken@3277
    12
#define DAMPING 0.5f;           /* after bouncing off a wall, damping coefficient determines final speed */
slouken@3277
    13
#define FRICTION 0.0008f        /* coefficient of acceleration that opposes direction of motion */
slouken@3277
    14
#define GRAVITY_CONSTANT 0.004f /* how sensitive the ship is to the accelerometer */
slouken@3277
    15
slouken@3277
    16
/*	If we aren't on an iPhone, then this definition ought to yield reasonable behavior */
slouken@3277
    17
#ifndef SDL_IPHONE_MAX_GFORCE
slouken@3277
    18
#define SDL_IPHONE_MAX_GFORCE 5.0f
slouken@3277
    19
#endif
slouken@3277
    20
slouken@3277
    21
static SDL_Joystick *accelerometer;     /* used for controlling the ship */
slouken@3277
    22
slouken@3277
    23
static struct
slouken@3277
    24
{
slouken@3277
    25
    float x, y;                 /* position of ship */
slouken@3277
    26
    float vx, vy;               /* velocity of ship (in pixels per millesecond) */
slouken@3277
    27
    SDL_Rect rect;              /* (drawn) position and size of ship */
slouken@3690
    28
} shipData;
slouken@3277
    29
slouken@3685
    30
static SDL_Texture *ship = 0;        /* texture for spaceship */
slouken@3685
    31
static SDL_Texture *space = 0;       /* texture for space (background */
slouken@3277
    32
slouken@3277
    33
void
slouken@5208
    34
render(SDL_Renderer *renderer)
slouken@3277
    35
{
slouken@3277
    36
slouken@3277
    37
slouken@3277
    38
    /* get joystick (accelerometer) axis values and normalize them */
slouken@3277
    39
    float ax = SDL_JoystickGetAxis(accelerometer, 0);
slouken@3277
    40
    float ay = -SDL_JoystickGetAxis(accelerometer, 1);
slouken@3277
    41
slouken@3277
    42
    /* ship screen constraints */
slouken@3277
    43
    Uint32 minx = 0.0f;
slouken@3690
    44
    Uint32 maxx = SCREEN_WIDTH - shipData.rect.w;
slouken@3277
    45
    Uint32 miny = 0.0f;
slouken@3690
    46
    Uint32 maxy = SCREEN_HEIGHT - shipData.rect.h;
slouken@3277
    47
slouken@3277
    48
#define SINT16_MAX ((float)(0x7FFF))
slouken@3277
    49
slouken@3277
    50
    /* update velocity from accelerometer
slouken@3277
    51
       the factor SDL_IPHONE_MAX_G_FORCE / SINT16_MAX converts between 
slouken@3277
    52
       SDL's units reported from the joytick, and units of g-force, as reported by the accelerometer
slouken@3277
    53
     */
slouken@3690
    54
    shipData.vx +=
slouken@3277
    55
        ax * SDL_IPHONE_MAX_GFORCE / SINT16_MAX * GRAVITY_CONSTANT *
slouken@3277
    56
        MILLESECONDS_PER_FRAME;
slouken@3690
    57
    shipData.vy +=
slouken@3277
    58
        ay * SDL_IPHONE_MAX_GFORCE / SINT16_MAX * GRAVITY_CONSTANT *
slouken@3277
    59
        MILLESECONDS_PER_FRAME;
slouken@3277
    60
slouken@3690
    61
    float speed = sqrt(shipData.vx * shipData.vx + shipData.vy * shipData.vy);
slouken@3277
    62
slouken@3277
    63
    if (speed > 0) {
slouken@3277
    64
        /* compensate for friction */
slouken@3690
    65
        float dirx = shipData.vx / speed;   /* normalized x velocity */
slouken@3690
    66
        float diry = shipData.vy / speed;   /* normalized y velocity */
slouken@3277
    67
slouken@3277
    68
        /* update velocity due to friction */
slouken@3277
    69
        if (speed - FRICTION * MILLESECONDS_PER_FRAME > 0) {
slouken@3277
    70
            /* apply friction */
slouken@3690
    71
            shipData.vx -= dirx * FRICTION * MILLESECONDS_PER_FRAME;
slouken@3690
    72
            shipData.vy -= diry * FRICTION * MILLESECONDS_PER_FRAME;
slouken@3277
    73
        } else {
slouken@3277
    74
            /* applying friction would MORE than stop the ship, so just stop the ship */
slouken@3690
    75
            shipData.vx = 0.0f;
slouken@3690
    76
            shipData.vy = 0.0f;
slouken@3277
    77
        }
slouken@3277
    78
    }
slouken@3277
    79
slouken@3277
    80
    /* update ship location */
slouken@3690
    81
    shipData.x += shipData.vx * MILLESECONDS_PER_FRAME;
slouken@3690
    82
    shipData.y += shipData.vy * MILLESECONDS_PER_FRAME;
slouken@3277
    83
slouken@3690
    84
    if (shipData.x > maxx) {
slouken@3690
    85
        shipData.x = maxx;
slouken@3690
    86
        shipData.vx = -shipData.vx * DAMPING;
slouken@3690
    87
    } else if (shipData.x < minx) {
slouken@3690
    88
        shipData.x = minx;
slouken@3690
    89
        shipData.vx = -shipData.vx * DAMPING;
slouken@3277
    90
    }
slouken@3690
    91
    if (shipData.y > maxy) {
slouken@3690
    92
        shipData.y = maxy;
slouken@3690
    93
        shipData.vy = -shipData.vy * DAMPING;
slouken@3690
    94
    } else if (shipData.y < miny) {
slouken@3690
    95
        shipData.y = miny;
slouken@3690
    96
        shipData.vy = -shipData.vy * DAMPING;
slouken@3277
    97
    }
slouken@3277
    98
slouken@3277
    99
    /* draw the background */
slouken@5208
   100
    SDL_RenderCopy(renderer, space, NULL, NULL);
slouken@3277
   101
slouken@3277
   102
    /* draw the ship */
slouken@3690
   103
    shipData.rect.x = shipData.x;
slouken@3690
   104
    shipData.rect.y = shipData.y;
slouken@3277
   105
slouken@5208
   106
    SDL_RenderCopy(renderer, ship, NULL, &shipData.rect);
slouken@3277
   107
slouken@3277
   108
    /* update screen */
slouken@5208
   109
    SDL_RenderPresent(renderer);
slouken@3277
   110
slouken@3277
   111
}
slouken@3277
   112
slouken@3277
   113
void
slouken@5208
   114
initializeTextures(SDL_Renderer *renderer)
slouken@3277
   115
{
slouken@3277
   116
slouken@3277
   117
    SDL_Surface *bmp_surface;
slouken@3277
   118
slouken@3277
   119
    /* load the ship */
slouken@3277
   120
    bmp_surface = SDL_LoadBMP("ship.bmp");
slouken@3277
   121
    if (bmp_surface == NULL) {
slouken@3277
   122
        fatalError("could not ship.bmp");
slouken@3277
   123
    }
slouken@3277
   124
    /* set blue to transparent on the ship */
slouken@3277
   125
    SDL_SetColorKey(bmp_surface, 1,
slouken@3277
   126
                    SDL_MapRGB(bmp_surface->format, 0, 0, 255));
slouken@3277
   127
slouken@3277
   128
    /* create ship texture from surface */
slouken@5208
   129
    ship = SDL_CreateTextureFromSurface(renderer, bmp_surface);
slouken@3685
   130
    if (ship == 0) {
slouken@3277
   131
        fatalError("could not create ship texture");
slouken@3277
   132
    }
slouken@3685
   133
    SDL_SetTextureBlendMode(ship, SDL_BLENDMODE_BLEND);
slouken@3277
   134
slouken@3277
   135
    /* set the width and height of the ship from the surface dimensions */
slouken@3690
   136
    shipData.rect.w = bmp_surface->w;
slouken@3690
   137
    shipData.rect.h = bmp_surface->h;
slouken@3277
   138
slouken@3277
   139
    SDL_FreeSurface(bmp_surface);
slouken@3277
   140
slouken@3277
   141
    /* load the space background */
slouken@3277
   142
    bmp_surface = SDL_LoadBMP("space.bmp");
slouken@3277
   143
    if (bmp_surface == NULL) {
slouken@3277
   144
        fatalError("could not load space.bmp");
slouken@3277
   145
    }
slouken@3277
   146
    /* create space texture from surface */
slouken@5208
   147
    space = SDL_CreateTextureFromSurface(renderer, bmp_surface);
slouken@3685
   148
    if (space == 0) {
slouken@3277
   149
        fatalError("could not create space texture");
slouken@3277
   150
    }
slouken@3277
   151
    SDL_FreeSurface(bmp_surface);
slouken@3277
   152
slouken@3277
   153
}
slouken@3277
   154
slouken@3277
   155
slouken@3277
   156
slouken@3277
   157
int
slouken@3277
   158
main(int argc, char *argv[])
slouken@3277
   159
{
slouken@3277
   160
slouken@3685
   161
    SDL_Window *window;         /* main window */
slouken@5208
   162
	SDL_Renderer *renderer;
slouken@3277
   163
    Uint32 startFrame;          /* time frame began to process */
slouken@3277
   164
    Uint32 endFrame;            /* time frame ended processing */
slouken@3277
   165
    Uint32 delay;               /* time to pause waiting to draw next frame */
slouken@3277
   166
    int done;                   /* should we clean up and exit? */
slouken@3277
   167
slouken@3277
   168
    /* initialize SDL */
slouken@3277
   169
    if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK) < 0) {
slouken@3277
   170
        fatalError("Could not initialize SDL");
slouken@3277
   171
    }
slouken@3277
   172
slouken@3277
   173
    /* create main window and renderer */
slouken@3685
   174
    window = SDL_CreateWindow(NULL, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT,
slouken@3277
   175
                                SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN |
slouken@3277
   176
                                SDL_WINDOW_BORDERLESS);
slouken@5208
   177
    renderer = SDL_CreateRenderer(window, 0, 0);
slouken@3277
   178
slouken@3277
   179
    /* print out some info about joysticks and try to open accelerometer for use */
slouken@3277
   180
    printf("There are %d joysticks available\n", SDL_NumJoysticks());
slouken@3277
   181
    printf("Default joystick (index 0) is %s\n", SDL_JoystickName(0));
slouken@3277
   182
    accelerometer = SDL_JoystickOpen(0);
slouken@3277
   183
    if (accelerometer == NULL) {
slouken@3277
   184
        fatalError("Could not open joystick (accelerometer)");
slouken@3277
   185
    }
slouken@3277
   186
    printf("joystick number of axis = %d\n",
slouken@3277
   187
           SDL_JoystickNumAxes(accelerometer));
slouken@3277
   188
    printf("joystick number of hats = %d\n",
slouken@3277
   189
           SDL_JoystickNumHats(accelerometer));
slouken@3277
   190
    printf("joystick number of balls = %d\n",
slouken@3277
   191
           SDL_JoystickNumBalls(accelerometer));
slouken@3277
   192
    printf("joystick number of buttons = %d\n",
slouken@3277
   193
           SDL_JoystickNumButtons(accelerometer));
slouken@3277
   194
slouken@3277
   195
    /* load graphics */
slouken@5208
   196
    initializeTextures(renderer);
slouken@3277
   197
slouken@3277
   198
    /* setup ship */
slouken@3690
   199
    shipData.x = (SCREEN_WIDTH - shipData.rect.w) / 2;
slouken@3690
   200
    shipData.y = (SCREEN_HEIGHT - shipData.rect.h) / 2;
slouken@3690
   201
    shipData.vx = 0.0f;
slouken@3690
   202
    shipData.vy = 0.0f;
slouken@3277
   203
slouken@3277
   204
    done = 0;
slouken@3277
   205
    /* enter main loop */
slouken@3277
   206
    while (!done) {
slouken@3277
   207
        startFrame = SDL_GetTicks();
slouken@3277
   208
        SDL_Event event;
slouken@3277
   209
        while (SDL_PollEvent(&event)) {
slouken@3277
   210
            if (event.type == SDL_QUIT) {
slouken@3277
   211
                done = 1;
slouken@3277
   212
            }
slouken@3277
   213
        }
slouken@5208
   214
        render(renderer);
slouken@3277
   215
        endFrame = SDL_GetTicks();
slouken@3277
   216
slouken@3277
   217
        /* figure out how much time we have left, and then sleep */
slouken@3277
   218
        delay = MILLESECONDS_PER_FRAME - (endFrame - startFrame);
slouken@3277
   219
        if (delay < 0) {
slouken@3277
   220
            delay = 0;
slouken@3277
   221
        } else if (delay > MILLESECONDS_PER_FRAME) {
slouken@3277
   222
            delay = MILLESECONDS_PER_FRAME;
slouken@3277
   223
        }
slouken@3277
   224
        SDL_Delay(delay);
slouken@3277
   225
    }
slouken@3277
   226
slouken@3277
   227
    /* delete textures */
slouken@3685
   228
    SDL_DestroyTexture(ship);
slouken@3685
   229
    SDL_DestroyTexture(space);
slouken@3277
   230
slouken@3277
   231
    /* shutdown SDL */
slouken@3277
   232
    SDL_Quit();
slouken@3277
   233
slouken@3277
   234
    return 0;
slouken@3277
   235
slouken@3277
   236
}