diff --git a/Scenes/Objects/Paddle.tscn b/Scenes/Objects/Paddle.tscn
index 147a898..4c77401 100644
--- a/Scenes/Objects/Paddle.tscn
+++ b/Scenes/Objects/Paddle.tscn
@@ -1,4 +1,4 @@
-[gd_scene load_steps=5 format=3]
+[gd_scene load_steps=5 format=3 uid="uid://ijf4pw1wmb4t"]
[ext_resource type="PhysicsMaterial" uid="uid://e05n66x8ug77" path="res://Resources/BouncyMaterial.tres" id="1_76uik"]
[ext_resource type="Script" path="res://Scripts/Objects/Paddle.cs" id="1_uv7s3"]
diff --git a/Scenes/Pong.tscn b/Scenes/Pong.tscn
index 6af3bf5..715cf7c 100644
--- a/Scenes/Pong.tscn
+++ b/Scenes/Pong.tscn
@@ -1,6 +1,6 @@
[gd_scene load_steps=8 format=3 uid="uid://bh3p1hnvsviu6"]
-[ext_resource type="PackedScene" path="res://Scenes/Objects/Paddle.tscn" id="1_5rs0o"]
+[ext_resource type="PackedScene" uid="uid://ijf4pw1wmb4t" path="res://Scenes/Objects/Paddle.tscn" id="1_5rs0o"]
[ext_resource type="Script" path="res://Scripts/Managers/PongSceneManager.cs" id="1_ee533"]
[ext_resource type="Script" path="res://Scripts/Managers/ScalingManager.cs" id="2_dc5sv"]
[ext_resource type="PackedScene" uid="uid://clsmrwvyrt7av" path="res://Scenes/UI/Score.tscn" id="2_f3jwj"]
diff --git a/Scripts/Constants.cs b/Scripts/Constants.cs
index 53f3325..e550a08 100644
--- a/Scripts/Constants.cs
+++ b/Scripts/Constants.cs
@@ -5,11 +5,16 @@ public static class Constants
///
/// a constant representing 1 Meter in pixels.
///
- internal const double Meter = 10;
+ public const double Meter = 10;
+ ///
+ /// the pixel size of either the vertical or the horizontal size of the walls.
+ ///
+ public const long WallSize = 30;
+
///
/// the extents (half of the size) of the pixel size of either the width for the vertical walls,
/// or the height for the horizontal walls.
///
- internal const long WallSizeExtents = 15;
+ public const long WallSizeExtents = WallSize / 2;
}
diff --git a/Scripts/Data/GameArea.cs b/Scripts/Data/GameArea.cs
new file mode 100644
index 0000000..58ec1bb
--- /dev/null
+++ b/Scripts/Data/GameArea.cs
@@ -0,0 +1,37 @@
+namespace Pong.Scripts.Data;
+
+public record GameArea
+{
+ ///
+ /// the X coordinate of the GameArea wrapped in a struct that makes operating on it easier. this is divided
+ /// by 2 in the constructor to represent both sides of the screen by either negative or positive of the number.
+ ///
+ public GameCoordinate X { get; }
+
+ ///
+ /// the Y coordinate of the GameArea wrapped in a struct that makes operating on it easier. this is divided
+ /// by 2 in the constructor to represent both sides of the screen by either negative or positive of the number.
+ ///
+ public GameCoordinate Y { get; }
+
+ public Vector2 NormalizePosition(Vector2 globalPosition)
+ {
+ var normalizedX = Mathf.InverseLerp(-X.ByWallSizeExtents, X.ByWallSizeExtents, globalPosition.X);
+ var normalizedY = Mathf.InverseLerp(-Y.ByWallSizeExtents, Y.ByWallSizeExtents, globalPosition.Y);
+ return new Vector2(normalizedX, normalizedY);
+ }
+
+
+ public Vector2 GlobalizePosition(Vector2 normalizedPosition)
+ {
+ var globalizedX = Mathf.Lerp(-X.ByWallSizeExtents, X.ByWallSizeExtents, normalizedPosition.X);
+ var globalizedY = Mathf.Lerp(-Y.ByWallSizeExtents, Y.ByWallSizeExtents, normalizedPosition.Y);
+ return new Vector2(globalizedX, globalizedY);
+ }
+
+ public GameArea(Vector2 area)
+ {
+ X = new GameCoordinate(area.X / 2);
+ Y = new GameCoordinate(area.Y / 2);
+ }
+}
diff --git a/Scripts/Data/GameCoordinate.cs b/Scripts/Data/GameCoordinate.cs
new file mode 100644
index 0000000..577006f
--- /dev/null
+++ b/Scripts/Data/GameCoordinate.cs
@@ -0,0 +1,25 @@
+namespace Pong.Scripts.Data;
+
+///
+/// simple wrapper structure to a double that makes it easy to get commonly used calculations of the number.
+///
+/// the coordinate you want to wrap.
+public readonly record struct GameCoordinate(double Coordinate)
+{
+ ///
+ /// the original coordinate. you don't really need to use this as the struct has an implicit operator, but
+ /// its here if you need it.
+ ///
+ public readonly double Coordinate = Coordinate;
+
+ ///
+ /// get the coordinate but calculated by the extents of the wall size.
+ ///
+ public double ByWallSizeExtents => Coordinate - Constants.WallSizeExtents;
+ ///
+ /// get the coordinate but calculated by the wall size.
+ ///
+ public double ByWallSize => Coordinate - Constants.WallSize;
+
+ public static implicit operator double(GameCoordinate coord) => coord.Coordinate;
+}
diff --git a/Scripts/Data/Settings.cs b/Scripts/Data/Settings.cs
index e613166..0dafce7 100644
--- a/Scripts/Data/Settings.cs
+++ b/Scripts/Data/Settings.cs
@@ -1,6 +1,3 @@
-using System;
-using System.Text.Json.Serialization;
-
namespace Pong.Scripts.Data;
///
diff --git a/Scripts/Managers/PongSceneManager.cs b/Scripts/Managers/PongSceneManager.cs
index da2a5a3..d19b3e5 100644
--- a/Scripts/Managers/PongSceneManager.cs
+++ b/Scripts/Managers/PongSceneManager.cs
@@ -1,5 +1,3 @@
-using Godot;
-
namespace Pong.Scripts.Managers;
public partial class PongSceneManager : Node2D
diff --git a/Scripts/Managers/ScalingManager.cs b/Scripts/Managers/ScalingManager.cs
index c2d13d6..70718de 100644
--- a/Scripts/Managers/ScalingManager.cs
+++ b/Scripts/Managers/ScalingManager.cs
@@ -1,96 +1,102 @@
+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 HFlowContainer _score;
+ private RigidBody2D _paddle;
+ private CharacterBody2D _ball;
- private Area2D _leftWall;
- private Area2D _rightWall;
- private StaticBody2D _topWall;
- private StaticBody2D _bottomWall;
+ private Area2D _leftWall;
+ private Area2D _rightWall;
+ private StaticBody2D _topWall;
+ private StaticBody2D _bottomWall;
- private RigidBody2D _enemy;
+ private RigidBody2D _enemy;
- private Vector2I _gameResolution;
- private Vector2 _edgePosition;
+ private Vector2I _gameResolution;
+ private GameArea _gameArea;
- public override void _EnterTree()
- {
- GetNodes();
- GetTree().Root.SizeChanged += AdaptToGameResolution;
- AdaptToGameResolution();
- }
+ public event EventHandler NewPaddlePosition;
- public override void _ExitTree()
- {
- GetTree().Root.SizeChanged -= AdaptToGameResolution;
- }
+ public override void _EnterTree()
+ {
+ GetNodes();
+ GetTree().Root.SizeChanged += AdaptToGameResolution;
+ AdaptToGameResolution();
+ }
- ///
- /// a method that gets all the nodes that the scaling manager will manage the position and scale of.
- ///
- private void GetNodes()
- {
- _score = GetNode("../Score");
- _paddle = GetNode("../Paddle");
- _ball = GetNode("../Ball");
+ public override void _ExitTree()
+ {
+ GetTree().Root.SizeChanged -= AdaptToGameResolution;
+ }
- _leftWall = GetNode("../Walls/Left");
- _rightWall = GetNode("../Walls/Right");
- _topWall = GetNode("../Walls/Top");
- _bottomWall = GetNode("../Walls/Bottom");
+ ///
+ /// a method that gets all the nodes that the scaling manager will manage the position and scale of.
+ ///
+ private void GetNodes()
+ {
+ _score = GetNode("../Score");
+ _paddle = GetNode("../Paddle");
+ _ball = GetNode("../Ball");
- _enemy = GetNode("../Enemy");
- }
+ _leftWall = GetNode("../Walls/Left");
+ _rightWall = GetNode("../Walls/Right");
+ _topWall = GetNode("../Walls/Top");
+ _bottomWall = GetNode("../Walls/Bottom");
- ///
- /// adapt to the current resolution of the game.
- ///
- private void AdaptToGameResolution()
- {
- _gameResolution = DisplayServer.WindowGetSize();
- _edgePosition = CalculateEdgePosition(_gameResolution);
+ _enemy = GetNode("../Enemy");
+ }
- SetWallPosition();
- SetScorePosition();
- }
+ ///
+ /// adapt to the current resolution of the game.
+ ///
+ private void AdaptToGameResolution()
+ {
+ var normalizedPaddlePosition =
+ _gameArea?.NormalizePosition(_paddle.Position) ?? new Vector2(0, 0.5);
+ _gameResolution = DisplayServer.WindowGetSize();
+ _gameArea = new GameArea(_gameResolution);
- ///
- /// calculate the edges of the screen according to 0, 0 being in the center of the screen.
- ///
- private static Vector2 CalculateEdgePosition(Vector2 resolution)
- {
- return new Vector2(resolution.X / 2, resolution.Y / 2);
- }
+ SetWallPosition();
+ SetScorePosition();
+ SetPaddlePosition(normalizedPaddlePosition);
+ }
- ///
- /// set the position and scale of the walls according to the edge position.
- ///
- private void SetWallPosition()
- {
- var xSize = _edgePosition.X - Constants.WallSizeExtents;
- var ySize = _edgePosition.Y - Constants.WallSizeExtents;
+ ///
+ /// set the position and scale of the walls according to the edge position.
+ ///
+ 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.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 };
- }
+ _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 };
+ }
- ///
- /// set the position of the score ui. this has to be calculated with 0, 0 being the top left of the screen as
- /// the UI's point starts from there instead of the point being in the middle of the screen.
- ///
- private void SetScorePosition()
- {
- _score.Position = new Vector2(-_edgePosition.X + 30, -_edgePosition.Y + 30);
- _score.Size = new Vector2(_gameResolution.X - 60, _gameResolution.Y - 60);
- }
+ ///
+ /// 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.
+ ///
+ 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);
+ }
}
diff --git a/Scripts/Managers/SettingsManager.cs b/Scripts/Managers/SettingsManager.cs
index d6e533f..dc23d89 100644
--- a/Scripts/Managers/SettingsManager.cs
+++ b/Scripts/Managers/SettingsManager.cs
@@ -1,7 +1,6 @@
using System;
using System.Text.Json;
using System.Threading.Tasks;
-using Godot;
using Pong.Scripts.Data;
namespace Pong.Scripts.Managers;
diff --git a/Scripts/Managers/UI/BaseMenu.cs b/Scripts/Managers/UI/BaseMenu.cs
index 0639d3a..292d1df 100644
--- a/Scripts/Managers/UI/BaseMenu.cs
+++ b/Scripts/Managers/UI/BaseMenu.cs
@@ -1,5 +1,3 @@
-using Godot;
-
namespace Pong.Scripts.Managers.UI;
public partial class BaseMenu : VBoxContainer
diff --git a/Scripts/Managers/UI/Menus/MainMenu.cs b/Scripts/Managers/UI/Menus/MainMenu.cs
index b17be61..c270832 100644
--- a/Scripts/Managers/UI/Menus/MainMenu.cs
+++ b/Scripts/Managers/UI/Menus/MainMenu.cs
@@ -1,5 +1,3 @@
-using Godot;
-
namespace Pong.Scripts.Managers.UI.Menus;
public partial class MainMenu : BaseMenu
diff --git a/Scripts/Managers/UI/Menus/Settings.cs b/Scripts/Managers/UI/Menus/Settings.cs
index 98cb070..6077487 100644
--- a/Scripts/Managers/UI/Menus/Settings.cs
+++ b/Scripts/Managers/UI/Menus/Settings.cs
@@ -1,5 +1,3 @@
-using Godot;
-
namespace Pong.Scripts.Managers.UI.Menus;
public partial class Settings : BaseMenu
diff --git a/Scripts/Managers/WallCollisionManager.cs b/Scripts/Managers/WallCollisionManager.cs
index 63738e4..596d28c 100644
--- a/Scripts/Managers/WallCollisionManager.cs
+++ b/Scripts/Managers/WallCollisionManager.cs
@@ -1,4 +1,3 @@
-using Godot;
using Pong.Scripts.Data;
using Pong.Scripts.Objects;
diff --git a/Scripts/Objects/Paddle.cs b/Scripts/Objects/Paddle.cs
index cebc4ed..b050d72 100644
--- a/Scripts/Objects/Paddle.cs
+++ b/Scripts/Objects/Paddle.cs
@@ -1,26 +1,48 @@
+using Pong.Scripts.Managers;
+
namespace Pong.Scripts.Objects;
public partial class Paddle : RigidBody2D
{
[Export] private double _moveSpeed;
-
+
private double _verticalInput;
private readonly StringName _paddleUp = "paddle_up";
private readonly StringName _paddleDown = "paddle_down";
+ private ScalingManager _scalingManager;
+
+ private bool _canMove = true;
+ private Vector2 _originalPosition;
+
+ private Vector2? _newPosition;
///
/// property that multiples the moveSpeed by the Meter constant.
///
private double MoveSpeed => _moveSpeed * Constants.Meter;
+ public override void _EnterTree()
+ {
+ SetNotifyTransform(true);
+ SetNotifyLocalTransform(true);
+ _scalingManager = GetNode("../ScalingManager");
+ _scalingManager.NewPaddlePosition += (_, vector2) => _newPosition = vector2;
+ }
+
public override void _Process(double delta)
{
_verticalInput = GetVerticalInput();
}
- public override void _PhysicsProcess(double delta)
+ public override void _IntegrateForces(PhysicsDirectBodyState2D state)
{
- LinearVelocity = Vector2.Up * MoveSpeed * _verticalInput;
+ if (_newPosition.HasValue)
+ {
+ state.Transform = new Transform2D(0, _newPosition.Value);
+ _newPosition = null;
+ }
+
+ state.LinearVelocity = Vector2.Up * MoveSpeed * _verticalInput;
}
///