#include "player.h" #include "game.h" Player createPlayer() { return (Player){ .position = Vector3Zero(), .direction = (Vector3){0.0, 0.0, 0.0}, .velocity = Vector3Zero(), .camera = (Camera){ .position = (Vector3){0.0, 0.0, 0.0}, .target = Vector3Zero(), .up = (Vector3){0.0, 1.0, 0.0}, .fovy = 90.0, .projection = CAMERA_PERSPECTIVE }, .cameraAngle = Vector2Zero(), .selectedEntity = ENTITY_NONE, .isInteracting = false }; } // Fake physics, distance from ground. void updatePlayerHeight(Player* player, Game* game) { float height = getWorldHeightAtLocation( &game->world, player->position.x, player->position.z) + PLAYER_HEIGHT; player->position.y = height; } void updatePlayerLookingAround(Player* player, Game* game) { Settings* settings = &game->settings; Vector2* cameraAngle = &player->cameraAngle; // Get mouse speed. Vector2 mouseSpeed = Vector2Scale(GetMouseDelta(), settings->mouseSpeed); mouseSpeed = Vector2Scale(mouseSpeed, 1.0 / (PI * 2.0)); // Update camera angle. *cameraAngle = Vector2Add(*cameraAngle, mouseSpeed); cameraAngle->x = Wrap(cameraAngle->x, -PI, PI); cameraAngle->y = Clamp(cameraAngle->y, -PI / 2.5, PI / 2.5); // Set player direction. Matrix matrix = MatrixRotateXYZ( (Vector3){-cameraAngle->y, cameraAngle->x, 0.0}); player->direction = (Vector3){matrix.m2, matrix.m6, matrix.m10}; } void updatePlayerMovement(Player* player, Game* game) { Camera* camera = &player->camera; Vector2* cameraAngle = &player->cameraAngle; Settings* settings = &game->settings; if (!game->isCursorEnabled) { updatePlayerLookingAround(player, game); } // Walking around. player->velocity = Vector3Zero(); if (IsKeyDown(settings->forwardKey)) { player->velocity.z += cosf(cameraAngle->x); player->velocity.x += -sinf(cameraAngle->x); } if (IsKeyDown(settings->leftKey)) { player->velocity.z += cosf(cameraAngle->x - (PI / 2.0)); player->velocity.x += -sinf(cameraAngle->x - (PI / 2.0)); } if (IsKeyDown(settings->backwardKey)) { player->velocity.z += -cosf(cameraAngle->x); player->velocity.x += sinf(cameraAngle->x); } if (IsKeyDown(settings->rightKey)) { player->velocity.z += cosf(cameraAngle->x + (PI / 2.0)); player->velocity.x += -sinf(cameraAngle->x + (PI / 2.0)); } player->velocity = Vector3Scale(player->velocity, PLAYER_SPEED); // Apply velocity. player->position = Vector3Add( player->position, Vector3Scale(player->velocity, GetFrameTime())); updatePlayerHeight(player, game); // Apply camera. camera->position = player->position; camera->target = Vector3Add(player->position, player->direction); } bool playerCanEntityBeSelected(Player* player, Entity entity) { return getEntityDistance(entity, player->position) <= PLAYER_MAX_SELECT_DISTANCE; } void playerInteractWithEntity(Player* player, WorldUID uid, Game* game, Selection selection) { InteractionChat* chat = &game->chat; Entity* entity = &game->world.entities[uid]; // Handle selection type. switch (selection) { case SELECTION_INTERACT: clearInteractionChat(chat); chat->entityId = entity->id; player->selectedEntity = uid; player->isInteracting = true; break; case SELECTION_LEAVE: player->selectedEntity = ENTITY_NONE; player->isInteracting = false; chat->entityId = ENTITY_NONE; break; default: break; } // Interact with it. switch (interactWithEntity(entity, game, selection)) { case INTERACTION_TALK: showInteractionChat(chat); break; case INTERACTION_END: hideInteractionChat(chat); player->selectedEntity = ENTITY_NONE; player->isInteracting = false; chat->entityId = ENTITY_NONE; break; default: break; } } void playerUpdateSelectedEntity(Player* player, WorldUID uid, Game* game) { Entity* entity = &game->world.entities[uid]; // If the entity can be selected. if (!playerCanEntityBeSelected(player, *entity)) { // Leave interaction if far away. if (player->isInteracting) { playerInteractWithEntity(player, uid, game, SELECTION_LEAVE); } return; } player->selectedEntity = uid; // Draw outline. DrawBoundingBox(entity->box, player->isInteracting ? YELLOW : PINK); // Handle key presses. if (IsKeyPressed(game->settings.interactKey)) { playerInteractWithEntity(player, uid, game, SELECTION_INTERACT); } else if (IsKeyPressed(game->settings.nextMessageKey)) { playerInteractWithEntity(player, uid, game, SELECTION_NEXT_MESSAGE); } } void updatePlayer(Player* player, Game* game) { updatePlayerMovement(player, game); Ray ray = (Ray){ .position = player->position, .direction = player->direction }; if (game->isCrossHairEnabled) { DrawRay(ray, YELLOW); } if (player->isInteracting) { playerUpdateSelectedEntity(player, player->selectedEntity, game); } else { WorldUID uid = castRayAtWorld(&game->world, ray, false, NULL); if (uid == -1) { player->selectedEntity = ENTITY_NONE; } else { playerUpdateSelectedEntity(player, uid, game); } } }