cscg22-gearboy

CSCG 2022 Challenge 'Gearboy'
git clone https://git.sinitax.com/sinitax/cscg22-gearboy
Log | Files | Refs | sfeed.txt

accelerometer.c (7459B)


      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
     21static SDL_Joystick *accelerometer;     /* used for controlling the ship */
     22
     23static 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
     30static SDL_Texture *ship = 0;        /* texture for spaceship */
     31static SDL_Texture *space = 0;       /* texture for space (background */
     32
     33void
     34render(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
    113void
    114initializeTextures(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
    157int
    158main(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_FULLSCREEN);
    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}