コード例 #1
0
void WorldLogic::restartGame(Logic &l)
{
  for (const std::shared_ptr<GameObject> &obj: l.game_model()->objects()) {
    if (typeid(obj) != typeid(model::Explosion)) {
      obj->alive() = false;
    }
  }

  add_box_interval_timer = 0.f;
  next_powerup_timer = NAN; // batman
  box_count = 0;

  _model->alive() = true;
  _model->playerPoints() = 0;
  _model->remainingLives() = 5;
  l.game_model()->gameSpeed() = 1.f;
  l.game_model()->stickyWallTimer() = 0.f;

  std::shared_ptr<Paddle> user_paddle(new Paddle("PlayerPaddle"));
  user_paddle->size() = vec3_type(10.f, 2.5f, 10.f);
  user_paddle->position() = vec3_type(0.f, -_model->getWorldHalfHeight() + user_paddle->size().y() * 2.f, 0.f);
  user_paddle->maxPosition() = vec3_type(_model->getWorldHalfWidth() - user_paddle->size().x() / 2.f, _model->getWorldHalfHeight(), HUGE_VALF);

  l.game_model()->addGameObject(user_paddle);

  _shallRestartTheGame = false;

  _model->gameRestarted() = true;
}
コード例 #2
0
void WorldLogic::addBoxToGame(Logic &l)
{
  std::uniform_real_distribution<scalar_type> size_exp_dist(1.7f, 3.4f);
  scalar_type size = exp2(size_exp_dist(rng));

  vec3_type max_pos(_model->getWorldHalfWidth() - size / 2.f, _model->getWorldHalfHeight() - size / 2.f, HUGE_VALF);

  std::uniform_real_distribution<scalar_type> x_dist(-max_pos.x(), max_pos.x());
  scalar_type x = x_dist(rng);

  std::shared_ptr<Box> box(new Box("Box", !_model->remainingLives()));
  box->size() = size;
  box->position() = vec3_type(x, 0.f, 0.f);
  box->maxPosition() = max_pos;

  l.game_model()->addGameObject(box);
  box_count++;
}
コード例 #3
0
// I love this function because it shows how bad this whole engine model is
// (this class basically does all the physics calculations, so we could have
// put everything in a single big loop anyway)
bool WorldLogic::advance(Logic &l, const InputEventHandler::keyboard_event &evt)
{
  _model->gameRestarted() = false;

  if (evt.key == 'r') {
    _shallRestartTheGame = true;
  }

  if (_shallRestartTheGame) {
    restartGame(l);
  }


  // Oh my beloved Madoka, you can't be serious
  const auto &objs = l.game_model()->objects();
  auto paddle_obj_it = std::find_if(objs.begin(), objs.end(),
          [](const std::shared_ptr<GameObject> &obj) { return typeid(*obj) == typeid(Paddle); });

  std::shared_ptr<Paddle> paddle(nullptr);

  if (paddle_obj_it != objs.end()) {
    paddle = std::dynamic_pointer_cast<Paddle>(*paddle_obj_it);

    if (!paddle->alive()) {
      paddle = nullptr;
    }
  }


  // paddle == nullptr means Game Over


  scalar_type timestep_sec = l.game_model()->timestep().count();

  static scalar_type add_box_interval_timer;
  add_box_interval_timer += timestep_sec;

  float true_add_box_interval = add_box_interval * powf(l.game_model()->gameSpeed(), -8.f);
  if (true_add_box_interval > add_box_interval) {
    true_add_box_interval = add_box_interval;
  }

  while (add_box_interval_timer >= true_add_box_interval) {
    if (paddle || (box_count < 20)) {
      addBoxToGame(l);
    }
    add_box_interval_timer -= true_add_box_interval;
  }


  if (std::isnan(next_powerup_timer) || (next_powerup_timer <= 0.f)) {
    if (paddle && !std::isnan(next_powerup_timer)) {
      bool generate_bad = std::uniform_int_distribution<int>(0, 2)(rng) != 0;
      std::uniform_int_distribution<int> t_dist;
      if (generate_bad) {
        t_dist = std::uniform_int_distribution<int>(PowerUp::BAD_TYPE_START, PowerUp::BAD_TYPE_END);
      } else {
        t_dist = std::uniform_int_distribution<int>(PowerUp::GOOD_TYPE_START, PowerUp::GOOD_TYPE_END);
      }

      PowerUp::Type t = static_cast<PowerUp::Type>(t_dist(rng));

      std::uniform_real_distribution<float> x_dist(-_model->getWorldHalfWidth() + 5.f, _model->getWorldHalfWidth() - 5.f);

      l.game_model()->addGameObject(std::make_shared<PowerUp>(t,
                                                              vec3_type(x_dist(rng), paddle->position().y(), -400.f),
                                                              vec3_type(_model->getWorldHalfWidth(), _model->getWorldHalfHeight(), HUGE_VALF)));
    }

    std::uniform_real_distribution<scalar_type> nput_dist(7.f, 10.f);
    next_powerup_timer = powf(l.game_model()->gameSpeed(), -7.f) * nput_dist(rng);
  }

  if (paddle) {
    next_powerup_timer -= timestep_sec;
  }


  if (l.game_model()->stickyWallTimer() > 0.f) {
    l.game_model()->stickyWallTimer() -= timestep_sec;

    if (l.game_model()->stickyWallTimer() < 0.f) {
      l.game_model()->stickyWallTimer() = 0.f;
    }
  }


  // The task says to do this after incrementing the point count, but I really
  // don't see why
  if ((_model->remainingLives() <= 0) && paddle) {
    paddle->alive() = false;
    for (const std::shared_ptr<GameObject> &obj: objs) {
      if (typeid(*obj) == typeid(PowerUp)) {
        obj->alive() = false;
      }
    }

    l.game_model()->addGameObject(std::make_shared<GameOver>("Game Over", _model->playerPoints()));
  }


  float old_player_points = _model->playerPoints();

  // Keep the points exact
  static scalar_type player_points_inc;

  if (paddle) {
    player_points_inc += timestep_sec;

    int inc_now = static_cast<int>(player_points_inc * 10.f);
    _model->playerPoints() += inc_now;
    player_points_inc -= static_cast<scalar_type>(inc_now) / 10.f;
  }

  for (std::shared_ptr<GameObject> obj: objs) {
    if (!obj->alive()) {
      continue;
    }

    std::shared_ptr<Box> box = std::dynamic_pointer_cast<Box>(obj);
    if (!box) {
      // haha this nesting is so ugly (but it's not my fault)
      std::shared_ptr<PowerUp> pu = std::dynamic_pointer_cast<PowerUp>(obj);
      if (pu && paddle) {
        if ((pu->position() - paddle->position()).length() <= (paddle->size().x() + 5.f)) {
          Explosion::Type xt;

          switch (pu->type()) {
            case PowerUp::LIFE:
              ++_model->remainingLives();
              xt = Explosion::GOOD_POWER_UP_COLLECTED;
              break;

            case PowerUp::STICKY_WALLS:
              l.game_model()->stickyWallTimer() = 10.f;
              xt = Explosion::GOOD_POWER_UP_COLLECTED;
              break;

            case PowerUp::SLOW_GAME:
              l.game_model()->gameSpeed() /= 1.05f;
              xt = Explosion::GOOD_POWER_UP_COLLECTED;
              break;

            case PowerUp::EVAPORATE_BOXES:
              // FIXME: Somehow I don't like this... But it will probably work.
              for (std::shared_ptr<GameObject> pobj: objs) {
                if (!pobj->alive()) {
                  continue;
                }

                std::shared_ptr<Box> puff_the_magic_box = std::dynamic_pointer_cast<Box>(pobj);
                if (puff_the_magic_box) {
                  l.game_model()->addGameObject(std::make_shared<Explosion>(Explosion::BOX_EVAPORATE, *puff_the_magic_box));

                  puff_the_magic_box->alive() = false;
                  box_count--;
                }
              }
              xt = Explosion::GOOD_POWER_UP_COLLECTED;
              break;

            case PowerUp::PADDLE_SMALLER:
              // I'd love to directly influence the model, but Catalyst apparently
              // really dislikes frequent STATIC_DRAW updates (the libGL part
              // crashes)
              paddle->scale() *= .3f;
              off_force_exp *= 2.f;
              xt = Explosion::BAD_POWER_UP_COLLECTED;
              break;

            case PowerUp::QUICKEN_GAME:
              l.game_model()->gameSpeed() *= 1.1f;
              xt = Explosion::BAD_POWER_UP_COLLECTED;
              break;

            case PowerUp::DECREASE_FAN:
              paddle->relativeFanPower() *= .2f;
              xt = Explosion::BAD_POWER_UP_COLLECTED;
              break;
          }

          l.game_model()->addGameObject(std::make_shared<Explosion>(xt, *pu));

          pu->alive() = false;
        }
      }
      continue;
    }

    setForce(box, paddle);

    if (!paddle) {
      continue;
    }

    if (box->position().y() - box->size() / 2.f < paddle->position().y()) {
      l.game_model()->addGameObject(std::make_shared<Explosion>(Explosion::BOX_FLOOR_CRASH, *box));

      box->alive() = false;
      box_count--;

      if (_model->remainingLives() > 0) {
        --_model->remainingLives();
      }
    }

    // this is genius
    for (std::shared_ptr<GameObject> iobj: objs) {
      if (!iobj->alive() || (iobj == obj)) {
        continue;
      }

      std::shared_ptr<Box> ibox = std::dynamic_pointer_cast<Box>(iobj);
      if (!ibox) {
        continue;
      }

      if ((box->position() - ibox->position()).length() < box->size() + ibox->size()) {
        l.game_model()->addGameObject(std::make_shared<Explosion>(Explosion::BOX_BOX_COLLISION, *box));
        l.game_model()->addGameObject(std::make_shared<Explosion>(Explosion::BOX_BOX_COLLISION, *ibox));

        box->alive() = false;
        ibox->alive() = false;
        box_count -= 2;

        // EXTRA MONSTER POINTS
        _model->playerPoints() += (box->velocity() - ibox->velocity()).length() / 4.f;
      }
    }
  }

  if (paddle) {
    if (l.game_model()->gameSpeed() < 1.f) {
      l.game_model()->gameSpeed() = 1.f;
    }

    l.game_model()->gameSpeed() += (_model->playerPoints() - old_player_points) / 10000.f;

    if (l.game_model()->gameSpeed() > 1.25f) {
      l.game_model()->gameSpeed() = 1.25f;
    }
  } else {
    l.game_model()->gameSpeed() = .3f;
  }

  if (off_force_exp > 5.f) {
    off_force_exp *= exp(-timestep_sec / 10.f);

    if (off_force_exp < 5.f) {
      off_force_exp = 5.f;
    }
  }

  return true;
}