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.
This commit is contained in:
Fries 2023-05-23 00:21:54 -07:00
parent e1b0fa338f
commit 604d79e654
14 changed files with 178 additions and 96 deletions

View file

@ -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="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"] [ext_resource type="Script" path="res://Scripts/Objects/Paddle.cs" id="1_uv7s3"]

View file

@ -1,6 +1,6 @@
[gd_scene load_steps=8 format=3 uid="uid://bh3p1hnvsviu6"] [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/PongSceneManager.cs" id="1_ee533"]
[ext_resource type="Script" path="res://Scripts/Managers/ScalingManager.cs" id="2_dc5sv"] [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"] [ext_resource type="PackedScene" uid="uid://clsmrwvyrt7av" path="res://Scenes/UI/Score.tscn" id="2_f3jwj"]

View file

@ -5,11 +5,16 @@ public static class Constants
/// <summary> /// <summary>
/// a constant representing 1 Meter in pixels. /// a constant representing 1 Meter in pixels.
/// </summary> /// </summary>
internal const double Meter = 10; public const double Meter = 10;
/// <summary>
/// the pixel size of either the vertical or the horizontal size of the walls.
/// </summary>
public const long WallSize = 30;
/// <summary> /// <summary>
/// the extents (half of the size) of the pixel size of either the width for the vertical walls, /// 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. /// or the height for the horizontal walls.
/// </summary> /// </summary>
internal const long WallSizeExtents = 15; public const long WallSizeExtents = WallSize / 2;
} }

37
Scripts/Data/GameArea.cs Normal file
View file

@ -0,0 +1,37 @@
namespace Pong.Scripts.Data;
public record GameArea
{
/// <summary>
/// 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.
/// </summary>
public GameCoordinate X { get; }
/// <summary>
/// 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.
/// </summary>
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);
}
}

View file

@ -0,0 +1,25 @@
namespace Pong.Scripts.Data;
/// <summary>
/// simple wrapper structure to a double that makes it easy to get commonly used calculations of the number.
/// </summary>
/// <param name="Coordinate">the coordinate you want to wrap.</param>
public readonly record struct GameCoordinate(double Coordinate)
{
/// <summary>
/// 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.
/// </summary>
public readonly double Coordinate = Coordinate;
/// <summary>
/// get the coordinate but calculated by the extents of the wall size.
/// </summary>
public double ByWallSizeExtents => Coordinate - Constants.WallSizeExtents;
/// <summary>
/// get the coordinate but calculated by the wall size.
/// </summary>
public double ByWallSize => Coordinate - Constants.WallSize;
public static implicit operator double(GameCoordinate coord) => coord.Coordinate;
}

View file

@ -1,6 +1,3 @@
using System;
using System.Text.Json.Serialization;
namespace Pong.Scripts.Data; namespace Pong.Scripts.Data;
/// <summary> /// <summary>

View file

@ -1,5 +1,3 @@
using Godot;
namespace Pong.Scripts.Managers; namespace Pong.Scripts.Managers;
public partial class PongSceneManager : Node2D public partial class PongSceneManager : Node2D

View file

@ -1,3 +1,6 @@
using System;
using Pong.Scripts.Data;
namespace Pong.Scripts.Managers; namespace Pong.Scripts.Managers;
public partial class ScalingManager : Node public partial class ScalingManager : Node
@ -14,7 +17,9 @@ public partial class ScalingManager : Node
private RigidBody2D _enemy; private RigidBody2D _enemy;
private Vector2I _gameResolution; private Vector2I _gameResolution;
private Vector2 _edgePosition; private GameArea _gameArea;
public event EventHandler<Vector2> NewPaddlePosition;
public override void _EnterTree() public override void _EnterTree()
{ {
@ -50,19 +55,14 @@ public partial class ScalingManager : Node
/// </summary> /// </summary>
private void AdaptToGameResolution() private void AdaptToGameResolution()
{ {
var normalizedPaddlePosition =
_gameArea?.NormalizePosition(_paddle.Position) ?? new Vector2(0, 0.5);
_gameResolution = DisplayServer.WindowGetSize(); _gameResolution = DisplayServer.WindowGetSize();
_edgePosition = CalculateEdgePosition(_gameResolution); _gameArea = new GameArea(_gameResolution);
SetWallPosition(); SetWallPosition();
SetScorePosition(); SetScorePosition();
} SetPaddlePosition(normalizedPaddlePosition);
/// <summary>
/// calculate the edges of the screen according to 0, 0 being in the center of the screen.
/// </summary>
private static Vector2 CalculateEdgePosition(Vector2 resolution)
{
return new Vector2(resolution.X / 2, resolution.Y / 2);
} }
/// <summary> /// <summary>
@ -70,8 +70,8 @@ public partial class ScalingManager : Node
/// </summary> /// </summary>
private void SetWallPosition() private void SetWallPosition()
{ {
var xSize = _edgePosition.X - Constants.WallSizeExtents; var xSize = _gameArea.X.ByWallSizeExtents;
var ySize = _edgePosition.Y - Constants.WallSizeExtents; var ySize = _gameArea.Y.ByWallSizeExtents;
_leftWall.Position = new Vector2(-xSize, 0); _leftWall.Position = new Vector2(-xSize, 0);
_rightWall.Position = new Vector2(xSize, 0); _rightWall.Position = new Vector2(xSize, 0);
@ -86,11 +86,17 @@ public partial class ScalingManager : Node
/// <summary> /// <summary>
/// set the position of the score ui. this has to be calculated with 0, 0 being the top left of the screen as /// 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. /// the UIs point starts from there instead of the point being in the middle of the screen.
/// </summary> /// </summary>
private void SetScorePosition() private void SetScorePosition()
{ {
_score.Position = new Vector2(-_edgePosition.X + 30, -_edgePosition.Y + 30); _score.Position = new Vector2(-_gameArea.X.ByWallSize, -_gameArea.Y.ByWallSize);
_score.Size = new Vector2(_gameResolution.X - 60, _gameResolution.Y - 60); _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);
}
} }

View file

@ -1,7 +1,6 @@
using System; using System;
using System.Text.Json; using System.Text.Json;
using System.Threading.Tasks; using System.Threading.Tasks;
using Godot;
using Pong.Scripts.Data; using Pong.Scripts.Data;
namespace Pong.Scripts.Managers; namespace Pong.Scripts.Managers;

View file

@ -1,5 +1,3 @@
using Godot;
namespace Pong.Scripts.Managers.UI; namespace Pong.Scripts.Managers.UI;
public partial class BaseMenu : VBoxContainer public partial class BaseMenu : VBoxContainer

View file

@ -1,5 +1,3 @@
using Godot;
namespace Pong.Scripts.Managers.UI.Menus; namespace Pong.Scripts.Managers.UI.Menus;
public partial class MainMenu : BaseMenu public partial class MainMenu : BaseMenu

View file

@ -1,5 +1,3 @@
using Godot;
namespace Pong.Scripts.Managers.UI.Menus; namespace Pong.Scripts.Managers.UI.Menus;
public partial class Settings : BaseMenu public partial class Settings : BaseMenu

View file

@ -1,4 +1,3 @@
using Godot;
using Pong.Scripts.Data; using Pong.Scripts.Data;
using Pong.Scripts.Objects; using Pong.Scripts.Objects;

View file

@ -1,3 +1,5 @@
using Pong.Scripts.Managers;
namespace Pong.Scripts.Objects; namespace Pong.Scripts.Objects;
public partial class Paddle : RigidBody2D public partial class Paddle : RigidBody2D
@ -7,20 +9,40 @@ public partial class Paddle : RigidBody2D
private double _verticalInput; private double _verticalInput;
private readonly StringName _paddleUp = "paddle_up"; private readonly StringName _paddleUp = "paddle_up";
private readonly StringName _paddleDown = "paddle_down"; private readonly StringName _paddleDown = "paddle_down";
private ScalingManager _scalingManager;
private bool _canMove = true;
private Vector2 _originalPosition;
private Vector2? _newPosition;
/// <summary> /// <summary>
/// property that multiples the moveSpeed by the <see cref="Constants.Meter">Meter</see> constant. /// property that multiples the moveSpeed by the <see cref="Constants.Meter">Meter</see> constant.
/// </summary> /// </summary>
private double MoveSpeed => _moveSpeed * Constants.Meter; private double MoveSpeed => _moveSpeed * Constants.Meter;
public override void _EnterTree()
{
SetNotifyTransform(true);
SetNotifyLocalTransform(true);
_scalingManager = GetNode<ScalingManager>("../ScalingManager");
_scalingManager.NewPaddlePosition += (_, vector2) => _newPosition = vector2;
}
public override void _Process(double delta) public override void _Process(double delta)
{ {
_verticalInput = GetVerticalInput(); _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;
} }
/// <summary> /// <summary>