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;
}
示例#2
0
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
	//}
}
示例#4
0
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]);
  }
}