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