From 604d79e654f1623c8798bc5846065b0e333b1804 Mon Sep 17 00:00:00 2001 From: Fries Date: Tue, 23 May 2023 00:21:54 -0700 Subject: [PATCH] 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. --- Scenes/Objects/Paddle.tscn | 2 +- Scenes/Pong.tscn | 2 +- Scripts/Constants.cs | 9 +- Scripts/Data/GameArea.cs | 37 ++++++ Scripts/Data/GameCoordinate.cs | 25 ++++ Scripts/Data/Settings.cs | 3 - Scripts/Managers/PongSceneManager.cs | 2 - Scripts/Managers/ScalingManager.cs | 158 ++++++++++++----------- Scripts/Managers/SettingsManager.cs | 1 - Scripts/Managers/UI/BaseMenu.cs | 2 - Scripts/Managers/UI/Menus/MainMenu.cs | 2 - Scripts/Managers/UI/Menus/Settings.cs | 2 - Scripts/Managers/WallCollisionManager.cs | 1 - Scripts/Objects/Paddle.cs | 28 +++- 14 files changed, 178 insertions(+), 96 deletions(-) create mode 100644 Scripts/Data/GameArea.cs create mode 100644 Scripts/Data/GameCoordinate.cs 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; } ///