/** * @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 Notifies this state that the hero has just changed its * position. */ void Hero::PullingState::notify_position_changed() { if (is_moving_grabbed_entity()) { // if the entity has made more than 8 pixels and is aligned on the grid, // we stop the movement PathMovement* movement = static_cast<PathMovement*>(get_hero().get_movement()); bool horizontal = get_sprites().get_animation_direction() % 2 == 0; bool has_reached_grid = movement->get_total_distance_covered() >= 16 && ((horizontal && pulled_entity->is_aligned_to_grid_x()) || (!horizontal && pulled_entity->is_aligned_to_grid_y())); if (has_reached_grid) { pulled_entity->update(); stop_moving_pulled_entity(); } } }
/** * @brief Notifies this state that the hero has just changed its * position. */ void Hero::PushingState::notify_position_changed() { if (is_moving_grabbed_entity()) { // if the entity has made more than 8 pixels and is aligned on the grid, // we stop the movement PathMovement *movement = (PathMovement*) hero.get_movement(); bool horizontal = pushing_direction4 % 2 == 0; bool has_reached_grid = movement->get_total_distance_covered() > 8 && ((horizontal && pushed_entity->is_aligned_to_grid_x()) || (!horizontal && pushed_entity->is_aligned_to_grid_y())); if (has_reached_grid) { //std::cout << "stop moving block: the entity has reached the grid\n"; stop_moving_pushed_entity(); } } }
/** * \brief Starts this state. * \param previous_state the previous state */ void Hero::StairsState::start(State* previous_state) { State::start(previous_state); // movement int speed = stairs.is_inside_floor() ? 40 : 24; std::string path = stairs.get_path(way); PathMovement* movement = new PathMovement(path, speed, false, true, false); // sprites and sound HeroSprites& sprites = get_sprites(); if (carried_item == NULL) { sprites.set_animation_walking_normal(); } else { sprites.set_lifted_item(carried_item); sprites.set_animation_walking_carrying(); } sprites.set_animation_direction((path[0] - '0') / 2); get_keys_effect().set_action_key_effect(KeysEffect::ACTION_KEY_NONE); if (stairs.is_inside_floor()) { if (way == Stairs::NORMAL_WAY) { // Towards an upper layer: change the layer now Layer layer = stairs.get_layer(); Debug::check_assertion(layer != LAYER_HIGH, "Invalid stairs layer"); get_entities().set_entity_layer(hero, Layer(layer + 1)); } } else { sprites.set_clipping_rectangle(stairs.get_clipping_rectangle(way)); if (way == Stairs::REVERSE_WAY) { Rectangle dxy = movement->get_xy_change(); int fix_y = 8; if (path[path.size() - 1] == '2') { fix_y *= -1; } hero.set_xy(hero.get_x() - dxy.get_x(), hero.get_y() - dxy.get_y() + fix_y); } } hero.set_movement(movement); }