From 07c373d60a9f2d262617dbfdf719499687aeea73 Mon Sep 17 00:00:00 2001 From: terkhen Date: Sat, 6 Mar 2010 12:44:30 +0000 Subject: [PATCH] (svn r19339) -Codechange: Move acceleration functions to GroundVehicle. --- projects/openttd_vs80.vcproj | 4 + projects/openttd_vs90.vcproj | 4 + source.list | 1 + src/ground_vehicle.cpp | 150 +++++++++++++++++++++++++++++++++++ src/ground_vehicle.hpp | 3 + src/train.h | 5 +- src/train_cmd.cpp | 128 ------------------------------ 7 files changed, 164 insertions(+), 131 deletions(-) create mode 100644 src/ground_vehicle.cpp diff --git a/projects/openttd_vs80.vcproj b/projects/openttd_vs80.vcproj index 3bd155680a..c9fec0861b 100644 --- a/projects/openttd_vs80.vcproj +++ b/projects/openttd_vs80.vcproj @@ -571,6 +571,10 @@ RelativePath=".\..\src\gfxinit.cpp" > + + diff --git a/projects/openttd_vs90.vcproj b/projects/openttd_vs90.vcproj index f95dd212a4..a3c51ea7e1 100644 --- a/projects/openttd_vs90.vcproj +++ b/projects/openttd_vs90.vcproj @@ -568,6 +568,10 @@ RelativePath=".\..\src\gfxinit.cpp" > + + diff --git a/source.list b/source.list index 66c1216881..483791309b 100644 --- a/source.list +++ b/source.list @@ -28,6 +28,7 @@ gamelog.cpp genworld.cpp gfx.cpp gfxinit.cpp +ground_vehicle.cpp heightmap.cpp highscore.cpp ini.cpp diff --git a/src/ground_vehicle.cpp b/src/ground_vehicle.cpp new file mode 100644 index 0000000000..1ab6da9da2 --- /dev/null +++ b/src/ground_vehicle.cpp @@ -0,0 +1,150 @@ +/* $Id$ */ + +/* + * This file is part of OpenTTD. + * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2. + * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see . + */ + +/** @file ground_vehicle.cpp Implementation of GroundVehicle. */ + +#include "stdafx.h" +#include "train.h" +#include "ground_vehicle.hpp" +#include "window_type.h" +#include "vehicle_gui.h" +#include "window_func.h" + +/** + * Recalculates the cached total power of a vehicle. Should be called when the consist is changed. + */ +template +void GroundVehicle::PowerChanged() +{ + assert(this->First() == this); + const T *v = T::From(this); + + uint32 total_power = 0; + uint32 max_te = 0; + uint32 number_of_parts = 0; + uint16 max_track_speed = v->GetInitialMaxSpeed(); + + for (const T *u = v; u != NULL; u = u->Next()) { + uint32 current_power = u->GetPower(); + total_power += current_power; + + /* Only powered parts add tractive effort. */ + if (current_power > 0) max_te += u->GetWeight() * u->GetTractiveEffort(); + total_power += u->GetPoweredPartPower(v); + number_of_parts++; + + /* Get minimum max speed for this track. */ + uint16 track_speed = u->GetMaxTrackSpeed(); + if (track_speed > 0) max_track_speed = min(max_track_speed, track_speed); + } + + this->acc_cache.cached_axle_resistance = 60 * number_of_parts; + this->acc_cache.cached_air_drag = 20 + 3 * number_of_parts; + + max_te *= 10000; // Tractive effort in (tonnes * 1000 * 10 =) N. + max_te /= 256; // Tractive effort is a [0-255] coefficient. + if (this->acc_cache.cached_power != total_power || this->acc_cache.cached_max_te != max_te) { + /* Stop the vehicle if it has no power. */ + if (total_power == 0) this->vehstatus |= VS_STOPPED; + + this->acc_cache.cached_power = total_power; + this->acc_cache.cached_max_te = max_te; + SetWindowDirty(WC_VEHICLE_DETAILS, this->index); + SetWindowWidgetDirty(WC_VEHICLE_VIEW, this->index, VVW_WIDGET_START_STOP_VEH); + } + + this->acc_cache.cached_max_track_speed = max_track_speed; +} + +/** + * Recalculates the cached weight of a vehicle and its parts. Should be called each time the cargo on + * the consist changes. + */ +template +void GroundVehicle::CargoChanged() +{ + assert(this->First() == this); + uint32 weight = 0; + + for (T *u = T::From(this); u != NULL; u = u->Next()) { + uint32 current_weight = u->GetWeight(); + weight += current_weight; + u->acc_cache.cached_slope_resistance = current_weight * u->GetSlopeSteepness(); + } + + /* Store consist weight in cache. */ + this->acc_cache.cached_weight = weight; + + /* Now update vehicle power (tractive effort is dependent on weight). */ + this->PowerChanged(); +} + +/** + * Calculates the acceleration of the vehicle under its current conditions. + * @return Current acceleration of the vehicle. + */ +template +int GroundVehicle::GetAcceleration() const +{ + /* Templated class used for function calls for performance reasons. */ + const T *v = T::From(this); + int32 speed = v->GetCurrentSpeed(); + + /* Weight is stored in tonnes. */ + int32 mass = this->acc_cache.cached_weight; + + /* Power is stored in HP, we need it in watts. */ + int32 power = this->acc_cache.cached_power * 746; + + int32 resistance = 0; + + bool maglev = v->GetAccelerationType() == 2; + + const int area = 120; + if (!maglev) { + resistance = (13 * mass) / 10; + resistance += this->acc_cache.cached_axle_resistance; + resistance += (v->GetRollingFriction() * mass * speed) / 1000; + resistance += (area * this->acc_cache.cached_air_drag * speed * speed) / 10000; + } else { + resistance += (area * this->acc_cache.cached_air_drag * speed * speed) / 20000; + } + + resistance += v->GetSlopeResistance(); + resistance *= 4; //[N] + + /* This value allows to know if the vehicle is accelerating or braking. */ + AccelStatus mode = v->GetAccelerationStatus(); + + const int max_te = this->acc_cache.cached_max_te; // [N] + int force; + if (speed > 0) { + if (!maglev) { + force = power / speed; //[N] + force *= 22; + force /= 10; + if (mode == AS_ACCEL && force > max_te) force = max_te; + } else { + force = power / 25; + } + } else { + /* "Kickoff" acceleration. */ + force = (mode == AS_ACCEL && !maglev) ? min(max_te, power) : power; + force = max(force, (mass * 8) + resistance); + } + + if (mode == AS_ACCEL) { + return (force - resistance) / (mass * 2); + } else { + return min(-force - resistance, -10000) / mass; + } +} + +/* Instantiation for Train */ +template struct GroundVehicle; diff --git a/src/ground_vehicle.hpp b/src/ground_vehicle.hpp index 200d378303..c87dbf76f1 100644 --- a/src/ground_vehicle.hpp +++ b/src/ground_vehicle.hpp @@ -49,6 +49,9 @@ struct GroundVehicle : public SpecializedVehicle { */ GroundVehicle() : SpecializedVehicle() {} + void PowerChanged(); + void CargoChanged(); + int GetAcceleration() const; }; #endif /* GROUND_VEHICLE_HPP */ diff --git a/src/train.h b/src/train.h index bbb8ab3e90..30226e605d 100644 --- a/src/train.h +++ b/src/train.h @@ -110,6 +110,8 @@ struct Train : public GroundVehicle { /** We want to 'destruct' the right class. */ virtual ~Train() { this->PreDestructor(); } + friend struct GroundVehicle; // GroundVehicle needs to use the acceleration functions defined at Train. + const char *GetTypeString() const { return "train"; } void MarkDirty(); void UpdateDeltaXY(Direction direction); @@ -135,15 +137,12 @@ struct Train : public GroundVehicle { int GetCurveSpeedLimit() const; void ConsistChanged(bool same_length); - void CargoChanged(); - void PowerChanged(); int UpdateSpeed(); void UpdateAcceleration(); int GetCurrentMaxSpeed() const; - int GetAcceleration() const; /** * enum to handle train subtypes diff --git a/src/train_cmd.cpp b/src/train_cmd.cpp index 90ff4dd1ce..39ef3c33fb 100644 --- a/src/train_cmd.cpp +++ b/src/train_cmd.cpp @@ -88,75 +88,6 @@ byte FreightWagonMult(CargoID cargo) return _settings_game.vehicle.freight_trains; } - -/** - * Recalculates the cached total power of a train. Should be called when the consist is changed - */ -void Train::PowerChanged() -{ - assert(this->First() == this); - - uint32 total_power = 0; - uint32 max_te = 0; - uint32 number_of_parts = 0; - uint16 max_track_speed = this->GetInitialMaxSpeed(); - - for (const Train *u = this; u != NULL; u = u->Next()) { - uint32 current_power = u->GetPower(); - total_power += current_power; - - /* Only powered parts add tractive effort */ - if (current_power > 0) max_te += u->GetWeight() * u->GetTractiveEffort(); - total_power += u->GetPoweredPartPower(this); - number_of_parts++; - - /* Get minimum max speed for this track */ - uint16 track_speed = u->GetMaxTrackSpeed(); - if (track_speed > 0) max_track_speed = min(max_track_speed, track_speed); - } - - this->acc_cache.cached_axle_resistance = 60 * number_of_parts; - this->acc_cache.cached_air_drag = 20 + 3 * number_of_parts; - - max_te *= 10000; // Tractive effort in (tonnes * 1000 * 10 =) N - max_te /= 256; // Tractive effort is a [0-255] coefficient - if (this->acc_cache.cached_power != total_power || this->acc_cache.cached_max_te != max_te) { - /* Stop the vehicle if it has no power */ - if (total_power == 0) this->vehstatus |= VS_STOPPED; - - this->acc_cache.cached_power = total_power; - this->acc_cache.cached_max_te = max_te; - SetWindowDirty(WC_VEHICLE_DETAILS, this->index); - SetWindowWidgetDirty(WC_VEHICLE_VIEW, this->index, VVW_WIDGET_START_STOP_VEH); - } - - this->acc_cache.cached_max_track_speed = max_track_speed; -} - - -/** - * Recalculates the cached weight of a train and its vehicles. Should be called each time the cargo on - * the consist changes. - */ -void Train::CargoChanged() -{ - assert(this->First() == this); - uint32 weight = 0; - - for (Train *u = this; u != NULL; u = u->Next()) { - uint32 current_weight = u->GetWeight(); - weight += current_weight; - u->acc_cache.cached_slope_resistance = current_weight * u->GetSlopeSteepness(); - } - - /* store consist weight in cache */ - this->acc_cache.cached_weight = weight; - - /* Now update train power (tractive effort is dependent on weight) */ - this->PowerChanged(); -} - - /** Logs a bug in GRF and shows a warning message if this * is for the first time this happened. * @param u first vehicle of chain @@ -501,65 +432,6 @@ int Train::GetCurrentMaxSpeed() const return min(max_speed, this->acc_cache.cached_max_track_speed); } -/** - * Calculates the acceleration of the vehicle under its current conditions. - * @return Current acceleration of the vehicle. - */ - -int Train::GetAcceleration() const -{ - int32 speed = this->GetCurrentSpeed(); - - /* Weight is stored in tonnes */ - int32 mass = this->acc_cache.cached_weight; - - /* Power is stored in HP, we need it in watts. */ - int32 power = this->acc_cache.cached_power * 746; - - int32 resistance = 0; - - bool maglev = this->GetAccelerationType() == 2; - - const int area = 120; - if (!maglev) { - resistance = (13 * mass) / 10; - resistance += this->acc_cache.cached_axle_resistance; - resistance += (this->GetRollingFriction() * mass * speed) / 1000; - resistance += (area * this->acc_cache.cached_air_drag * speed * speed) / 10000; - } else { - resistance += (area * this->acc_cache.cached_air_drag * speed * speed) / 20000; - } - - resistance += this->GetSlopeResistance(); - resistance *= 4; //[N] - - /* This value allows to know if the vehicle is accelerating or braking. */ - AccelStatus mode = this->GetAccelerationStatus(); - - const int max_te = this->acc_cache.cached_max_te; // [N] - int force; - if (speed > 0) { - if (!maglev) { - force = power / speed; //[N] - force *= 22; - force /= 10; - if (mode == AS_ACCEL && force > max_te) force = max_te; - } else { - force = power / 25; - } - } else { - /* "kickoff" acceleration */ - force = (mode == AS_ACCEL && !maglev) ? min(max_te, power) : power; - force = max(force, (mass * 8) + resistance); - } - - if (mode == AS_ACCEL) { - return (force - resistance) / (mass * 2); - } else { - return min(-force - resistance, -10000) / mass; - } -} - void Train::UpdateAcceleration() { assert(this->IsFrontEngine());