/** * @brief Updates this state. */ void Hero::PushingState::update() { State::update(); if (is_moving_grabbed_entity()) { // the hero is pushing an entity and is currently moving it (typically a block) // detect when the hero movement is finished // because the hero has covered 16 pixels, has reached an obstacle or has aligned the entity on the grid PathMovement *movement = (PathMovement*) hero.get_movement(); bool horizontal = pushing_direction4 % 2 == 0; bool has_reached_grid = movement->get_total_distance_covered() > 8 && ((horizontal && hero.is_aligned_to_grid_x()) || (!horizontal && hero.is_aligned_to_grid_y())); if (movement->is_finished() || has_reached_grid) { stop_moving_pushed_entity(); } } else { // the hero is pushing a fixed obstacle // stop pushing if there is no more obstacle if (!hero.is_facing_obstacle()) { hero.set_state(new FreeState(hero)); } // stop pushing if the player changes his direction else if (get_controls().get_wanted_direction8() != pushing_direction4 * 2) { if (get_controls().is_key_pressed(GameControls::ACTION)) { hero.set_state(new GrabbingState(hero)); } else { hero.set_state(new FreeState(hero)); } } // see if the obstacle pushed is an entity that the hero can move else { Detector *facing_entity = hero.get_facing_entity(); if (facing_entity != NULL) { // the obstacle pushed is an entity if (facing_entity->get_type() == BLOCK) { // it can be moved by the hero (TODO dynamic binding) hero.try_snap_to_facing_entity(); } if (facing_entity->moved_by_hero()) { std::string path = " "; path[0] = path[1] = '0' + pushing_direction4 * 2; hero.set_movement(new PathMovement(path, 40, false, false, false)); pushed_entity = facing_entity; } } } } }
/** * @brief Updates this state. */ void Hero::SwordSwingingState::update() { State::update(); // check the animation if (get_sprites().is_animation_finished()) { sword_finished = true; if (hero.get_movement() == NULL) { // if the player is still pressing the sword key, start loading the sword if (get_controls().is_key_pressed(GameControls::SWORD) && !attacked) { hero.set_state(new SwordLoadingState(hero)); } else { hero.set_state(new FreeState(hero)); } } else { // the sword animation is finished, but the movement continues hero.get_sprites().set_animation_stopped_normal(); } } // check the movement if any if (hero.get_movement() != NULL && hero.get_movement()->is_finished()) { hero.clear_movement(); if (sword_finished) { hero.set_state(new FreeState(hero)); } } }
/** * @brief Updates this state. */ void Hero::SwordLoadingState::update() { PlayerMovementState::update(); if (suspended) { return; } uint32_t now = System::now(); // detect when the sword is loaded (i.e. ready for a spin attack) if (!sword_loaded && now >= sword_loaded_date) { play_load_sound(); sword_loaded = true; } if (!get_controls().is_key_pressed(GameControls::SWORD)) { // the player has just released the sword key // stop loading the sword, go to the normal state or make a spin attack if (!sword_loaded) { // the sword was not loaded yet: go to the normal state hero.set_state(new FreeState(hero)); } else { // the sword is loaded: release a spin attack hero.set_state(new SpinAttackState(hero)); } } }
/** * @brief Makes the hero stop pushing the entity he is facing. */ void Hero::PushingState::stop_moving_pushed_entity() { if (pushed_entity != NULL) { pushed_entity->stop_movement_by_hero(); // the hero may have moved one or several pixels too much // because he moved before the block, not knowing that the block would not follow him switch (pushing_direction4) { case 0: // east hero.set_x(pushed_entity->get_x() - 16); break; case 1: // north hero.set_y(pushed_entity->get_y() + 16); break; case 2: // west hero.set_x(pushed_entity->get_x() + 16); break; case 3: // south hero.set_y(pushed_entity->get_y() - 16); break; } pushed_entity = NULL; } hero.clear_movement(); if (!get_controls().is_key_pressed(GameControls::ACTION)) { // the hero was pushing an entity without grabbing it // stop the animation pushing if his direction changed if (get_controls().get_wanted_direction8() != pushing_direction4 * 2) { hero.set_state(new FreeState(hero)); } } else { hero.set_state(new GrabbingState(hero)); } }
/** * @brief Makes the hero stop pushing the entity he is facing. * * This function is called while moving the entity, when the * hero or the entity collides with an obstacle or when * the hero's movement is finished. */ void Hero::PushingState::stop_moving_pushed_entity() { pushed_entity = NULL; hero.clear_movement(); if (!get_controls().is_key_pressed(GameControls::ACTION)) { // the hero was pushing an entity without grabbing it // stop the animation pushing if his direction changed if (get_controls().get_wanted_direction8() != pushing_direction4 * 2) { hero.set_state(new FreeState(hero)); } } else { hero.set_state(new GrabbingState(hero)); } }
/** * @brief Updates this state. */ void Hero::PushingState::update() { State::update(); if (!is_moving_grabbed_entity()) { // the hero is pushing a fixed obstacle // stop pushing if there is no more obstacle if (!hero.is_facing_obstacle()) { hero.set_state(new FreeState(hero)); } // stop pushing if the player changes his direction else if (get_controls().get_wanted_direction8() != pushing_direction4 * 2) { if (get_controls().is_key_pressed(GameControls::ACTION)) { hero.set_state(new GrabbingState(hero)); } else { hero.set_state(new FreeState(hero)); } } // see if the obstacle pushed is an entity that the hero can move else { Detector *facing_entity = hero.get_facing_entity(); if (facing_entity != NULL) { // the obstacle pushed is an entity if (facing_entity->get_type() == BLOCK) { // it can be moved by the hero (TODO dynamic binding) hero.try_snap_to_facing_entity(); } if (facing_entity->start_movement_by_hero()) { std::string path = " "; path[0] = path[1] = '0' + pushing_direction4 * 2; hero.set_movement(new PathMovement(path, 40, false, false, false)); pushed_entity = facing_entity; } } } } }
/** * @brief Updates this state. */ void Hero::PullingState::update() { State::update(); if (!is_moving_grabbed_entity()) { int wanted_direction8 = get_controls().get_wanted_direction8(); int opposite_direction8 = (get_sprites().get_animation_direction8() + 4) % 8; // stop pulling if the action key is released or if there is no more obstacle if (!get_controls().is_key_pressed(GameControls::ACTION) || !hero.is_facing_obstacle()) { hero.set_state(new FreeState(hero)); } // stop pulling the obstacle if the player changes his direction else if (wanted_direction8 != opposite_direction8) { hero.set_state(new GrabbingState(hero)); } // see if the obstacle is an entity that the hero can pull else { Detector *facing_entity = hero.get_facing_entity(); if (facing_entity != NULL) { if (facing_entity->get_type() == BLOCK) { // TODO use dynamic binding hero.try_snap_to_facing_entity(); } if (facing_entity->start_movement_by_hero()) { std::string path = " "; path[0] = path[1] = '0' + opposite_direction8; hero.set_movement(new PathMovement(path, 40, false, false, false)); pulled_entity = facing_entity; } } } } }
/** * @brief Updates this state. */ void Hero::SwordSwingingState::update() { State::update(); if (get_sprites().is_animation_finished()) { // if the player is still pressing the sword key, start loading the sword if (get_controls().is_key_pressed(GameControls::SWORD)) { hero.set_state(new SwordLoadingState(hero)); } else { hero.set_state(new FreeState(hero)); } } }