bool Player::checkChunkIntersection(Manifold& manifold) { // Retrieve blocks for current chunk if (m_chunkValid) { const std::vector<glm::vec3>& blockPositions = m_currentChunk.getBlockPositions(); // Create player collider glm::vec3 playerMinPoint(m_currentPosition.x - 0.5f, m_currentPosition.y - 1.0f, m_currentPosition.z - 0.5f); glm::vec3 playerMaxPoint(m_currentPosition.x + 0.5f, m_currentPosition.y + 1.0f, m_currentPosition.z + 0.5f); AABBCollider playerCollider(playerMinPoint, playerMaxPoint); for (const glm::vec3& block : blockPositions) { // Create AABB glm::vec3 minPoint(block.x - 0.5f, block.y - 0.5f, block.z - 0.5f); glm::vec3 maxPoint(block.x + 0.5f, block.y + 0.5f, block.z + 0.5f); AABBCollider collider(minPoint, maxPoint); // Check intersection if (AABBCollider::checkCollision(playerCollider, collider, manifold)) { //std::cout << "PIGNGNOFNOSFOSFNFON" << std::endl; // ########################################################################################### //glm::vec3 directionOfMovement(m_currentPosition - m_lastPosition); //std::cout << "(" << directionOfMovement.x << ", " << directionOfMovement.y << ", " << directionOfMovement.z << ")" << std::endl; // //glm::vec3 displacement-directionO; // //// If im moving in the positive x //if (directionOfMovement.x > 0) { // //} //else if (directionOfMovement.x < 0) { // //} //else { // displacement.x = 0; //} resolveChunkIntersection(manifold, collider); return true; } } } return false; }
void World::update() { uint32_t updateTime = SDL_GetTicks(); float dtime = (updateTime-lastUpdateTime)/1000.f; // If F5 released, reload the scene if (wasF5Down and not Input::isKeyDown(SDL_SCANCODE_F5)) { if (Input::isKeyDown(SDL_SCANCODE_LSHIFT) || Input::isKeyDown(SDL_SCANCODE_RSHIFT)) { // Enable reload-on-change (inotify on Linux) } loadScene(currentScenePath); } wasF5Down = Input::isKeyDown(SDL_SCANCODE_F5); // If Tab released, toggle editor if (wasTabDown and not Input::isKeyDown(SDL_SCANCODE_TAB)) { isEditorShown = !isEditorShown; } wasTabDown = Input::isKeyDown(SDL_SCANCODE_F5); Entity &player = scene->player; Health &plrHealth = player.getComponent<Health>(); Transform &plrTform = player.getComponent<Transform>(); PlayerMotion &plrMotion = player.getComponent<PlayerMotion>(); // Check if player is still alive if (not plrHealth.isAlive()) { plrTform.position = scene->start.getComponent<Transform>().position; plrHealth.revive(); hidePortals(); } // Calculate the view and new velocity of the player // FIXME: don't do this here, let a manager handle plrMotion.mouseLook(); plrMotion.move(dtime); // Figure out the provisional new player position Vector3f pos = plrTform.position + plrMotion.velocity; //Y collision BoxCollider bboxY(Vector3f(plrTform.position.x, pos.y, plrTform.position.z), plrTform.scale); if (collidesWithWalls(bboxY)) { bool portaling = false; portaling = WorldHelper::isPlayerPortalingY(bboxY, &player, scene); if (not portaling and not plrMotion.noclip) { if (plrMotion.velocity.y < 0) { if(plrMotion.velocity.y < -HURT_VELOCITY) { std::uniform_int_distribution<> dis(0, PLAYER_FALL_SOUND.size()-1); player.getComponent<SoundSource>().playSound( Environment::getDataDir() + PLAYER_FALL_SOUND[dis(generator)]); } plrMotion.grounded = true; } plrMotion.velocity.y = 0; } } else { plrMotion.grounded = false; } //X collision BoxCollider bboxX(Vector3f(pos.x, plrTform.position.y, plrTform.position.z), plrTform.scale); if (collidesWithWalls(bboxX)) { bool portaling = false; portaling = WorldHelper::isPlayerPortalingX(bboxX, &player, scene); if (not portaling and not plrMotion.noclip) { plrMotion.velocity.x = 0; } } //Z collision BoxCollider bboxZ(Vector3f(plrTform.position.x, plrTform.position.y, pos.z), plrTform.scale); if (collidesWithWalls(bboxZ)) { bool portaling = false; portaling = WorldHelper::isPlayerPortalingZ(bboxZ, &player, scene); if (not portaling and not plrMotion.noclip) { plrMotion.velocity.z = 0; } } for (Entity &e : scene->entities) { // Trigger if (e.hasComponent<Trigger>()) { const Trigger &trigger = e.getComponent<Trigger>(); const Transform &trTform = e.getComponent<Transform>(); BoxCollider playerCollider(plrTform.position, plrTform.scale); BoxCollider triggerCollider(trTform.position, trTform.scale); if (playerCollider.collidesWith(triggerCollider)) { if (trigger.type == "radiation") { player.getComponent<Health>().harm(.1f); } else if (trigger.type == "death") { player.getComponent<Health>().kill(); printf("Death touched\n"); } else if (trigger.type == "win") { if(currentLevel + 1 < mapList.size()) { currentLevel++; } loadScene(mapList[currentLevel]); printf("Win touched\n"); } else if (trigger.type == "map") { printf("Map Trigger touched\n"); throw __FILE__ ": Map trigger type de-implemented, please reimplement"; //loadScene(trigger.reference); } else if (trigger.type == "button") { printf("Button touched\n"); } else { printf("Some trigger touched: %s\n", trigger.type.c_str()); } } } } pos = plrTform.position + plrMotion.velocity; // Check if the player is moving through a portal BoxCollider playerCollider(pos, plrTform.scale); for (EntityPair &p : scene->portalPairs) { Portal &portal1 = p.first->getComponent<Portal>(), &portal2 = p.second->getComponent<Portal>(); Transform &p1Tform = p.first->getComponent<Transform>(), &p2Tform = p.second->getComponent<Transform>(); if (portal1.open and portal2.open) { if (portal1.throughPortal(playerCollider)) { plrTform.position = p2Tform.position; float rotation = p2Tform.rotation.y - p1Tform.rotation.y + rad(180); plrTform.rotation.y += rotation; // Transform the velocity of the player float velocity = plrMotion.velocity.length(); plrMotion.velocity = portal2.getDirection() * velocity; } if (portal2.throughPortal(playerCollider)) { plrTform.position = p1Tform.position; float rotation = p1Tform.rotation.y - p2Tform.rotation.y + rad(180); plrTform.rotation.y += rotation; // Transform the velocity of the player float velocity = plrMotion.velocity.length(); plrMotion.velocity = portal1.getDirection() * velocity; } } } //Add velocity to the player position plrTform.position += plrMotion.velocity; //Parent camera to player scene->camera.setPerspective(); int vpWidth, vpHeight; renderer->getViewport()->getSize(&vpWidth, &vpHeight); scene->camera.setAspect((float)vpWidth / vpHeight); scene->camera.setPosition(plrTform.position + Vector3f(0, plrTform.scale.y/2, 0)); scene->camera.setRotation(plrTform.rotation); //Check if the end of the level has been reached float distToEnd = (scene->end.getComponent<Transform>().position - plrTform.position).length(); if (distToEnd < 1) { if(currentLevel + 1 < mapList.size()) { currentLevel++; } loadScene(mapList[currentLevel]); } lastUpdateTime = updateTime; }
void Player::resolveChunkIntersection(const Manifold& manifold, const AABBCollider& blockCollider) { //transform.translate(manifold.seperationVector); //std::cout << "(" << manifold.seperationVector.x << ", " << manifold.seperationVector.y << ", " << manifold.seperationVector.z << ")" << std::endl; glm::vec3 directionOfMovement(m_currentPosition - m_lastPosition); //std::cout << "(" << directionOfMovement.x << ", " << directionOfMovement.y << ", " << directionOfMovement.z << ")" << std::endl; glm::vec3 seperation(manifold.seperationVector); // Add displacement to axes that caused the collision bool collideX = false; if (directionOfMovement.x != 0) { glm::vec3 playerMinPoint(m_lastPosition.x - 0.5f + directionOfMovement.x, m_lastPosition.y - 1.0f, m_lastPosition.z - 0.5f); glm::vec3 playerMaxPoint(m_lastPosition.x + 0.5f + directionOfMovement.x, m_lastPosition.y + 1.0f, m_lastPosition.z + 0.5f); AABBCollider playerCollider(playerMinPoint, playerMaxPoint); if (AABBCollider::checkCollision(playerCollider, blockCollider)) { collideX = true; } } bool collideY = false; if (directionOfMovement.y != 0) { glm::vec3 playerMinPoint(m_lastPosition.x - 0.5f, m_lastPosition.y - 1.0f + directionOfMovement.y, m_lastPosition.z - 0.5f); glm::vec3 playerMaxPoint(m_lastPosition.x + 0.5f, m_lastPosition.y + 1.0f + directionOfMovement.y, m_lastPosition.z + 0.5f); AABBCollider playerCollider(playerMinPoint, playerMaxPoint); if (AABBCollider::checkCollision(playerCollider, blockCollider)) { collideY = true; } } bool collideZ = false; if (directionOfMovement.z != 0) { glm::vec3 playerMinPoint(m_lastPosition.x - 0.5f, m_lastPosition.y - 1.0f, m_lastPosition.z - 0.5f + directionOfMovement.z); glm::vec3 playerMaxPoint(m_lastPosition.x + 0.5f, m_lastPosition.y + 1.0f, m_lastPosition.z + 0.5f + directionOfMovement.z); AABBCollider playerCollider(playerMinPoint, playerMaxPoint); if (AABBCollider::checkCollision(playerCollider, blockCollider)) { collideZ = true; } } //// Only displace in the axes the player is moving in //if (abs(directionOfMovement.x) == 0) { // seperation.x = 0; //} //if (abs(directionOfMovement.y) == 0) { // seperation.y = 0; //} //if (abs(directionOfMovement.z) == 0) { // seperation.z = 0; //} // Only displace in the axes that caused the collision if (collideX || collideY || collideZ) { if (!collideX) { seperation.x = 0; } if (!collideY) { seperation.y = 0; } if (!collideZ) { seperation.z = 0; } } // Choose the minimum axis float32 depth = 0; int32 axis = 0; for (int32 i = 0; i < 3; i++) { if (depth == 0) { depth = seperation[i]; axis = i; } else { if (seperation[i] != 0 && (abs(seperation[i]) < abs(depth))) { depth = seperation[i]; axis = i; } } } for (int32 i = 0; i < 3; i++) { if (i == axis) { seperation[i] = depth; } else { seperation[i] = 0; } } //if (abs(seperation.x) < abs(seperation.y)) { // if (abs(seperation.x) < abs(seperation.z)) { // // min is x // seperation.y = 0; // seperation.z = 0; // } // else { // // min is z // seperation.y = 0; // seperation.x = 0; // } //} //else { // if (abs(seperation.y) < abs(seperation.z)) { // // min is y // seperation.x = 0; // seperation.z = 0; // } // else { // // min is z // seperation.y = 0; // seperation.x = 0; // } //} //glm::vec3 displacement = glm::proj(seperation, -glm::normalize(directionOfMovement)); glm::vec3 displacement = seperation; //std::cout << "(" << displacement.x << ", " << displacement.y << ", " << displacement.z << ")" << std::endl; // And just a hint of bias const static float32 bias = 0.0005f; if (abs(seperation.x) > 0) { displacement.x += signbit(seperation.x) ? -bias : bias; } if (abs(seperation.y) > 0) { displacement.y += signbit(seperation.y) ? -bias : bias; } if (abs(seperation.z) > 0) { displacement.z += signbit(seperation.z) ? -bias : bias; } //m_lastPosition = m_currentPosition; transform.translate(displacement); m_currentPosition = glm::vec3(transform.xPos, transform.yPos, transform.zPos); if (displacement.y > 0) { // Stop! m_velocityY = 0; //m_glueToGround = true; // Just a hint of bias //transform.translate(0, 0.0005f, 0); } // If im moving in the positive x //if (directionOfMovement.x > 0) { // //} //else if (directionOfMovement.x < 0) { // //} //else { // displacement.x = 0; //} // //if (manifold.seperationVector.x == 0 && manifold.seperationVector.z == 0 && manifold.seperationVector.y > 0) { // m_glueToGround = true; // // // Stop! // m_velocityY = 0; // transform.translate(0, 0.0005f, 0); // HACK WARNING, Adding a bias here so I can get it to work for the demo //} }
void World::update() { Player* player = &scene->player; player->mouseLook(); player->move(); Vector3f pos = add(player->position, player->velocity); //FIXME Remake the collision system to be less faulty and ugly //Y collision BoxCollider bboxY(Vector3f(player->position.x, pos.y, player->position.z), player->scale); if (collidesWithWalls(bboxY)) { bool portaling = false; if (scene->bluePortal.open && scene->orangePortal.open) { if(scene->bluePortal.inPortal(bboxY)) { if(scene->bluePortal.rotation.x == -90 || scene->bluePortal.rotation.x == 90) { portaling = true; } } if(scene->orangePortal.inPortal(bboxY)) { if(scene->orangePortal.rotation.x == -90 || scene->orangePortal.rotation.x == 90) { portaling = true; } } } if(!portaling) { if (player->velocity.y < 0) { if(player->velocity.y < -0.18f) { std::uniform_int_distribution<> dis(0, PLAYER_FALL_SOUND.size()-1); SoundManager::PlaySound(Environment::getDataDir() + PLAYER_FALL_SOUND[dis(generator)],player,SoundManager::PRIMARY); } player->grounded = true; } player->velocity.y = 0; } } //X collision BoxCollider bboxX(Vector3f(pos.x, player->position.y, player->position.z), player->scale); if (collidesWithWalls(bboxX)) { bool portaling = false; if (scene->bluePortal.open && scene->orangePortal.open) { if(scene->bluePortal.inPortal(bboxX)) { if(scene->bluePortal.rotation.x == 0 && (scene->bluePortal.rotation.y == -90 || scene->bluePortal.rotation.y == 90)) { portaling = true; } } if(scene->orangePortal.inPortal(bboxX)) { if(scene->bluePortal.rotation.x == 0 && (scene->orangePortal.rotation.y == -90 || scene->orangePortal.rotation.y == 90)) { portaling = true; } } } if(!portaling) { player->velocity.x = 0; } } //Z collision BoxCollider bboxZ(Vector3f(player->position.x, player->position.y, pos.z), player->scale); if (collidesWithWalls(bboxZ)) { bool portaling = false; if (scene->bluePortal.open && scene->orangePortal.open) { if(scene->bluePortal.inPortal(bboxZ)) { if(scene->bluePortal.rotation.x == 0 && (scene->bluePortal.rotation.y == 0 || scene->bluePortal.rotation.y == 180)) { portaling = true; } } if(scene->orangePortal.inPortal(bboxZ)) { if(scene->orangePortal.rotation.x == 0 && (scene->orangePortal.rotation.y == 0 || scene->orangePortal.rotation.y == 180)) { portaling = true; } } } if(!portaling) { player->velocity.z = 0; } } //Trigger for (unsigned int i = 0; i < scene->triggers.size(); i++) { Trigger trigger = scene->triggers[i]; BoxCollider playerCollider(player->position, player->scale); BoxCollider triggerCollider(trigger.position, trigger.scale); if (playerCollider.collidesWith(triggerCollider)) { if (trigger.type == "radiation") { player->harm(10); } else if (trigger.type == "death") { player->kill(); printf("Death touched\n"); } else if (trigger.type == "win") { printf("Win touched\n"); } else { printf("Some trigger touched: %s\n", trigger.type.c_str()); } } } pos = player->position + player->velocity; //Check if the player is moving through a portal BoxCollider playerCollider(pos, player->scale); if (scene->bluePortal.open && scene->orangePortal.open) { if (scene->bluePortal.throughPortal(playerCollider)) { player->position.set(scene->orangePortal.position); float rotation = scene->orangePortal.rotation.y - scene->bluePortal.rotation.y + 180; player->rotation.y += rotation; //Transform the velocity of the player float velocity = player->velocity.length(); player->velocity = *scene->orangePortal.getDirection().scale(velocity); } if (scene->orangePortal.throughPortal(playerCollider)) { player->position.set(scene->bluePortal.position); float rotation = scene->bluePortal.rotation.y - scene->orangePortal.rotation.y + 180; player->rotation.y += rotation; //Transform the velocity of the player float velocity = player->velocity.length(); player->velocity = *scene->bluePortal.getDirection().scale(velocity); } } //Add velocity to the player position player->position.add(player->velocity); //Parent camera to player scene->camera.position.set(scene->player.position); scene->camera.position.y += scene->player.scale.y/2; scene->camera.rotation.set(scene->player.rotation); //Check if the end of the level has been reached float distToEnd = (scene->end.position - scene->player.position).length(); if (distToEnd < 1) { if(currentLevel + 1 < mapList.size()) { currentLevel++; } loadScene(mapList[currentLevel]); } }