Skip to content

Commit

Permalink
Rotation speed curves for arm and vehicles
Browse files Browse the repository at this point in the history
  • Loading branch information
frutiemax92 committed May 21, 2023
1 parent 9ba7b8f commit e87ed9a
Show file tree
Hide file tree
Showing 4 changed files with 95 additions and 25 deletions.
103 changes: 80 additions & 23 deletions src/openrct2/ride/thrill/Condor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#include "../Vehicle.h"
#include "../VehiclePaint.h"
#include "../RideBoundboxBuilder.h"
#include "../../util/Util.h"

#include <algorithm>
#include <cstring>
Expand Down Expand Up @@ -53,11 +54,13 @@ static constexpr int CondorRadius = 48;
static constexpr int CondorCenter = 96;
static constexpr float CondorAngleDelta = 0.09817f;

static std::array<CoordsXY, 64> CalculateLocations()
static constexpr int NumArmSprites = 16;

static std::array<CoordsXY, NumArmSprites*4> CalculateLocations()
{
std::array<CoordsXY, 64> res;
std::array<CoordsXY, NumArmSprites*4> res;
int i = 0;
for (i = 0; i < 64; i++)
for (i = 0; i < NumArmSprites*4; i++)
{
res[i] = CoordsXY{ static_cast<int>(CondorCenter + CondorRadius * cos(i * CondorAngleDelta)),
static_cast<int>(CondorCenter + CondorRadius * sin(i * CondorAngleDelta)) };
Expand All @@ -66,18 +69,53 @@ static std::array<CoordsXY, 64> CalculateLocations()
}
static auto CondorLocations = CalculateLocations();

static constexpr int MaxAnimationFrameTime = 8;
static constexpr int NumArmSpritesSymmetry = 4;
static constexpr int NumVehicleAngles = 8;
static constexpr int NumCarsPerVehicle = 7;
static constexpr int NumCarsTiltAngles = 8;

// degrees/second
static constexpr float MaxVehicleRotationSpeed = 120;
static constexpr float MinVehicleRotationSpeed = 10;
static constexpr float MaxTowerRotationSpeed = 30;
static constexpr float MinTowerRotationSpeed = 10;

static constexpr int GetAnimationFrameTime(int currentHeight, int minHeight, int maxHeight)
static int GetTowerRotationFrameTime(int currentHeight, int minHeight, int maxHeight)
{
float progress = static_cast<float>(currentHeight - minHeight) / static_cast<float>(maxHeight - minHeight);
return (1.0f - MaxAnimationFrameTime) * progress + MaxAnimationFrameTime;

//spin faster at the middle point
float rotationSpeed = CubicLerp(
progress, -1.0f, 0.0f, 0.5f, 1.0f, MinTowerRotationSpeed, MinTowerRotationSpeed, MaxTowerRotationSpeed,
MinTowerRotationSpeed);

float rotationFrameTime = 1.0f / rotationSpeed / static_cast<float>(NumArmSprites) * NumArmSpritesSymmetry * 360.0f;
return static_cast<int>(rotationFrameTime);
}

static int GetVehicleRotationFrameTime(int currentHeight, int minHeight, int maxHeight)
{
float progress = static_cast<float>(currentHeight - minHeight) / static_cast<float>(maxHeight - minHeight);

//the max vehicle rotation speed is at the top
float rotationSpeed = CubicLerp(
progress, -1.0f, 0.0f, 1.0f, 2.0f, MinVehicleRotationSpeed, MinVehicleRotationSpeed, MaxVehicleRotationSpeed,
MaxVehicleRotationSpeed);

float rotationFrameTime = 1.0f / rotationSpeed / static_cast<float>(NumVehicleAngles) * static_cast<float>(NumCarsPerVehicle) * 360.0f;
return static_cast<int>(rotationFrameTime);
}

static int MaxVehicleRotationFrameTime = GetVehicleRotationFrameTime(0, 0, 100);
static int MinVehicleRotationFrameTime = GetVehicleRotationFrameTime(100, 0, 100);

// tilt angle is function of the vehicle roation speed
constexpr int NumTiltAngles = 8;
static uint8_t GetVehicleTilt(uint8_t rotationFrameTime)
static uint8_t GetVehicleTilt(int vehicleFrameTime)
{
return (MaxAnimationFrameTime / rotationFrameTime) - 1;
float progress = static_cast<float>(vehicleFrameTime - MinVehicleRotationFrameTime)
/ static_cast<float>(MaxVehicleRotationFrameTime - MinVehicleRotationFrameTime);
return Lerp(NumCarsTiltAngles - 1, 0, progress);
}

static void PaintCondorStructure(
Expand Down Expand Up @@ -106,24 +144,21 @@ static void PaintCondorStructure(
std::array<CoordsXY, 4>
offsets2 = { CoordsXY{ 50, 0 }, CoordsXY{ 0, -50 }, CoordsXY{ -50, 0 }, CoordsXY{ 0, 50 } };

const int NumVehicleAnimationFrames = 8;


auto condorRideData = static_cast<CondorRideData*>(ride.Data.get());
if (condorRideData != nullptr)
{
auto vehicleZ = condorRideData->VehiclesZ;
auto tilt = GetVehicleTilt(condorRideData->RotationFrameTime);
auto tilt = GetVehicleTilt(condorRideData->VehicleRotationFrameTime);
auto armsImageId = imageTemplate.WithIndex(
rideEntry->Cars[0].base_image_id + NumVehicleAnimationFrames * NumTiltAngles + (condorRideData->ArmRotation % 16));
rideEntry->Cars[0].base_image_id + NumVehicleAngles * NumTiltAngles + (condorRideData->ArmRotation % 16));
for (int i = 0; i < 4; i++)
{
int locationIndex = i * 16;
int locationIndex = i * NumArmSprites;
locationIndex += condorRideData->ArmRotation;
locationIndex %= 64;
locationIndex %= (NumArmSprites * 4);

auto imageId = imageTemplate.WithIndex(
rideEntry->Cars[0].base_image_id + tilt * NumVehicleAnimationFrames + condorRideData->QuadRotation[i]);
rideEntry->Cars[0].base_image_id + tilt * NumVehicleAngles + condorRideData->QuadRotation[i]);
PaintAddImageAsParent(
session, imageId,
{ -bbOffset.x + CondorLocations[locationIndex].x, -bbOffset.y + CondorLocations[locationIndex].y,
Expand Down Expand Up @@ -301,12 +336,14 @@ CondorRideData::CondorRideData()
, TowerTop(0)
, TowerBase(0)
, ArmRotation(0)
, RotationFrameTime(MaxAnimationFrameTime)
, ArmRotationCounter(0)
, TowerRotationCounter(0)
, SpinningTopCounter(0)
, VehicleRotationCounter(0)
{
QuadRotation = { 0, 0, 0, 0 };
InitialQuadRotation = QuadRotation[0];
TowerRotationFrameTime = GetTowerRotationFrameTime(0, 0, 100);
VehicleRotationFrameTime = GetVehicleRotationFrameTime(0, 0, 100);
}

static uint32_t CondorGetTowerHeight(const Vehicle& vehicle)
Expand Down Expand Up @@ -401,20 +438,28 @@ void CondorRideUpdateWating(Ride& ride)

static void UpdateRotation(CondorRideData* condorRideData)
{
condorRideData->RotationFrameTime = GetAnimationFrameTime(condorRideData->VehiclesZ, condorRideData->TowerBase, condorRideData->TowerTop);
condorRideData->ArmRotationCounter++;
condorRideData->TowerRotationFrameTime = GetTowerRotationFrameTime(condorRideData->VehiclesZ, condorRideData->TowerBase, condorRideData->TowerTop);
condorRideData->TowerRotationCounter++;

if (condorRideData->ArmRotationCounter >= condorRideData->RotationFrameTime)
if (condorRideData->TowerRotationCounter >= condorRideData->TowerRotationFrameTime)
{
condorRideData->ArmRotation++;
condorRideData->ArmRotation %= 64;
condorRideData->ArmRotationCounter = 0;
condorRideData->ArmRotation %= (NumArmSprites * 4);
condorRideData->TowerRotationCounter = 0;
}

condorRideData->VehicleRotationFrameTime = GetVehicleRotationFrameTime(
condorRideData->VehiclesZ, condorRideData->TowerBase, condorRideData->TowerTop);
condorRideData->VehicleRotationCounter++;

if (condorRideData->VehicleRotationCounter >= condorRideData->VehicleRotationFrameTime)
{
for (auto& quadRot : condorRideData->QuadRotation)
{
quadRot++;
quadRot %= 8;
}
condorRideData->VehicleRotationCounter = 0;
}
}

Expand All @@ -441,18 +486,26 @@ static void CondorRideUpdateFalling(Ride& ride)
if (condorRideData != nullptr)
{
int32_t height = condorRideData->VehiclesZ - 1;

auto oldArmRotation = condorRideData->ArmRotation;
UpdateRotation(condorRideData);

if (height < condorRideData->TowerBase)
{
height = condorRideData->TowerBase;

if (oldArmRotation % (NumArmSprites * 4) == 0)
condorRideData->ArmRotation = 0;

if (condorRideData->ArmRotation != 0)
condorRideData->State = CondorRideState::Falling;
else if (condorRideData->QuadRotation[0] != condorRideData->InitialQuadRotation)
condorRideData->State = CondorRideState::Falling;
else
{
condorRideData->State = CondorRideState::Waiting;
}


}
condorRideData->VehiclesZ = height;
Expand All @@ -466,6 +519,10 @@ static void CondorRideUpdateSpinningAtTop(Ride& ride)
if (condorRideData != nullptr)
{
UpdateRotation(condorRideData);

//dont spin the arms when at top
condorRideData->TowerRotationCounter = 0;

condorRideData->SpinningTopCounter++;
if (condorRideData->SpinningTopCounter >= SpinningTopTime)
{
Expand Down
6 changes: 4 additions & 2 deletions src/openrct2/ride/thrill/meta/Condor.h
Original file line number Diff line number Diff line change
Expand Up @@ -138,8 +138,10 @@ struct CondorRideData : public RideData
int32_t TowerTop;
int32_t TowerBase;
CondorRideState State;
int32_t RotationFrameTime;
int32_t ArmRotationCounter;
int32_t TowerRotationFrameTime;
int32_t VehicleRotationFrameTime;
int32_t TowerRotationCounter;
int32_t VehicleRotationCounter;
int32_t ArmRotation;
int32_t SpinningTopCounter;

Expand Down
10 changes: 10 additions & 0 deletions src/openrct2/util/Util.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -619,3 +619,13 @@ size_t StrCatFTime(char* buffer, size_t bufferSize, const char* format, const st
}
return 0;
}

float CubicLerp(float x, float x0, float x1, float x2, float x3, float y0, float y1, float y2, float y3)
{
float res = 0.0f;
res += (x - x1) * (x - x2) * (x - x3) / (x0 - x1) / (x0 - x2) / (x0 - x3) * y0;
res += (x - x0) * (x - x2) * (x - x3) / (x1 - x0) / (x1 - x2) / (x1 - x3) * y1;
res += (x - x0) * (x - x1) * (x - x3) / (x2 - x0) / (x2 - x1) / (x2 - x3) * y2;
res += (x - x0) * (x - x1) * (x - x2) / (x3 - x0) / (x3 - x1) / (x3 - x2) * y3;
return res;
}
1 change: 1 addition & 0 deletions src/openrct2/util/Util.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ money64 AddClamp_money64(money64 value, money64 value_to_add);

uint8_t Lerp(uint8_t a, uint8_t b, float t);
float FLerp(float a, float b, float t);
float CubicLerp(float x, float x0, float x1, float x2, float x3, float y0, float y1, float y2, float y3);
uint8_t SoftLight(uint8_t a, uint8_t b);

size_t StrCatFTime(char* buffer, size_t bufferSize, const char* format, const struct tm* tp);
Expand Down

0 comments on commit e87ed9a

Please sign in to comment.