#include "simulation_world.h" #include #include #include #define SIM_COMMANDS_PER_PLAYER 4 Simulation_World simulation_create_world(uint32_t seed, bool online, uint8_t max_players, uint16_t width, uint16_t height) { Simulation_World w; memset(&w, 0, sizeof(Simulation_World)); w.tick = 0; w.online = online; w.game_world = game_world_create(seed, width, height); assert(w.game_world != NULL); w.match_state = Simulation_Match_State_Waiting_To_Start; w.players = (Simulation_Player *)calloc(max_players, sizeof(Simulation_Player)); w.max_players = max_players; w.max_commands = w.max_players * SIM_COMMANDS_PER_PLAYER; w.command_count = 0; w.commands = (Simulation_Command *)calloc(w.max_commands, sizeof(Simulation_Command)); return w; } void simulation_destroy_world(Simulation_World *simulation_world) { assert(simulation_world != NULL); game_world_destroy(simulation_world->game_world); simulation_world->game_world = NULL; simulation_world->match_state = Simulation_Match_State_Waiting_To_Start; free(simulation_world->players); simulation_world->players = NULL; free(simulation_world->commands); simulation_world->commands = NULL; } void simulation_world_tick(Simulation_World *simulation_world) { assert(simulation_world != NULL); // printf("TICK: %lu.\n", simulation_world->tick); for(uint16_t i = 0; i < simulation_world->command_count; i++) { Simulation_Command *cmd = &simulation_world->commands[i]; // printf("Command type: %i, player id: %i.\n", cmd->type, cmd->player_id); Simulation_Player *player = &simulation_world->players[cmd->player_id]; assert(player != NULL); switch(cmd->type) { case Simulation_Command_Type_Add_Player: { // printf("Simulation_Command_Type_Add_Player\n"); assert(!player->active); player->active = true; Game_World *gw = simulation_world->game_world; assert(gw != NULL); uint16_t spawn_x = 0; uint16_t spawn_y = 0; assert(game_world_find_position_to_spawn(gw, &spawn_x, &spawn_y)); assert(game_world_create_entity( gw, Entity_Type_Snake_Head, spawn_x, spawn_y, &player->entity_id )); Entity *player_entity = game_world_try_get_entity_by_id(gw, player->entity_id); // Set initial move-direction for player-entities. player_entity->move_direction = game_world_choose_initial_move_direction_based_on_coords( gw, spawn_x, spawn_y ); break; } case Simulation_Command_Type_Remove_Player: { // printf("Simulation_Command_Type_Remove_Player\n"); assert(player->active); player->active = false; game_world_destroy_entity(simulation_world->game_world, player->entity_id, true); break; } case Simulation_Command_Type_Set_Player_Input: { // printf("Simulation_Command_Type_Set_Player_Input\n"); assert(player->active); player->input = cmd->player_input; break; } } } simulation_world->command_count = 0; switch(simulation_world->match_state) { case Simulation_Match_State_Waiting_To_Start: { if(!simulation_world->online) { // If not online, just go to Counting_Down. simulation_world->match_state = Simulation_Match_State_Counting_Down; } else { if(simulation_world_amount_of_active_players(simulation_world) > 1) { simulation_world->match_state = Simulation_Match_State_Counting_Down; } } break; } case Simulation_Match_State_Counting_Down: { if(simulation_world->tick > 20) { // TEMP: SS - Hardcoded number and condition to break out of this state. simulation_world->match_state = Simulation_Match_State_Active; } break; } case Simulation_Match_State_Active: { if(simulation_world->tick > 500) { // TEMP: SS - Hardcoded number and condition to break out of this state. simulation_world->match_state = Simulation_Match_State_Ended; } else { Game_World *gw = simulation_world->game_world; // Loop over all players in the simulation. for(uint16_t i = 0; i < simulation_world->max_players; i++) { Simulation_Player *player = &simulation_world->players[i]; if(!player->active) { continue; } // printf("* Input for player %i - up: %i, down: %i, right: %i, left: %i.\n", // i, // player->input.up, player->input.down, player->input.right, player->input.left // ); Entity *player_entity = game_world_try_get_entity_by_id(gw, player->entity_id); assert(player_entity != NULL); // Snakes can't go backwards. They have to turn. switch(player_entity->move_direction) { case Entity_Movement_Direction_None: { break; } case Entity_Movement_Direction_Up: case Entity_Movement_Direction_Down: // Snakes can only go right/left if it's currently moving up/down. { if(player->input.right) { player_entity->move_direction = Entity_Movement_Direction_Right; } else if(player->input.left) { player_entity->move_direction = Entity_Movement_Direction_Left; } break; } case Entity_Movement_Direction_Right: case Entity_Movement_Direction_Left: // Snakes can only go up/down if it's currently moving right/left. { if(player->input.up) { player_entity->move_direction = Entity_Movement_Direction_Up; } else if(player->input.down) { player_entity->move_direction = Entity_Movement_Direction_Down; } break; } } } game_world_tick(gw); } break; } case Simulation_Match_State_Ended: { printf("Match over!\n"); break; } } simulation_world->tick += 1; // TODO: SS - Stop ticking if match has ended. } bool simulation_world_enqueue_command(Simulation_World *simulation_world, Simulation_Command command) { assert(simulation_world != NULL); if(simulation_world->command_count >= simulation_world->max_commands) { return false; } simulation_world->commands[simulation_world->command_count] = command; simulation_world->command_count += 1; return true; } uint16_t simulation_world_amount_of_active_players(Simulation_World *simulation_world) { assert(simulation_world != NULL); uint16_t count = 0; for(uint16_t i = 0; i < simulation_world->max_players; i++) { Simulation_Player *player = &simulation_world->players[i]; if(player->active) { count += 1; } } return count; }