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