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 }