Skip to content

Commit

Permalink
feat: camera clamp, lerp & fixed camera jittering with gaps
Browse files Browse the repository at this point in the history
  • Loading branch information
cherrynik committed Jul 3, 2024
1 parent f2fa7db commit 8d102ea
Show file tree
Hide file tree
Showing 10 changed files with 63 additions and 30 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ private static void RegisterTransformComponent(IServiceRegistry serviceRegistry)
serviceRegistry.RegisterTransient(_ => new TransformComponent());

serviceRegistry.RegisterSingleton(_ =>
new TransformComponent { Position = new(0, 4) }, "PlayerAnimations");
new TransformComponent { Position = new(0, 3) }, "PlayerAnimationsOffset");

serviceRegistry.RegisterSingleton(_ =>
new TransformComponent { Position = new(316, 116), Pivot = Sector.Up }, "PlayerEntity");
Expand Down Expand Up @@ -194,7 +194,7 @@ private static void RegisterCharacterAnimatorComponent(IServiceRegistry serviceR
const Sector facing = Sector.Right;

return new CharacterAnimatorComponent(facing, movementAnimations.IdleAnimations[facing],
factory.GetInstance<TransformComponent>("PlayerAnimations"));
factory.GetInstance<TransformComponent>("PlayerAnimationsOffset"));
}, "PlayerEntity");
}
}
8 changes: 4 additions & 4 deletions src/Apps/GameDesktop/Content/TileMaps/Test.ldtk
Original file line number Diff line number Diff line change
Expand Up @@ -2360,7 +2360,7 @@
},
{
"__identifier": "Player",
"__grid": [5,5],
"__grid": [26,13],
"__pivot": [0.5,1],
"__tags": ["Transform"],
"__tile": { "tilesetUid": 3, "x": 48, "y": 128, "w": 32, "h": 32 },
Expand All @@ -2369,10 +2369,10 @@
"width": 32,
"height": 32,
"defUid": 120,
"px": [88,96],
"px": [424,224],
"fieldInstances": [],
"__worldX": 88,
"__worldY": 96
"__worldX": 424,
"__worldY": 224
},
{
"__identifier": "Red_Flower",
Expand Down
9 changes: 9 additions & 0 deletions src/Apps/GameDesktop/Game.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,15 @@

namespace GameDesktop;

// TODO: 1. Камера, зум, границы уровня
// 2. Переход между уровнями
// 3. Меню, экран загрузки, настройки игры, пауза
// 4. Окно, фпс и скорость игры
// 5. Сохранение, загрузка
// 6. Инвентарь, добыча ресурсов, квесты, награды
//
// Наполнение уровня энтити, компоненты, коллайдеры, рефакторинг
// Пофиксить при движении по диагонали полосы между тайлами
public class Game : Microsoft.Xna.Framework.Game
{
private readonly ILogger _logger;
Expand Down
3 changes: 3 additions & 0 deletions src/Apps/GameDesktop/GameDesktop.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,9 @@
<None Update="Content\TileMaps\Test.ldtk">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="Content\SpriteSheets\Sprite.png">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="Icon.ico" />
Expand Down
14 changes: 13 additions & 1 deletion src/Libs/Components/Data/CameraComponent.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System.Numerics;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Scellecs.Morpeh;
using Vector2 = System.Numerics.Vector2;

namespace Components.Data;

Expand All @@ -12,4 +13,15 @@ public struct CameraComponent(Viewport viewport) : IComponent
public Vector2 Position;

public Vector2 WorldToScreen(Vector2 other) => other - Position;

public Vector2 GetCenteredPosition(Viewport viewport, Vector2 off)
{
var cameraX = off.X - (float)viewport.Width / 2;
var cameraY = off.Y - (float)viewport.Height / 2;

cameraX = MathHelper.Clamp(cameraX, 0, 900 - viewport.Width);
cameraY = MathHelper.Clamp(cameraY, 0, 600 - viewport.Height);

return new Vector2(cameraX, cameraY);
}
}
31 changes: 13 additions & 18 deletions src/Libs/Systems/Render/CameraFollowingSystem.cs
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
using System.Numerics;
using Components.Data;
using Components.Data;
using Components.Render.Animation;
using Components.Render.Static;
using Components.Tags;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Scellecs.Morpeh;
using Vector2 = System.Numerics.Vector2;

namespace Systems.Render;

// issue: https://gamedev.stackexchange.com/questions/46963/how-to-avoid-texture-bleeding-in-a-texture-atlas
public class CameraFollowingSystem(World world) : ILateSystem
{
// private readonly ICamera _camera;
Expand Down Expand Up @@ -38,27 +40,20 @@ public void OnUpdate(float deltaTime)
ref var transform = ref e.GetComponent<TransformComponent>();
ref var camera = ref e.GetComponent<CameraComponent>();

camera.Position = GetCenteredPosition(camera.Viewport, off: transform.Position);
camera.Position = Vector2.Lerp(camera.Position, GetCenteredPosition(camera.Viewport, off: transform.Position),
.25f);
// camera.Position = Vector2.Lerp(camera.Position, transform.Position, .2f);
}

private static Vector2 GetCenteredPosition(Viewport viewport, Vector2 off) => new(
off.X - viewport.Width / 2,
off.Y - viewport.Height / 2);

private static IEnumerable<Entity> SortEntitiesByYPosition(Filter filter)
private static Vector2 GetCenteredPosition(Viewport viewport, Vector2 off)
{
List<Entity> entities = new List<Entity>();
var cameraX = off.X - (float)viewport.Width / 2;
var cameraY = off.Y - (float)viewport.Height / 2;

foreach (Entity e in filter)
{
entities.Add(e);
}
cameraX = MathHelper.Clamp(cameraX, 0, 900 - viewport.Width);
cameraY = MathHelper.Clamp(cameraY, 0, 600 - viewport.Height);

return entities.OrderBy(x =>
{
ref var transform = ref x.GetComponent<TransformComponent>();
return transform.Position.Y;
});
return new Vector2(cameraX, cameraY);
}

public void Dispose()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using Components.Render.Animation;
using Components.Render.Static;
using Components.Tags;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Scellecs.Morpeh;
using Scellecs.Morpeh.Extended;
Expand Down Expand Up @@ -45,17 +46,22 @@ public void OnUpdate(float deltaTime)
ref var animator = ref e.GetComponent<CharacterAnimatorComponent>();
var pivotOffset = animator.GetOffPivot(transform);
var localTransform = animator.LocalTransform;
var position = at + localTransform.Position - pivotOffset;

animator.Animation.Draw(spriteBatch, at + localTransform.Position - pivotOffset);
// casting to int for pixel perfect matching
animator.Animation.Draw(spriteBatch,
new Vector2((int)Math.Round(position.X), (int)Math.Round(position.Y)));
}

if (e.Has<SpriteComponent>())
{
ref var sprite = ref e.GetComponent<SpriteComponent>();
var pivotOffset = sprite.GetOffPivot(transform);
var localTransform = sprite.LocalTransform;
var position = at + localTransform.Position - pivotOffset;

sprite.Sprite.Draw(spriteBatch, at + localTransform.Position - pivotOffset);
// casting to int for pixel perfect matching
sprite.Sprite.Draw(spriteBatch, new Vector2((int)Math.Round(position.X), (int)Math.Round(position.Y)));
}
}
}
Expand Down
7 changes: 5 additions & 2 deletions src/Libs/Systems/Render/TilesRenderingSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -103,10 +103,13 @@ private void RenderLevel(LDtkLevel level, CameraComponent camera)
{
Vector2 tilePos = new(tile.Px.X + layer._PxTotalOffsetX,
tile.Px.Y + layer._PxTotalOffsetY);
var position = camera.WorldToScreen(tilePos);
var camPos = camera.WorldToScreen(tilePos);
// casting to int for pixel perfect matching
var position = new Microsoft.Xna.Framework.Vector2((int)Math.Round(camPos.X),
(int)Math.Round(camPos.Y));
Rectangle rect = new(tile.Src.X, tile.Src.Y, layer._GridSize, layer._GridSize);
SpriteEffects mirror = (SpriteEffects)tile.F;
spriteBatch.Draw(texture, position, rect, new Color(1f, 1f, 1f, layer._Opacity), 0,
spriteBatch.Draw(texture, position, rect, new Color(Color.White, layer._Opacity), 0,
Vector2.Zero, 1f, mirror, 0);
}
}
Expand Down
7 changes: 6 additions & 1 deletion src/Libs/Systems/WorldInitializer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ public void OnAwake()
throw new Exception("Level has no layers.");
}


for (int i = level.LayerInstances.Length - 1; i >= 0; --i)
{
LayerInstance layer = level.LayerInstances[i];
Expand All @@ -56,6 +55,12 @@ public void OnAwake()
// var pivotOffset = MathUtils.SectorToVector(transform.Pivot);

transform.Position = new Vector2((float)entity._WorldX, (float)entity._WorldY);

Check warning on line 57 in src/Libs/Systems/WorldInitializer.cs

View workflow job for this annotation

GitHub Actions / Build (ubuntu-latest)

Nullable value type may be null.

Check warning on line 57 in src/Libs/Systems/WorldInitializer.cs

View workflow job for this annotation

GitHub Actions / Build (ubuntu-latest)

Nullable value type may be null.

Check warning on line 57 in src/Libs/Systems/WorldInitializer.cs

View workflow job for this annotation

GitHub Actions / Build (ubuntu-latest)

Nullable value type may be null.

Check warning on line 57 in src/Libs/Systems/WorldInitializer.cs

View workflow job for this annotation

GitHub Actions / Build (ubuntu-latest)

Nullable value type may be null.

Check warning on line 57 in src/Libs/Systems/WorldInitializer.cs

View workflow job for this annotation

GitHub Actions / Build (ubuntu-latest)

Nullable value type may be null.

Check warning on line 57 in src/Libs/Systems/WorldInitializer.cs

View workflow job for this annotation

GitHub Actions / Build (ubuntu-latest)

Nullable value type may be null.

Check warning on line 57 in src/Libs/Systems/WorldInitializer.cs

View workflow job for this annotation

GitHub Actions / Build (windows-latest)

Nullable value type may be null.

Check warning on line 57 in src/Libs/Systems/WorldInitializer.cs

View workflow job for this annotation

GitHub Actions / Build (windows-latest)

Nullable value type may be null.

Check warning on line 57 in src/Libs/Systems/WorldInitializer.cs

View workflow job for this annotation

GitHub Actions / Build (windows-latest)

Nullable value type may be null.

Check warning on line 57 in src/Libs/Systems/WorldInitializer.cs

View workflow job for this annotation

GitHub Actions / Build (windows-latest)

Nullable value type may be null.

Check warning on line 57 in src/Libs/Systems/WorldInitializer.cs

View workflow job for this annotation

GitHub Actions / Build (windows-latest)

Nullable value type may be null.

Check warning on line 57 in src/Libs/Systems/WorldInitializer.cs

View workflow job for this annotation

GitHub Actions / Build (windows-latest)

Nullable value type may be null.

if (e.Has<CameraComponent>())
{
ref var camera = ref e.GetComponent<CameraComponent>();
camera.Position = camera.GetCenteredPosition(camera.Viewport, transform.Position);
}
}
}
}
Expand Down

0 comments on commit 8d102ea

Please sign in to comment.