Pong/Scripts/Managers/ScalingManager.cs
Fries 604d79e654 the paddle can now scale to the resolution
i added a GameArea class which makes it easier to operate on in coordinates bounds with the GameCoordinate struct wrapper which does calculations for me. the GameArea class also has a normalization system which is how the ScalingManager can teleport items in bounds to relatively the same place when resized.

it took quite a while to get the paddle to teleport. looks like im supposed to modify the position inside IntegrateForces instead of PhysicsProcess which is my mistake.
2023-05-23 00:21:54 -07:00

102 lines
3 KiB
C#

using System;
using Pong.Scripts.Data;
namespace Pong.Scripts.Managers;
public partial class ScalingManager : Node
{
private HFlowContainer _score;
private RigidBody2D _paddle;
private CharacterBody2D _ball;
private Area2D _leftWall;
private Area2D _rightWall;
private StaticBody2D _topWall;
private StaticBody2D _bottomWall;
private RigidBody2D _enemy;
private Vector2I _gameResolution;
private GameArea _gameArea;
public event EventHandler<Vector2> NewPaddlePosition;
public override void _EnterTree()
{
GetNodes();
GetTree().Root.SizeChanged += AdaptToGameResolution;
AdaptToGameResolution();
}
public override void _ExitTree()
{
GetTree().Root.SizeChanged -= AdaptToGameResolution;
}
/// <summary>
/// a method that gets all the nodes that the scaling manager will manage the position and scale of.
/// </summary>
private void GetNodes()
{
_score = GetNode<HFlowContainer>("../Score");
_paddle = GetNode<RigidBody2D>("../Paddle");
_ball = GetNode<CharacterBody2D>("../Ball");
_leftWall = GetNode<Area2D>("../Walls/Left");
_rightWall = GetNode<Area2D>("../Walls/Right");
_topWall = GetNode<StaticBody2D>("../Walls/Top");
_bottomWall = GetNode<StaticBody2D>("../Walls/Bottom");
_enemy = GetNode<RigidBody2D>("../Enemy");
}
/// <summary>
/// adapt to the current resolution of the game.
/// </summary>
private void AdaptToGameResolution()
{
var normalizedPaddlePosition =
_gameArea?.NormalizePosition(_paddle.Position) ?? new Vector2(0, 0.5);
_gameResolution = DisplayServer.WindowGetSize();
_gameArea = new GameArea(_gameResolution);
SetWallPosition();
SetScorePosition();
SetPaddlePosition(normalizedPaddlePosition);
}
/// <summary>
/// set the position and scale of the walls according to the edge position.
/// </summary>
private void SetWallPosition()
{
var xSize = _gameArea.X.ByWallSizeExtents;
var ySize = _gameArea.Y.ByWallSizeExtents;
_leftWall.Position = new Vector2(-xSize, 0);
_rightWall.Position = new Vector2(xSize, 0);
_topWall.Position = new Vector2(0, -ySize);
_bottomWall.Position = new Vector2(0, ySize);
_leftWall.Scale = _leftWall.Scale with { Y = _gameResolution.Y };
_rightWall.Scale = _rightWall.Scale with { Y = _gameResolution.Y };
_topWall.Scale = _topWall.Scale with { X = _gameResolution.X - 60 };
_bottomWall.Scale = _bottomWall.Scale with { X = _gameResolution.X - 60 };
}
/// <summary>
/// set the position of the score ui. this has to be calculated with 0, 0 being the top left of the screen as
/// the UIs point starts from there instead of the point being in the middle of the screen.
/// </summary>
private void SetScorePosition()
{
_score.Position = new Vector2(-_gameArea.X.ByWallSize, -_gameArea.Y.ByWallSize);
_score.Size = new Vector2(_gameResolution.X - 60, _gameResolution.Y - 60);
}
private void SetPaddlePosition(Vector2 normalizedPosition)
{
var newPaddlePos = _gameArea.GlobalizePosition(normalizedPosition with { X = 0 }) + new Vector2(24, 0);
NewPaddlePosition?.Invoke(this, newPaddlePos);
}
}