165 asc_active_window->dimensions.y - ((AscText*)node)->dimension.height - 10 |
164 asc_active_window->dimensions.y - ((AscText*)node)->dimension.height - 10 |
166 )); |
165 )); |
167 } |
166 } |
168 } |
167 } |
169 |
168 |
170 static void fps_counter_create(void) { |
169 static AscSceneNode *fps_counter_create(void) { |
171 AscSceneNode *node = asc_text( |
170 AscSceneNode *node = asc_text( |
172 .name = "FPS Counter", |
171 .name = "FPS Counter", |
173 .color = ASC_RGB(1, 1, 1), |
172 .color = ASC_RGB(1, 1, 1), |
174 .font = asc_font(ASC_FONT_REGULAR, 12), |
173 .font = asc_font(ASC_FONT_REGULAR, 12), |
175 ); |
174 ); |
176 asc_behavior_add(node, .func = fps_counter_update, .interval = asc_seconds(1)); |
175 asc_behavior_add(node, .func = fps_counter_update, .interval = asc_seconds(1)); |
177 asc_behavior_add(node, fps_counter_tie_to_corner); |
176 asc_behavior_add(node, fps_counter_tie_to_corner); |
178 asc_ui_add_node(node); |
177 asc_ui_add_node(node); |
|
178 return node; |
179 } |
179 } |
180 |
180 |
181 |
181 |
182 static GameField *game_field; |
182 static GameField *game_field; |
183 |
183 |
194 } |
194 } |
195 int new_owner = game_field->tile_data[x][y] & GAME_FIELD_TILE_OWNER_MASK; |
195 int new_owner = game_field->tile_data[x][y] & GAME_FIELD_TILE_OWNER_MASK; |
196 return old_owner != new_owner; |
196 return old_owner != new_owner; |
197 } |
197 } |
198 |
198 |
199 static void game_field_create() { |
199 static GameField *game_field_create() { |
200 // TODO: create a more interesting map than just a basic grid |
200 // TODO: create a more interesting map than just a basic grid |
201 AscSceneNode *node = asc_scene_node_empty(); |
201 AscSceneNode *node = asc_scene_node_empty(); |
202 game_field = asc_scene_node_allocate_data(node, sizeof(GameField)); |
202 game_field = asc_scene_node_allocate_data(node, sizeof(GameField)); |
203 for (unsigned x = 0; x < GAME_FIELD_SIZE; x++) { |
203 for (unsigned x = 0; x < GAME_FIELD_SIZE; x++) { |
204 for (unsigned y = 0; y < GAME_FIELD_SIZE; y++) { |
204 for (unsigned y = 0; y < GAME_FIELD_SIZE; y++) { |
215 asc_scene_node_link(node, tile); |
215 asc_scene_node_link(node, tile); |
216 } |
216 } |
217 } |
217 } |
218 asc_scene_node_set_zindex(node, -2); |
218 asc_scene_node_set_zindex(node, -2); |
219 asc_scene_add_node(MAIN_SCENE, node); |
219 asc_scene_add_node(MAIN_SCENE, node); |
|
220 return game_field; |
220 } |
221 } |
221 |
222 |
222 static asc_vec2u game_field_tile_at_position(asc_vec3f position) { |
223 static asc_vec2u game_field_tile_at_position(asc_vec3f position) { |
223 return ASC_VEC2U((int)position.x / GAME_FIELD_TILE_SIZE, (int)position.y / GAME_FIELD_TILE_SIZE); |
224 return ASC_VEC2U((int)position.x / GAME_FIELD_TILE_SIZE, (int)position.y / GAME_FIELD_TILE_SIZE); |
224 } |
225 } |
344 } |
345 } |
345 } |
346 } |
346 } |
347 } |
347 } |
348 } |
348 |
349 |
|
350 static void player_controls(Player *player) { |
|
351 if (asc_key_pressed(ASC_KEY(LEFT))) { |
|
352 if (player->direction != MOVE_RIGHT) { |
|
353 player->target_direction = MOVE_LEFT; |
|
354 } |
|
355 } |
|
356 if (asc_key_pressed(ASC_KEY(RIGHT))) { |
|
357 if (player->direction != MOVE_LEFT) { |
|
358 player->target_direction = MOVE_RIGHT; |
|
359 } |
|
360 } |
|
361 if (asc_key_pressed(ASC_KEY(UP))) { |
|
362 if (player->direction != MOVE_DOWN) { |
|
363 player->target_direction = MOVE_UP; |
|
364 } |
|
365 } |
|
366 if (asc_key_pressed(ASC_KEY(DOWN))) { |
|
367 if (player->direction != MOVE_UP) { |
|
368 player->target_direction = MOVE_DOWN; |
|
369 } |
|
370 } |
|
371 } |
|
372 |
349 static void player_position(Player *pl, int x, int y) { |
373 static void player_position(Player *pl, int x, int y) { |
350 pl->new_position.x = x; |
374 pl->new_position.x = x; |
351 pl->new_position.y = y; |
375 pl->new_position.y = y; |
352 pl->reset_position = true; |
376 pl->reset_position = true; |
353 } |
377 } |
413 |
437 |
414 // Set the viewport to the scaled and centered region |
438 // Set the viewport to the scaled and centered region |
415 return ASC_RECT(offset_x, offset_y, viewport_size, viewport_size); |
439 return ASC_RECT(offset_x, offset_y, viewport_size, viewport_size); |
416 } |
440 } |
417 |
441 |
|
442 #define GAME_STATE_MENU 0 |
|
443 #define GAME_STATE_PLAYING 1 |
|
444 #define GAME_STATE_GAME_OVER 2 |
|
445 |
|
446 typedef struct { |
|
447 int state; |
|
448 GameField *field; |
|
449 Player *players[4]; |
|
450 } GameState; |
|
451 |
418 int main(void) { |
452 int main(void) { |
419 asc_context_initialize(); |
453 asc_context_initialize(); |
420 if (asc_has_error()) { |
454 if (asc_has_error()) { |
421 SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, |
455 SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, |
422 "Fatal Error",asc_get_error(), NULL); |
456 "Fatal Error",asc_get_error(), NULL); |
451 ), |
485 ), |
452 .viewport_clear = true, |
486 .viewport_clear = true, |
453 .clear_color = ASC_RGBi(0, 32, 16), |
487 .clear_color = ASC_RGBi(0, 32, 16), |
454 .viewport_update_func = main_scene_viewport_update |
488 .viewport_update_func = main_scene_viewport_update |
455 ); |
489 ); |
456 |
|
457 // backdrop for letterbox/pillarbox |
|
458 backdrop_create(); |
490 backdrop_create(); |
459 |
491 |
460 // the game field |
492 // create the fps counter |
461 game_field_create(); |
493 AscSceneNode *fps_counter = fps_counter_create(); |
462 |
494 asc_scene_node_hide(fps_counter); |
463 // create UI elements |
495 |
464 fps_counter_create(); |
496 // create the game state |
465 |
497 GameState game = {0}; |
466 // create player |
498 // TODO: add a main menu and start with the menu |
467 Player *player = player_create(); |
499 game.state = GAME_STATE_PLAYING; |
|
500 game.field = game_field_create(); |
|
501 game.players[0] = player_create(); |
468 |
502 |
469 // Main Loop |
503 // Main Loop |
470 do { |
504 do { |
471 // quit application on any error |
505 // quit application on any error |
472 if (asc_has_error()) { |
506 if (asc_has_error()) { |
475 asc_active_window->window); |
509 asc_active_window->window); |
476 asc_clear_error(); |
510 asc_clear_error(); |
477 asc_context_quit(); |
511 asc_context_quit(); |
478 } |
512 } |
479 |
513 |
480 // player rotation |
514 // game states |
481 if (asc_key_pressed(ASC_KEY(LEFT))) { |
515 if (game.state == GAME_STATE_PLAYING) { |
482 if (player->direction != MOVE_RIGHT) { |
516 // TODO: implement hot seat 1on1 multiplayer |
483 player->target_direction = MOVE_LEFT; |
517 player_controls(game.players[0]); |
484 } |
|
485 } |
|
486 if (asc_key_pressed(ASC_KEY(RIGHT))) { |
|
487 if (player->direction != MOVE_LEFT) { |
|
488 player->target_direction = MOVE_RIGHT; |
|
489 } |
|
490 } |
|
491 if (asc_key_pressed(ASC_KEY(UP))) { |
|
492 if (player->direction != MOVE_DOWN) { |
|
493 player->target_direction = MOVE_UP; |
|
494 } |
|
495 } |
|
496 if (asc_key_pressed(ASC_KEY(DOWN))) { |
|
497 if (player->direction != MOVE_UP) { |
|
498 player->target_direction = MOVE_DOWN; |
|
499 } |
|
500 } |
518 } |
501 |
519 |
502 // debug-key for clearing the shader registry |
520 // debug-key for clearing the shader registry |
503 if (asc_key_pressed(ASC_KEY(S))) { |
521 if (asc_key_pressed(ASC_KEY(S))) { |
504 asc_shader_clear_registry(); |
522 asc_shader_clear_registry(); |
505 asc_dprintf("Shader cache cleared."); |
523 asc_dprintf("Shader cache cleared."); |
506 } |
524 } |
507 |
525 |
|
526 // show/hide the FPS counter |
|
527 if (asc_key_pressed(ASC_KEY(F2))) { |
|
528 asc_scene_node_toggle_visibility(fps_counter); |
|
529 } |
|
530 |
508 // quit application on ESC key press |
531 // quit application on ESC key press |
509 if (asc_key_pressed(ASC_KEY(ESCAPE))) { |
532 if (asc_key_pressed(ASC_KEY(ESCAPE))) { |
510 asc_context_quit(); |
533 asc_context_quit(); |
511 } |
534 } |
512 } while (asc_loop_next()); |
535 } while (asc_loop_next()); |