Changeset - r15426:38ea83bb4f51
[Not reviewed]
master
0 5 0
frosch - 14 years ago 2010-07-04 13:07:47
frosch@openttd.org
(svn r20079) -Codechange [FS#3922]: Add helper functions to deal with the 192-256-magic of vehicle movement.
5 files changed with 68 insertions and 27 deletions:
0 comments (0 inline, 0 general)
src/aircraft_cmd.cpp
Show inline comments
 
@@ -734,7 +734,8 @@ static int UpdateAircraftSpeed(Aircraft 
 
	/* Adjust distance moved by plane speed setting */
 
	if (_settings_game.vehicle.plane_speed > 1) spd /= _settings_game.vehicle.plane_speed;
 

	
 
	if (!(v->direction & 1)) spd = spd * 3 / 4;
 
	/* Convert direction-indepenent speed into direction-dependent speed. (old movement method) */
 
	spd = v->GetOldAdvanceSpeed(spd);
 

	
 
	spd += v->progress;
 
	v->progress = (byte)spd;
src/roadveh_cmd.cpp
Show inline comments
 
@@ -756,6 +756,13 @@ static void RoadVehArrivesAt(const RoadV
 
	}
 
}
 

	
 
/**
 
 * This function looks at the vehicle and updates its speed (cur_speed
 
 * and subspeed) variables. Furthermore, it returns the distance that
 
 * the vehicle can drive this tick. #Vehicle::GetAdvanceDistance() determines
 
 * the distance to drive before moving a step on the map.
 
 * @return distance to drive.
 
 */
 
static int RoadVehAccelerate(RoadVehicle *v)
 
{
 
	uint oldspeed = v->cur_speed;
 
@@ -786,8 +793,7 @@ static int RoadVehAccelerate(RoadVehicle
 
		}
 
	}
 

	
 
	/* Speed is scaled in the same manner as for trains. @see train_cmd.cpp */
 
	int scaled_spd = spd * 3 >> 2;
 
	int scaled_spd = v->GetAdvanceSpeed(spd);
 

	
 
	scaled_spd += v->progress;
 
	v->progress = 0;
 
@@ -1595,7 +1601,7 @@ static bool RoadVehController(RoadVehicl
 
	/* Check how far the vehicle needs to proceed */
 
	int j = RoadVehAccelerate(v);
 

	
 
	int adv_spd = (v->direction & 1) ? 192 : 256;
 
	int adv_spd = v->GetAdvanceDistance();
 
	bool blocked = false;
 
	while (j >= adv_spd) {
 
		j -= adv_spd;
 
@@ -1609,8 +1615,8 @@ static bool RoadVehController(RoadVehicl
 
		}
 
		if (blocked) break;
 

	
 
		/* 192 spd used for going straight, 256 for going diagonally. */
 
		adv_spd = (v->direction & 1) ? 192 : 256;
 
		/* Determine distance to next map position */
 
		adv_spd = v->GetAdvanceDistance();
 

	
 
		/* Test for a collision, but only if another movement will occur. */
 
		if (j >= adv_spd && RoadVehCheckTrainCrash(v)) break;
src/ship_cmd.cpp
Show inline comments
 
@@ -346,8 +346,8 @@ static bool ShipAccelerate(Vehicle *v)
 
			SetWindowWidgetDirty(WC_VEHICLE_VIEW, v->index, VVW_WIDGET_START_STOP_VEH);
 
	}
 

	
 
	/* Decrease somewhat when turning */
 
	if (!(v->direction & 1)) spd = spd * 3 / 4;
 
	/* Convert direction-indepenent speed into direction-dependent speed. (old movement method) */
 
	spd = v->GetOldAdvanceSpeed(spd);
 

	
 
	if (spd == 0) return false;
 
	if ((byte)++spd == 0) return true;
src/train_cmd.cpp
Show inline comments
 
@@ -2839,10 +2839,8 @@ void Train::MarkDirty()
 
/**
 
 * This function looks at the vehicle and updates its speed (cur_speed
 
 * and subspeed) variables. Furthermore, it returns the distance that
 
 * the train can drive this tick. This distance is expressed as 256 * n,
 
 * where n is the number of straight (long) tracks the train can
 
 * traverse. This means that moving along a straight track costs 256
 
 * "speed" and a diagonal track costs 192 "speed".
 
 * the train can drive this tick. #Vehicle::GetAdvanceDistance() determines
 
 * the distance to drive before moving a step on the map.
 
 * @return distance to drive.
 
 */
 
int Train::UpdateSpeed()
 
@@ -2869,18 +2867,7 @@ int Train::UpdateSpeed()
 
		this->cur_speed = spd = Clamp(this->cur_speed + ((int)spd >> 8), 0, tempmax);
 
	}
 

	
 
	/* Scale speed by 3/4. Previously this was only done when the train was
 
	 * facing diagonally and would apply to however many moves the train made
 
	 * regardless the of direction actually moved in. Now it is always scaled,
 
	 * 256 spd is used to go straight and 192 is used to go diagonally
 
	 * (3/4 of 256). This results in the same effect, but without the error the
 
	 * previous method caused.
 
	 *
 
	 * The scaling is done in this direction and not by multiplying the amount
 
	 * to be subtracted by 4/3 so that the leftover speed can be saved in a
 
	 * byte in this->progress.
 
	 */
 
	int scaled_spd = spd * 3 >> 2;
 
	int scaled_spd = this->GetAdvanceSpeed(spd);
 

	
 
	scaled_spd += this->progress;
 
	this->progress = 0; // set later in TrainLocoHandler or TrainController
 
@@ -3885,7 +3872,7 @@ static bool TrainLocoHandler(Train *v, b
 
		SetWindowDirty(WC_VEHICLE_VIEW, v->index);
 
	}
 

	
 
	int adv_spd = (v->direction & 1) ? 192 : 256;
 
	int adv_spd = v->GetAdvanceDistance();
 
	if (j < adv_spd) {
 
		/* if the vehicle has speed 0, update the last_speed field. */
 
		if (v->cur_speed == 0) SetLastSpeed(v, v->cur_speed);
 
@@ -3897,8 +3884,8 @@ static bool TrainLocoHandler(Train *v, b
 
			TrainController(v, NULL);
 
			/* Don't continue to move if the train crashed. */
 
			if (CheckTrainCollision(v)) break;
 
			/* 192 spd used for going straight, 256 for going diagonally. */
 
			adv_spd = (v->direction & 1) ? 192 : 256;
 
			/* Determine distance to next map position */
 
			adv_spd = v->GetAdvanceDistance();
 

	
 
			/* No more moving this tick */
 
			if (j < adv_spd || v->cur_speed == 0) break;
src/vehicle_base.h
Show inline comments
 
@@ -227,6 +227,53 @@ public:
 
	virtual void UpdateDeltaXY(Direction direction) {}
 

	
 
	/**
 
	 * Determines the effective direction-specific vehicle movement speed.
 
	 *
 
	 * This method belongs to the old vehicle movement method:
 
	 * A vehicle moves a step every 256 progress units.
 
	 * The vehicle speed is scaled by 3/4 when moving in X or Y direction due to the longer distance.
 
	 *
 
	 * However, this method is slightly wrong in corners, as the leftover progress is not scaled correctly
 
	 * when changing movement direction. #GetAdvanceSpeed() and #GetAdvanceDistance() are better wrt. this.
 
	 *
 
	 * @param speed Direction-independent unscaled speed.
 
	 * @return speed scaled by movement direction. 256 units are required for each movement step.
 
	 */
 
	FORCEINLINE uint GetOldAdvanceSpeed(uint speed)
 
	{
 
		return (this->direction & 1) ? speed : speed * 3 / 4;
 
	}
 

	
 
	/**
 
	 * Determines the effective vehicle movement speed.
 
	 *
 
	 * Together with #GetAdvanceDistance() this function is a replacement for #GetOldAdvanceSpeed().
 
	 *
 
	 * A vehicle progresses independent of it's movement direction.
 
	 * However different amounts of "progress" are needed for moving a step in a specific direction.
 
	 * That way the leftover progress does not need any adaption when changing movement direction.
 
	 *
 
	 * @param speed Direction-independent unscaled speed.
 
	 * @return speed, scaled to match #GetAdvanceDistance().
 
	 */
 
	static FORCEINLINE uint GetAdvanceSpeed(uint speed)
 
	{
 
		return speed * 3 / 4;
 
	}
 

	
 
	/**
 
	 * Determines the vehicle "progress" needed for moving a step.
 
	 *
 
	 * Together with #GetAdvanceSpeed() this function is a replacement for #GetOldAdvanceSpeed().
 
	 *
 
	 * @return distance to drive for a movement step on the map.
 
	 */
 
	FORCEINLINE uint GetAdvanceDistance()
 
	{
 
		return (this->direction & 1) ? 192 : 256;
 
	}
 

	
 
	/**
 
	 * Sets the expense type associated to this vehicle type
 
	 * @param income whether this is income or (running) expenses of the vehicle
 
	 */
0 comments (0 inline, 0 general)