예제 #1
0
/**
 * Initiates the display of movement for the supplied unit.
 * This should be called before attempting to display moving to a new hex.
 */
void unit_mover::start(unit_ptr u)
{
	// Nothing to do here if there is nothing to animate.
	if ( !can_draw_ )
		return;
	// If no animation then hide unit until end of movement
	if ( !animate_ ) {
		was_hidden_ = u->get_hidden();
		u->set_hidden(true);
		return;
	}

	// This normally does nothing, but just in case...
	wait_for_anims();

	// Visually replace the original unit with the temporary.
	// (Original unit is left on the map, so the unit count is correct.)
	replace_temporary(u);

	// Initialize our temporary unit for the move.
	temp_unit_ptr_->set_location(path_[0]);
	temp_unit_ptr_->set_facing(path_[0].get_relative_dir(path_[1]));
	temp_unit_ptr_->anim_comp().set_standing(false);
	disp_->invalidate(path_[0]);

	// If the unit can be seen here by the viewing side:
	if ( !is_enemy_ || !temp_unit_ptr_->invisible(path_[0]) ) {
		// Scroll to the path, but only if it fully fits on screen.
		// If it does not fit we might be able to do a better scroll later.
		disp_->scroll_to_tiles(path_, game_display::ONSCREEN, true, true, 0.0, false);
	}
	// We need to clear big invalidation before the move and have a smooth animation
	// (mainly black stripes and invalidation after canceling attack dialog).
	// Two draw calls are needed to also redraw the previously invalidated hexes.
	// We use update=false because we don't need delay here (no time wasted)
	// and no screen refresh (will be done by last 3rd draw() and it optimizes
	// the double blitting done by these invalidations).
	disp_->draw(false);
	disp_->draw(false);

	// The last draw() was still slow, and its initial new_animation_frame() call
	// is now old, so we do another draw() to get a fresh one
	// TODO: replace that by a new_animation_frame() before starting anims
	//       don't forget to change the previous draw(false) to true
	disp_->draw(true);

	// extra immobile movement animation for take-off
	animator_.add_animation(temp_unit_ptr_.get(), "pre_movement", path_[0], path_[1]);
	animator_.start_animations();
	animator_.wait_for_end();
	animator_.clear();

	// Switch the display back to the real unit.
	u->set_facing(temp_unit_ptr_->facing());
	u->anim_comp().set_standing(false);	// Need to reset u's animation so the new facing takes effect.
	u->set_hidden(was_hidden_);
	temp_unit_ptr_->set_hidden(true);
}
예제 #2
0
/* Note: Hide the unit in its current location; do not actually remove it.
 * Otherwise the status displays will be wrong during the movement.
 */
void unit_mover::replace_temporary(unit_ptr u)
{
	if ( disp_ == nullptr )
		// No point in creating a temp unit with no way to display it.
		return;

	// Save the hidden state of the unit.
	was_hidden_ = u->get_hidden();

	// Make our temporary unit mostly match u...
	temp_unit_ptr_ = fake_unit_ptr(unit_ptr(new unit(*u)), resources::fake_units);

	// ... but keep the temporary unhidden and hide the original.
	temp_unit_ptr_->set_hidden(false);
	u->set_hidden(true);

	// Update cached data.
	is_enemy_ =	(*resources::teams)[u->side()-1].is_enemy(disp_->viewing_side());
}