ohsp

Prototype for a game with dual thruster controls.
git clone git://git.amin.space/ohsp.git
Log | Files | Refs | LICENSE

game.c (12939B)


      1 #include "game.h"
      2 // TODO: remove this
      3 #include <math.h>
      4 #include <stdlib.h>
      5 
      6 #include <assert.h>
      7 #include <stdbool.h>
      8 #include <stdio.h>
      9 
     10 // TODO: move this into the gamestate struct
     11 bool PAUSED = false;
     12 
     13 
     14 // TODO: move to util
     15 float rand_float(float min, float max)
     16 {
     17     assert(min < max);
     18     float random = ((float) rand()) / (float) RAND_MAX;
     19     float diff = max - min;
     20     float r = random * diff;
     21     return min + r;
     22 }
     23 
     24 
     25 void game_init(struct GameState *game_state, int field_width, int field_height)
     26 {
     27     if (!game_state)
     28     {
     29         // TODO: handle invalid pointer error
     30         return;
     31     }
     32 
     33     game_state->player.mass = 10;
     34     game_state->player.size = 20;
     35     game_state->player.color = 0x888888;
     36     game_state->player.position.x = field_width / 2;
     37     game_state->player.position.y = field_height / 2;
     38     game_state->player.velocity.x = 0;
     39     game_state->player.velocity.y = 0;
     40 
     41     game_state->thrust_vector01.x = 0;
     42     game_state->thrust_vector01.y = 0;
     43     game_state->thrust_vector02.x = 0;
     44     game_state->thrust_vector02.y = 0;
     45     game_state->thrust_vector_sum.x = 0;
     46     game_state->thrust_vector_sum.y = 0;
     47 
     48     game_state->view.dx = 0;
     49     game_state->view.dy = 0;
     50     game_state->view.zoom = 1;
     51 
     52     // TODO: change to calloc?
     53     game_state->entities = malloc(sizeof (struct Entities));
     54     assert(game_state->entities);
     55     game_state->entities->num_entities = ENTITIES_MAX;
     56     assert(game_state->entities->num_entities == ENTITIES_MAX);
     57 
     58     {
     59         float max_speed = 0.3f;
     60         for (uint32_t i = 0; i < game_state->entities->num_entities; ++i)
     61         {
     62             game_state->entities->physics[i].mass = 10.0f;
     63             game_state->entities->physics[i].velocity.x = rand_float(-max_speed, max_speed);
     64             game_state->entities->physics[i].velocity.y = rand_float(-max_speed, max_speed);
     65             game_state->entities->positions[i].x = rand() % field_width;
     66             game_state->entities->positions[i].y = rand() % field_height;
     67             game_state->entities->render[i].color = 0xFFFFFF;
     68             game_state->entities->render[i].size = 10.0f;
     69         }
     70     }
     71 }
     72 
     73 
     74 // TODO: move to util
     75 float wrap(float n, float min, float max)
     76 {
     77     if (n > max)
     78     {
     79         return min;
     80     }
     81     else if (n < min)
     82     {
     83         return max;
     84     }
     85     else
     86     {
     87         return n;
     88     }
     89 }
     90 
     91 
     92 void game_update(struct GameState *game_state, struct GameControllerInput game_input, int field_width, int field_height)
     93 {
     94     if (!game_state)
     95     {
     96         // TODO: handle invalid pointer error
     97         return;
     98     }
     99 
    100     game_state->thrust_vector01.x = game_input.left_stick_x;
    101     game_state->thrust_vector01.y = game_input.left_stick_y;
    102     //printf("(lx: %f, ly: %f, thrust_x: %f, thrust_y: %f)\n", game_input.left_stick_x, game_input.left_stick_y, game_state->thrust_vector01.x, game_state->thrust_vector01.y);
    103 
    104     game_state->thrust_vector02.x = game_input.right_stick_x;
    105     game_state->thrust_vector02.y = game_input.right_stick_y;
    106     //printf("(rx: %f, ry: %f, thrust_x: %f, thrust_y: %f)\n", game_input.right_stick_x, game_input.right_stick_y, game_state->thrust_vector02.x, game_state->thrust_vector02.y);
    107 
    108     game_state->thrust_vector_sum = vec2d_add(
    109             vec2d_negate(game_state->thrust_vector01),
    110             vec2d_negate(game_state->thrust_vector02));
    111     game_state->thrust_vector_sum = vec2d_scale(game_state->thrust_vector_sum, 0.01f);
    112     //printf("(total_thrust_x: %f, total_thrust_y: %f)\n", game_state->thrust_vector_sum.x, game_state->thrust_vector_sum.y);
    113 
    114     struct Entity *player = &game_state->player;
    115     entity_accelerate(player, &game_state->thrust_vector_sum);
    116 
    117     player->position.x += player->velocity.x;
    118     player->position.y += player->velocity.y;
    119     player->position.x = wrap(player->position.x, 0, field_width);
    120     player->position.y = wrap(player->position.y, 0, field_height);
    121 
    122     { // other entities
    123         for (size_t i = 0; i < game_state->entities->num_entities; ++i)
    124         {
    125             game_state->entities->positions[i].x += game_state->entities->physics[i].velocity.x;
    126             game_state->entities->positions[i].y += game_state->entities->physics[i].velocity.y;
    127             game_state->entities->positions[i].x = wrap(game_state->entities->positions[i].x, 0, field_width);
    128             game_state->entities->positions[i].y = wrap(game_state->entities->positions[i].y, 0, field_height);
    129         }
    130     }
    131 }
    132 
    133 
    134 void game_render(struct OffscreenBuffer *buffer, float dt, struct GameState *game_state)
    135 {
    136     if (!buffer || !game_state)
    137     {
    138         // TODO: handle invalid pointer error
    139         return;
    140     }
    141     struct Entity player = game_state->player;
    142     game_render_circle(buffer, player.position.x, player.position.y, player.size, player.color);
    143     game_render_vector(buffer, &game_state->thrust_vector01, player.position.x, player.position.y, 5, 0x0000FF);
    144     game_render_vector(buffer, &game_state->thrust_vector02, player.position.x, player.position.y, 5, 0xFF0000);
    145     game_render_vector(buffer, &game_state->thrust_vector_sum, player.position.x, player.position.y, 5, 0xFF00FF);
    146 
    147     struct Vec2d player_vec = vec2d_scale(player.velocity, 100);
    148     game_render_circle(buffer,
    149             player.position.x + player_vec.x,
    150             player.position.y + player_vec.y,
    151             5,
    152             0x00FF00);
    153 
    154     for (size_t i = 0; i < game_state->entities->num_entities; ++i)
    155     {
    156         game_set_pixel(buffer,
    157                 game_state->entities->positions[i].x,
    158                 game_state->entities->positions[i].y,
    159                 game_state->entities->render[i].color);
    160     }
    161 }
    162 
    163 
    164 void game_render_circle(struct OffscreenBuffer *buffer, float center_x, float center_y, float radius, uint32_t color)
    165 {
    166     for(int y = -radius; y <= radius; y++)
    167     {
    168         for(int x = -radius; x <= radius; x++)
    169         {
    170             if(x * x + y * y <= radius * radius)
    171             {
    172                 game_set_pixel(buffer, center_x + x, center_y + y, color);
    173             }
    174         }
    175     }
    176 }
    177 
    178 
    179 void game_render_line(struct OffscreenBuffer *buffer, float x0, float y0, float x1, float y1, uint32_t color)
    180 {
    181     float delta_x = x1 - x0;
    182     float delta_y = y1 - y0;
    183 
    184     if (0.0f == delta_x) // vertical
    185     {
    186         for (int y = fminf(y0, y1); y <= fmaxf(y0, y1); ++y)
    187         {
    188             game_set_pixel(buffer, x0, y, color);
    189         }
    190     }
    191     else if (0.0f == delta_y) // horizontal
    192     {
    193         for (int x = fminf(x0, x1); x <= fmaxf(x0, x1); ++x)
    194         {
    195             game_set_pixel(buffer, x, y0, color);
    196         }
    197     }
    198     else
    199     {
    200         bool quadrant_01 = (delta_x > 0.0f && delta_y <= 0.0f);
    201         bool quadrant_02 = (delta_x <= 0.0f && delta_y < 0.0f);
    202         bool quadrant_03 = (delta_x < 0.0f && delta_y >= 0.0f);
    203         bool quadrant_04 = (delta_x >= 0.0f && delta_y > 0.0f);
    204         bool bigger_delta_x = fabsf(delta_x) >= fabsf(delta_y);
    205         bool bigger_delta_y = !bigger_delta_x;
    206 
    207         if(bigger_delta_x && quadrant_01)
    208         {
    209             // octant 1
    210             // Bresenham's line algorithm
    211             assert(0.0f != delta_x);
    212             float delta_err = fabsf(delta_y / delta_x);
    213             float error = 0.0f;
    214             int y = y0;
    215             for (int x = x0; x <= x1; ++x)
    216             {
    217                 game_set_pixel(buffer, x, y, color);
    218                 error += delta_err;
    219                 if (error >= 0.5f)
    220                 {
    221                     y -= 1;
    222                     error -= 1.0f;
    223                 }
    224             }
    225         }
    226         else if (bigger_delta_x && quadrant_02)
    227         {
    228             // octant 4
    229             // Bresenham's line algorithm
    230             assert(0.0f != delta_x);
    231             float delta_err = fabsf(delta_y / delta_x);
    232             float error = 0.0f;
    233             int y = y0;
    234             for (int x = x0; x >= x1; --x)
    235             {
    236                 game_set_pixel(buffer, x, y, color);
    237                 error += delta_err;
    238                 if (error >= 0.5f)
    239                 {
    240                     y -= 1;
    241                     error -= 1.0f;
    242                 }
    243             }
    244         }
    245         else if (bigger_delta_x && quadrant_03)
    246         {
    247             // octant 5
    248             // Bresenham's line algorithm
    249             assert(0.0f != delta_x);
    250             float delta_err = fabsf(delta_y / delta_x);
    251             float error = 0.0f;
    252             int y = y0;
    253             for (int x = x0; x >= x1; --x)
    254             {
    255                 game_set_pixel(buffer, x, y, color);
    256                 error += delta_err;
    257                 if (error >= 0.5f)
    258                 {
    259                     y += 1;
    260                     error -= 1.0f;
    261                 }
    262             }
    263         }
    264         else if (bigger_delta_x && quadrant_04)
    265         {
    266             // octant 8
    267             // Bresenham's line algorithm
    268             assert(0.0f != delta_x);
    269             float delta_err = fabsf(delta_y / delta_x);
    270             float error = 0.0f;
    271             int y = y0;
    272             for (int x = x0; x <= x1; ++x)
    273             {
    274                 game_set_pixel(buffer, x, y, color);
    275                 error += delta_err;
    276                 if (error >= 0.5f)
    277                 {
    278                     y += 1;
    279                     error -= 1.0f;
    280                 }
    281             }
    282         }
    283         else if (bigger_delta_y && quadrant_01)
    284         {
    285             // octant 2
    286             // Bresenham's line algorithm
    287             assert(0.0f != delta_y);
    288             float delta_err = fabsf(delta_x / delta_y);
    289             float error = 0.0f;
    290             int x = x0;
    291             for (int y = y0; y >= y1; --y)
    292             {
    293                 game_set_pixel(buffer, x, y, color);
    294                 error += delta_err;
    295                 if (error >= 0.5f)
    296                 {
    297                     x += 1;
    298                     error -= 1.0f;
    299                 }
    300             }
    301         }
    302         else if (bigger_delta_y && quadrant_02)
    303         {
    304             // octant 3
    305             // Bresenham's line algorithm
    306             assert(0.0f != delta_y);
    307             float delta_err = fabsf(delta_x / delta_y);
    308             float error = 0.0f;
    309             int x = x0;
    310             for (int y = y0; y >= y1; --y)
    311             {
    312                 game_set_pixel(buffer, x, y, color);
    313                 error += delta_err;
    314                 if (error >= 0.5f)
    315                 {
    316                     x -= 1;
    317                     error -= 1.0f;
    318                 }
    319             }
    320         }
    321         else if (bigger_delta_y && quadrant_03)
    322         {
    323             // octant 6
    324             // Bresenham's line algorithm
    325             assert(0.0f != delta_y);
    326             float delta_err = fabsf(delta_x / delta_y);
    327             float error = 0.0f;
    328             int x = x0;
    329             for (int y = y0; y <= y1; ++y)
    330             {
    331                 game_set_pixel(buffer, x, y, color);
    332                 error += delta_err;
    333                 if (error >= 0.5f)
    334                 {
    335                     x -= 1;
    336                     error -= 1.0f;
    337                 }
    338             }
    339         }
    340         else if (bigger_delta_y && quadrant_04)
    341         {
    342             // octant 7
    343             // Bresenham's line algorithm
    344             assert(0.0f != delta_y);
    345             float delta_err = fabsf(delta_x / delta_y);
    346             float error = 0.0f;
    347             int x = x0;
    348             for (int y = y0; y <= y1; ++y)
    349             {
    350                 game_set_pixel(buffer, x, y, color);
    351                 error += delta_err;
    352                 if (error >= 0.5f)
    353                 {
    354                     x += 1;
    355                     error -= 1.0f;
    356                 }
    357             }
    358         }
    359         else
    360         {
    361             printf("ERROR: Your vector is as some angle you didn't catch!!!");
    362         }
    363     }
    364 }
    365 
    366 
    367 void game_render_vector(struct OffscreenBuffer *buffer, struct Vec2d *v, float x0, float y0, float radius, uint32_t color)
    368 {
    369     struct Vec2d vec = vec2d_scale(*v, 100);
    370     vec = vec2d_add_c(x0, y0, vec.x, vec.y);
    371     game_render_line(buffer, x0, y0, vec.x, vec.y, color);
    372     game_render_circle(buffer, vec.x, vec.y, radius, color);
    373 }
    374 
    375 
    376 void game_set_pixel(struct OffscreenBuffer *buffer, uint32_t x, uint32_t y, uint32_t color)
    377 {
    378     if (!buffer)
    379     {
    380         // TODO: handle invalid pointer error
    381         return;
    382     }
    383 
    384     /* Origin is (0, 0) on the upper left.
    385      * To go one pixel right, increment by 32 bits.
    386      * To go one pixel down, increment by (buffer.width * 32) bits.
    387      */
    388     if (x < buffer->width && y < buffer->height)
    389     {
    390         uint8_t *pixel_pos = (uint8_t *)buffer->memory;
    391         pixel_pos += ((BYTES_PER_PIXEL*x) + (buffer->pitch * y));
    392         uint32_t *pixel = (uint32_t *)pixel_pos;
    393         *pixel = color;
    394     }
    395 }
    396 
    397 
    398 float game_calc_render_offset(float zoom, float delta, float pos, float center)
    399 {
    400     return ((1 - zoom) * center) + (pos + delta) * zoom;
    401 }
    402 
    403 
    404 void game_cleanup(struct GameState *game_state)
    405 {
    406     if (!game_state)
    407     {
    408         // TODO: handle invalid pointer error
    409         return;
    410     }
    411     free(game_state->entities);
    412 }