#include "imgui.h" #include "Player.h" #include #include "colors.h" #include "utils.h" #include "WorldLevel.h" #include "Animations/Animation.h" #include "GridSystem/WorldTile.h" Player::Player(const Point2f& Position, TextureManager* manager) : m_Position(Position), m_Size(Point2f { 40, 40 }), m_Vel(Point2f { 0, 0 }), m_Acc(Point2f { 0, 0 }) { m_ContactMap[Collision::CollisionDirection::Top] = nullptr; m_ContactMap[Collision::CollisionDirection::Bottom] = nullptr; m_ContactMap[Collision::CollisionDirection::Left] = nullptr; m_ContactMap[Collision::CollisionDirection::Right] = nullptr; m_walkAnimation = new Animation(manager->GetTexture("animations/player/player_walk.png"), 8, 0.1f, Rectf { 0, 0, 70, 70 }); } Collision::CollisionRect Player::GetCollisionRect() const { Collision::CollisionRect rect = { m_Position, m_Size, m_Vel }; return rect; } void Player::Draw() const { if (m_DrawCollisionRect) { utils::SetColor(Colors::PINK); utils::DrawRect(Rectf { m_Position.x, m_Position.y, m_Size.x, m_Size.y }); } Point2f center = m_Position + m_Size / 2; const int frameWidth = 70; //TODO: fix this int halfFrameWidth = frameWidth / 2; auto drawPos = Point2f { center.x - halfFrameWidth - 10, center.y - halfFrameWidth + 9 }; m_walkAnimation->Draw(drawPos, 0); } void Player::ProcessImGui() { ImGui::Begin("Collision Info", nullptr, ImGuiWindowFlags_AlwaysAutoResize); ImGui::Text("is Grounded: %s", m_Grounded ? "true" : "false"); ImGui::Text("Did just dig right: %s", m_DidJustDigRight ? "true" : "false"); bool test = !utils::isKeyPressed(SDL_SCANCODE_H); ImGui::Text("Is Key Up H: %s", test ? "true" : "false"); ImGui::Checkbox("Draw Collision Rect", &m_DrawCollisionRect); //ContactMap ImGui::Text("ContactMap:"); ImGui::Text("Top: %s", m_ContactMap[Collision::CollisionDirection::Top] != nullptr ? "true" : "false"); ImGui::Text("Bottom: %s", m_ContactMap[Collision::CollisionDirection::Bottom] != nullptr ? "true" : "false"); ImGui::Text("Left: %s", m_ContactMap[Collision::CollisionDirection::Left] != nullptr ? "true" : "false"); ImGui::Text("Right: %s", m_ContactMap[Collision::CollisionDirection::Right] != nullptr ? "true" : "false"); ImGui::End(); } void Player::Update(float elapsedTime, WorldLevel& level) { m_Vel = Point2f { 0, -100 }; //check for keys if (utils::isKeyDown(SDL_SCANCODE_W)) { m_Vel.y = 100; m_Grounded = false; } if (utils::isKeyPressed(SDL_SCANCODE_S)) { m_Vel.y = -100; if (m_Grounded) { if (m_ContactMap[Collision::CollisionDirection::Bottom] != nullptr) { m_ContactMap[Collision::CollisionDirection::Bottom]->SetTileType(Tiles::AIR); WorldTile* tile = m_ContactMap[Collision::CollisionDirection::Bottom]; //center of tile Point2f tileCenter = tile->GetCollisionRect().getCollisionRect().pos + tile->GetCollisionRect().getCollisionRect().size / 2; m_Position = Point2f { tileCenter.x - m_Size.x / 2, tileCenter.y - m_Size.y / 2 + 5 }; m_ContactMap[Collision::CollisionDirection::Bottom] = nullptr; } } } if (utils::isKeyDown(SDL_SCANCODE_A)) { m_walkAnimation->SetFlipped(false); m_Vel.x = -100; } if (utils::isKeyDown(SDL_SCANCODE_D)) { m_Vel.x = 100; m_walkAnimation->SetFlipped(true); if (m_Grounded && !m_DidJustDigRight) { //Check if the player doesnt come from digging a tile if (m_ContactMap[Collision::CollisionDirection::Right] != nullptr) { m_ContactMap[Collision::CollisionDirection::Right]->SetTileType(Tiles::AIR); WorldTile* tile = m_ContactMap[Collision::CollisionDirection::Right]; //center of tile const Point2f tileCenter = tile->GetCollisionRect().getCollisionRect().pos + tile->GetCollisionRect().getCollisionRect().size / 2; m_Position = Point2f { tileCenter.x - m_Size.x / 2, tileCenter.y - m_Size.y / 2 + 5 }; m_ContactMap[Collision::CollisionDirection::Right] = nullptr; m_DidJustDigRight = true; } } } if (m_DidJustDigRight) { if (!utils::isKeyDown(SDL_SCANCODE_D)) { m_DidJustDigRight = false; } } m_walkAnimation->Update(elapsedTime); m_ContactMap[Collision::CollisionDirection::Top] = nullptr; m_ContactMap[Collision::CollisionDirection::Bottom] = nullptr; m_ContactMap[Collision::CollisionDirection::Left] = nullptr; m_ContactMap[Collision::CollisionDirection::Right] = nullptr; m_Grounded = false; float t = 0, min_t = INFINITY; Point2f intersectionPoint, normal; std::vector> contactTimes {}; const WorldGridManager& gridManager = level.GetGridManager(); for (int x { 0 }; x < WORLD_WIDTH; ++x) { for (int y { 0 }; y < WORLD_HEIGHT; ++y) { WorldTile* tile = gridManager.GetTileAtIndex(x, y); if (*tile->GetTileType() != Tiles::AIR) { tile->m_Hightlight = false; if (Collision::DynamicRectVsRect(this->GetCollisionRect(), elapsedTime, tile->GetCollisionRect().getCollisionRect(), intersectionPoint, normal, t)) { contactTimes.emplace_back(std::pair { x + y * WORLD_WIDTH, t }); } } } } std::sort(contactTimes.begin(), contactTimes.end(), [](const std::pair& a, const std::pair& b) { return a.second < b.second; }); for (std::pair contact_time : contactTimes) { int x = contact_time.first % WORLD_WIDTH; int y = contact_time.first / WORLD_WIDTH; WorldTile* world_tile = gridManager.GetTileAtIndex(x, y); const Point2f WorldTilePos = world_tile->GetCollisionRect().getCollisionRect().pos; const Point2f WorldTileSize = world_tile->GetCollisionRect().getCollisionRect().size; if (WorldTilePos.y + WorldTileSize.y > m_Position.y) { if (WorldTilePos.x + WorldTileSize.x > m_Position.x) { if (WorldTilePos.y + WorldTileSize.y / 2 > m_Position.y && m_Position.y + m_Size.y / 2 > WorldTilePos.y) { //Right of player m_ContactMap[Collision::CollisionDirection::Right] = world_tile; } } } if (WorldTilePos.y + WorldTileSize.y > m_Position.y) { if (WorldTilePos.x < m_Position.x + m_Size.x) { if (WorldTilePos.y + WorldTileSize.y / 2 > m_Position.y && m_Position.y + m_Size.y / 2 > WorldTilePos.y) { //Left of player m_ContactMap[Collision::CollisionDirection::Left] = world_tile; } } } //Below the player if (WorldTilePos.y + WorldTileSize.y <= m_Position.y) { if (WorldTilePos.x + WorldTileSize.x / 2 > m_Position.x && m_Position.x + m_Size.x / 2 > WorldTilePos.x) { m_ContactMap[Collision::CollisionDirection::Bottom] = world_tile; m_Grounded = true; world_tile->m_Hightlight = true; } } Collision::CollisionRect rect = world_tile->GetCollisionRect().getCollisionRect(); //TODO: fix this mess Collision::ResolvePlayerVsRect(*this, elapsedTime, &rect); } if (m_Vel.x != 0.0f) { m_State = PlayerState::Walking; } else { m_State = PlayerState::Idle; } switch (m_State) { case PlayerState::Idle: m_walkAnimation->SetPlaying(false); break; case PlayerState::Walking: m_walkAnimation->SetPlaying(true); break; default: break; } m_Position = m_Position + m_Vel * elapsedTime; }