Skip to content

Commit

Permalink
Rewritten camera smoothing, refactoring, reverted previous changes
Browse files Browse the repository at this point in the history
  • Loading branch information
deathkiller committed Jan 8, 2024
1 parent 5b7710e commit 1ab70b2
Show file tree
Hide file tree
Showing 13 changed files with 154 additions and 117 deletions.
68 changes: 45 additions & 23 deletions Sources/Jazz2/LevelHandler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ namespace Jazz2
LevelHandler::LevelHandler(IRootController* root)
: _root(root), _eventSpawner(this), _difficulty(GameDifficulty::Default), _isReforged(false), _cheatsUsed(false), _checkpointCreated(false),
_cheatsBufferLength(0), _nextLevelType(ExitType::None), _nextLevelTime(0.0f), _elapsedFrames(0.0f), _checkpointFrames(0.0f),
_shakeDuration(0.0f), _waterLevel(FLT_MAX), _ambientLightTarget(1.0f), _weatherType(WeatherType::None),
_cameraResponsiveness(1.0f, 1.0f), _shakeDuration(0.0f), _waterLevel(FLT_MAX), _ambientLightTarget(1.0f), _weatherType(WeatherType::None),
_downsamplePass(this), _blurPass1(this), _blurPass2(this), _blurPass3(this), _blurPass4(this),
_pressedKeys((uint32_t)KeySym::COUNT), _pressedActions(0), _overrideActions(0), _playerFrozenEnabled(false),
_lastPressedNumericKey(UINT32_MAX)
Expand Down Expand Up @@ -250,7 +250,7 @@ namespace Jazz2

Vector2i levelBounds = _tileMap->GetLevelBounds();
_levelBounds = Recti(0, 0, levelBounds.X, levelBounds.Y);
_viewBounds = Rectf((float)_levelBounds.X, (float)_levelBounds.Y, (float)_levelBounds.W, (float)_levelBounds.H);
_viewBounds = _levelBounds.As<float>();
_viewBoundsTarget = _viewBounds;

_ambientColor = descriptor.AmbientColor;
Expand Down Expand Up @@ -399,7 +399,7 @@ namespace Jazz2
TileMap::DestructibleDebris debris = { };
debris.Pos = debrisPos;
debris.Depth = MainPlaneZ - 100 + (uint16_t)(200 * scale);
debris.Size = Vector2f((float)resBase->FrameDimensions.X, (float)resBase->FrameDimensions.Y);
debris.Size = resBase->FrameDimensions.As<float>();
debris.Speed = Vector2f(speedX, speedY);
debris.Acceleration = Vector2f(0.0f, 0.0f);

Expand Down Expand Up @@ -438,15 +438,15 @@ namespace Jazz2
TileMap::DestructibleDebris debris = { };
debris.Pos = debrisPos;
debris.Depth = MainPlaneZ - 100 + (uint16_t)(200 * scale);
debris.Size = Vector2f((float)resBase->FrameDimensions.X, (float)resBase->FrameDimensions.Y);
debris.Size = resBase->FrameDimensions.As<float>();
debris.Speed = Vector2f(speedX, speedY);
debris.Acceleration = Vector2f(accel, -std::abs(accel));

debris.Scale = scale;
debris.ScaleSpeed = 0.0f;
debris.Angle = Random().FastFloat(0.0f, fTwoPi);
debris.AngleSpeed = speedX * 0.02f,
debris.Alpha = 1.0f;
debris.AngleSpeed = speedX * 0.02f;
debris.Alpha = 1.0f;
debris.AlphaSpeed = 0.0f;

debris.Time = 180.0f;
Expand Down Expand Up @@ -802,15 +802,13 @@ namespace Jazz2

Vector2f focusPos = actor->_pos;
if (!fast) {
_cameraPos.X = focusPos.X;
_cameraPos.Y = focusPos.Y;
_cameraPos = focusPos;
_cameraLastPos = _cameraPos;
_cameraDistanceFactor.X = 0.0f;
_cameraDistanceFactor.Y = 0.0f;
_cameraDistanceFactor = Vector2f(0.0f, 0.0f);
_cameraResponsiveness = Vector2f(1.0f, 1.0f);
} else {
Vector2f diff = _cameraLastPos - _cameraPos;
_cameraPos.X = focusPos.X;
_cameraPos.Y = focusPos.Y;
_cameraPos = focusPos;
_cameraLastPos = _cameraPos + diff;
}
}
Expand Down Expand Up @@ -1066,7 +1064,7 @@ namespace Jazz2
WarpCameraToTarget(player, true);
} else {
Vector2f pos = player->GetPos();
if (Vector2f(prevPos.X - pos.X, prevPos.Y - pos.Y).Length() > 250.0f) {
if ((prevPos - pos).Length() > 250.0f) {
WarpCameraToTarget(player);
}
}
Expand Down Expand Up @@ -1518,7 +1516,7 @@ namespace Jazz2
return;
}

auto targetObj = _players[0];
auto* targetObj = _players[0];

// The position to focus on
Vector2f focusPos = targetObj->_pos;
Expand All @@ -1544,6 +1542,8 @@ namespace Jazz2
{
ZoneScopedC(0x4876AF);

constexpr float ResponsivenessChange = 0.04f;
constexpr float ResponsivenessMin = 0.3f;
constexpr float SlowRatioX = 0.3f;
constexpr float SlowRatioY = 0.3f;
constexpr float FastRatioX = 0.2f;
Expand Down Expand Up @@ -1571,11 +1571,33 @@ namespace Jazz2
Vector2i halfView = _view->size() / 2;
Vector2f focusPos = targetObj->_pos;
Vector2f focusSpeed = targetObj->_speed;
Vector2f focusVelocity = Vector2f(std::abs(focusSpeed.X), std::abs(focusSpeed.Y));

// Camera responsiveness (smoothing unexpected movements)
if (focusVelocity.X < 1.0f) {
if (_cameraResponsiveness.X > ResponsivenessMin) {
_cameraResponsiveness.X = std::max(_cameraResponsiveness.X - ResponsivenessChange * timeMult, ResponsivenessMin);
}
} else {
if (_cameraResponsiveness.X < 1.0f) {
_cameraResponsiveness.X = std::min(_cameraResponsiveness.X + ResponsivenessChange * timeMult, 1.0f);
}
}
if (focusVelocity.Y < 1.0f) {
if (_cameraResponsiveness.Y > ResponsivenessMin) {
_cameraResponsiveness.Y = std::max(_cameraResponsiveness.Y - ResponsivenessChange * timeMult, ResponsivenessMin);
}
} else {
if (_cameraResponsiveness.Y < 1.0f) {
_cameraResponsiveness.Y = std::min(_cameraResponsiveness.Y + ResponsivenessChange * timeMult, 1.0f);
}
}

_cameraLastPos = focusPos;
_cameraLastPos.X = lerpByTime(_cameraLastPos.X, focusPos.X, _cameraResponsiveness.X, timeMult);
_cameraLastPos.Y = lerpByTime(_cameraLastPos.Y, focusPos.Y, _cameraResponsiveness.Y, timeMult);

_cameraDistanceFactor.X = lerpByTime(_cameraDistanceFactor.X, focusSpeed.X * 8.0f, (std::abs(focusSpeed.X) < 2.0f ? SlowRatioX : FastRatioX), timeMult);
_cameraDistanceFactor.Y = lerpByTime(_cameraDistanceFactor.Y, focusSpeed.Y * 5.0f, (std::abs(focusSpeed.Y) < 2.0f ? SlowRatioY : FastRatioY), timeMult);
_cameraDistanceFactor.X = lerpByTime(_cameraDistanceFactor.X, focusSpeed.X * 8.0f, (focusVelocity.X < 2.0f ? SlowRatioX : FastRatioX), timeMult);
_cameraDistanceFactor.Y = lerpByTime(_cameraDistanceFactor.Y, focusSpeed.Y * 5.0f, (focusVelocity.Y < 2.0f ? SlowRatioY : FastRatioY), timeMult);

if (_shakeDuration > 0.0f) {
_shakeDuration -= timeMult;
Expand Down Expand Up @@ -1607,11 +1629,11 @@ namespace Jazz2
_cameraPos.Y = std::floor(_viewBounds.Y + _viewBounds.H * 0.5f + _shakeOffset.Y);
}

_camera->setView(_cameraPos - Vector2f(halfView.X, halfView.Y), 0.0f, 1.0f);
_camera->setView(_cameraPos - halfView.As<float>(), 0.0f, 1.0f);

// Update audio listener position
IAudioDevice& device = theServiceLocator().audioDevice();
device.updateListener(Vector3f(_cameraPos.X, _cameraPos.Y, 0.0f), Vector3f(focusSpeed.X, focusSpeed.Y, 0.0f));
device.updateListener(Vector3f(_cameraPos, 0.0f), Vector3f(focusSpeed, 0.0f));
}

void LevelHandler::LimitCameraView(int left, int width)
Expand All @@ -1624,10 +1646,10 @@ namespace Jazz2
}

if (left == 0 && width == 0) {
_viewBounds = Rectf((float)_levelBounds.X, (float)_levelBounds.Y, (float)_levelBounds.W, (float)_levelBounds.H);
_viewBounds = _levelBounds.As<float>();
_viewBoundsTarget = _viewBounds;
} else {
Rectf bounds = Rectf((float)_levelBounds.X, (float)_levelBounds.Y, (float)_levelBounds.W, (float)_levelBounds.H);
Rectf bounds = _levelBounds.As<float>();
float viewWidth = (float)_view->size().X;
if (bounds.W < viewWidth) {
bounds.X -= (viewWidth - bounds.W);
Expand Down Expand Up @@ -2077,7 +2099,7 @@ namespace Jazz2
{
Vector2i size = _target->size();

auto instanceBlock = _renderCommand.material().uniformBlock(Material::InstanceBlockName);
auto* instanceBlock = _renderCommand.material().uniformBlock(Material::InstanceBlockName);
instanceBlock->uniform(Material::TexRectUniformName)->setFloatValue(1.0f, 0.0f, 1.0f, 0.0f);
instanceBlock->uniform(Material::SpriteSizeUniformName)->setFloatValue(static_cast<float>(size.X), static_cast<float>(size.Y));
instanceBlock->uniform(Material::ColorUniformName)->setFloatVector(Colorf::White.Data());
Expand Down Expand Up @@ -2164,7 +2186,7 @@ namespace Jazz2
command.material().setTexture(4, *_owner->_noiseTexture);
}

auto instanceBlock = command.material().uniformBlock(Material::InstanceBlockName);
auto* instanceBlock = command.material().uniformBlock(Material::InstanceBlockName);
instanceBlock->uniform(Material::TexRectUniformName)->setFloatValue(1.0f, 0.0f, 1.0f, 0.0f);
instanceBlock->uniform(Material::SpriteSizeUniformName)->setFloatValue(_size.X, _size.Y);
instanceBlock->uniform(Material::ColorUniformName)->setFloatVector(Colorf::White.Data());
Expand Down
1 change: 1 addition & 0 deletions Sources/Jazz2/LevelHandler.h
Original file line number Diff line number Diff line change
Expand Up @@ -297,6 +297,7 @@ namespace Jazz2
Vector2f _cameraPos;
Vector2f _cameraLastPos;
Vector2f _cameraDistanceFactor;
Vector2f _cameraResponsiveness;
float _shakeDuration;
Vector2f _shakeOffset;
float _waterLevel;
Expand Down
3 changes: 0 additions & 3 deletions Sources/Jazz2/PreferencesCache.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ namespace Jazz2
bool PreferencesCache::ShowPlayerTrails = true;
bool PreferencesCache::LowGraphicsQuality = false;
bool PreferencesCache::UnalignedViewport = false;
bool PreferencesCache::UnalignedParallaxLayers = false;
bool PreferencesCache::EnableReforgedGameplay = true;
bool PreferencesCache::EnableReforgedHUD = true;
bool PreferencesCache::EnableReforgedMainMenu = true;
Expand Down Expand Up @@ -155,7 +154,6 @@ namespace Jazz2
ShowPlayerTrails = ((boolOptions & BoolOptions::ShowPlayerTrails) == BoolOptions::ShowPlayerTrails);
LowGraphicsQuality = ((boolOptions & BoolOptions::LowGraphicsQuality) == BoolOptions::LowGraphicsQuality);
UnalignedViewport = ((boolOptions & BoolOptions::UnalignedViewport) == BoolOptions::UnalignedViewport);
UnalignedParallaxLayers = ((boolOptions & BoolOptions::UnalignedParallaxLayers) == BoolOptions::UnalignedParallaxLayers);
EnableReforgedGameplay = ((boolOptions & BoolOptions::EnableReforgedGameplay) == BoolOptions::EnableReforgedGameplay);
EnableLedgeClimb = ((boolOptions & BoolOptions::EnableLedgeClimb) == BoolOptions::EnableLedgeClimb);
WeaponWheel = ((boolOptions & BoolOptions::EnableWeaponWheel) == BoolOptions::EnableWeaponWheel ? WeaponWheelStyle::Enabled : WeaponWheelStyle::Disabled);
Expand Down Expand Up @@ -343,7 +341,6 @@ namespace Jazz2
if (ShowPlayerTrails) boolOptions |= BoolOptions::ShowPlayerTrails;
if (LowGraphicsQuality) boolOptions |= BoolOptions::LowGraphicsQuality;
if (UnalignedViewport) boolOptions |= BoolOptions::UnalignedViewport;
if (UnalignedParallaxLayers) boolOptions |= BoolOptions::UnalignedParallaxLayers;
if (EnableReforgedGameplay) boolOptions |= BoolOptions::EnableReforgedGameplay;
if (EnableLedgeClimb) boolOptions |= BoolOptions::EnableLedgeClimb;
if (WeaponWheel != WeaponWheelStyle::Disabled) boolOptions |= BoolOptions::EnableWeaponWheel;
Expand Down
2 changes: 0 additions & 2 deletions Sources/Jazz2/PreferencesCache.h
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,6 @@ namespace Jazz2
static bool ShowPlayerTrails;
static bool LowGraphicsQuality;
static bool UnalignedViewport;
static bool UnalignedParallaxLayers;

// Gameplay
static bool EnableReforgedGameplay;
Expand Down Expand Up @@ -138,7 +137,6 @@ namespace Jazz2
ShowPlayerTrails = 0x08,
LowGraphicsQuality = 0x10,
UnalignedViewport = 0x20,
UnalignedParallaxLayers = 0x40,

EnableReforgedGameplay = 0x100,
EnableLedgeClimb = 0x200,
Expand Down
16 changes: 4 additions & 12 deletions Sources/Jazz2/Tiles/TileMap.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -602,7 +602,6 @@ namespace Jazz2::Tiles
Vector2f viewCenter = _owner->GetCameraPos();

Vector2i tileCount = layer.LayoutSize;
Vector2i tileSize = Vector2i(TileSet::DefaultTileSize, TileSet::DefaultTileSize);

// Get current layer offsets and speeds
float loX = layer.Description.OffsetX;
Expand All @@ -617,18 +616,16 @@ namespace Jazz2::Tiles
constexpr float PerspectiveSpeedY = 0.16f;
RenderTexturedBackground(renderQueue, layer, x1 * PerspectiveSpeedX + loX, y1 * PerspectiveSpeedY + loY);
} else {
float xt, yt; bool xAlign, yAlign;
float xt, yt;
switch (layer.Description.SpeedModelX) {
case LayerSpeedModel::AlwaysOnTop:
xt = -HardcodedOffset;
xAlign = false;
break;
case LayerSpeedModel::FitLevel: {
float progress = (float)viewCenter.X / (_layers[_sprLayerIndex].LayoutSize.X * TileSet::DefaultTileSize);
xt = std::clamp(progress, 0.0f, 1.0f)
* ((layer.LayoutSize.X * TileSet::DefaultTileSize) - viewSize.X + HardcodedOffset)
+ loX;
xAlign = !PreferencesCache::UnalignedViewport && !PreferencesCache::UnalignedParallaxLayers;
break;
}
case LayerSpeedModel::SpeedMultipliers: {
Expand All @@ -639,25 +636,21 @@ namespace Jazz2::Tiles
xt = progress
* ((layer.LayoutSize.X * TileSet::DefaultTileSize) - HardcodedOffset)
+ loX;
xAlign = !PreferencesCache::UnalignedViewport && !PreferencesCache::UnalignedParallaxLayers;
break;
}
default:
xt = TranslateCoordinate(x1, layer.Description.SpeedX, loX, viewSize.X, false);
xAlign = !PreferencesCache::UnalignedViewport && (!PreferencesCache::UnalignedParallaxLayers || layer.Description.SpeedX == 1.0f);
break;
}
switch (layer.Description.SpeedModelY) {
case LayerSpeedModel::AlwaysOnTop:
yt = -HardcodedOffset;
yAlign = false;
break;
case LayerSpeedModel::FitLevel: {
float progress = (float)viewCenter.Y / (_layers[_sprLayerIndex].LayoutSize.Y * TileSet::DefaultTileSize);
yt = std::clamp(progress, 0.0f, 1.0f)
* ((layer.LayoutSize.Y * TileSet::DefaultTileSize) - viewSize.Y + HardcodedOffset)
+ loY;
yAlign = !PreferencesCache::UnalignedViewport && !PreferencesCache::UnalignedParallaxLayers;
break;
}
case LayerSpeedModel::SpeedMultipliers: {
Expand All @@ -668,7 +661,6 @@ namespace Jazz2::Tiles
yt = progress
* ((layer.LayoutSize.Y * TileSet::DefaultTileSize) - HardcodedOffset)
+ loY;
yAlign = !PreferencesCache::UnalignedViewport && !PreferencesCache::UnalignedParallaxLayers;
break;
}
default:
Expand All @@ -680,7 +672,6 @@ namespace Jazz2::Tiles
}*/

yt = TranslateCoordinate(y1, layer.Description.SpeedY, loY, viewSize.Y, true);
yAlign = !PreferencesCache::UnalignedViewport && (!PreferencesCache::UnalignedParallaxLayers || layer.Description.SpeedY == 1.0f);
break;
}

Expand Down Expand Up @@ -787,8 +778,9 @@ namespace Jazz2::Tiles
instanceBlock->uniform(Material::ColorUniformName)->setFloatVector(color.Data());

float x2r = x2, y2r = y2;
if (xAlign) x2r = std::floor(x2r);
if (yAlign) y2r = std::floor(y2r);
if (!PreferencesCache::UnalignedViewport) {
x2r = std::floor(x2r); y2r = std::floor(y2r);
}

command->setTransformation(Matrix4x4f::Translation(x2r, y2r, 0.0f));
command->setLayer(layer.Description.Depth);
Expand Down
11 changes: 2 additions & 9 deletions Sources/Jazz2/UI/Menu/GraphicsOptionsSection.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ namespace Jazz2::UI::Menu
case GraphicsOptionsItemType::Antialiasing: enabled = (PreferencesCache::ActiveRescaleMode & RescaleMode::UseAntialiasing) == RescaleMode::UseAntialiasing; break;
case GraphicsOptionsItemType::LowGraphicsQuality: customText = (enabled ? _("Low") : _("High")); break;
case GraphicsOptionsItemType::ShowPlayerTrails: enabled = PreferencesCache::ShowPlayerTrails; break;
case GraphicsOptionsItemType::UnalignedViewport: customText = (PreferencesCache::UnalignedViewport ? _("Enabled") : (PreferencesCache::UnalignedParallaxLayers ? _("Parallax Layers Only") : _("Disabled"))); break;
case GraphicsOptionsItemType::UnalignedViewport: enabled = PreferencesCache::UnalignedViewport; break;
case GraphicsOptionsItemType::KeepAspectRatioInCinematics: enabled = PreferencesCache::KeepAspectRatioInCinematics; break;
case GraphicsOptionsItemType::ShowPerformanceMetrics: enabled = PreferencesCache::ShowPerformanceMetrics; break;
}
Expand Down Expand Up @@ -175,14 +175,7 @@ namespace Jazz2::UI::Menu
_root->PlaySfx("MenuSelect"_s, 0.6f);
break;
case GraphicsOptionsItemType::UnalignedViewport:
if (PreferencesCache::UnalignedViewport) {
PreferencesCache::UnalignedViewport = false;
PreferencesCache::UnalignedParallaxLayers = true;
} else if (PreferencesCache::UnalignedParallaxLayers) {
PreferencesCache::UnalignedParallaxLayers = false;
} else {
PreferencesCache::UnalignedViewport = true;
}
PreferencesCache::UnalignedViewport = !PreferencesCache::UnalignedViewport;
_isDirty = true;
_animation = 0.0f;
_root->PlaySfx("MenuSelect"_s, 0.6f);
Expand Down
3 changes: 2 additions & 1 deletion Sources/nCine/Application.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -676,7 +676,8 @@ namespace nCine

if (appCfg_.frameLimit > 0) {
FrameMarkStart("Frame limiting");
#if defined(DEATH_TARGET_WINDOWS)
#if 0 //defined(DEATH_TARGET_WINDOWS)
// TODO: This code sometimes doesn't work properly
const std::uint64_t clockFreq = static_cast<std::uint64_t>(clock().frequency());
const std::uint64_t frameTimeDuration = (clockFreq / static_cast<std::uint64_t>(appCfg_.frameLimit));
const std::int64_t remainingTime = (std::int64_t)frameTimeDuration - (std::int64_t)frameTimer_->frameDurationAsTicks();
Expand Down
9 changes: 7 additions & 2 deletions Sources/nCine/Primitives/AABB.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,17 @@ namespace nCine
AABB()
: L(0), T(0), R(0), B(0) { }

AABB(S ll, S tt, S rr, S bb)
: L(ll), T(tt), R(rr), B(bb) { }
AABB(S l, S t, S r, S b)
: L(l), T(t), R(r), B(b) { }

AABB(const Vector2<S>& min, const Vector2<S>& max)
: L(std::min(min.X, max.X)), T(std::min(min.Y, max.Y)), R(std::max(min.X, max.X)), B(std::max(min.Y, max.Y)) { }

template<class U>
AABB<U> As() {
return AABB<S>(static_cast<U>(L), static_cast<U>(T), static_cast<U>(R), static_cast<U>(B));
}

S GetWidth() const {
return R - L;
}
Expand Down
Loading

0 comments on commit 1ab70b2

Please sign in to comment.