the enemy can now scale to the resolution.

i made a BasePaddle class so i can put commonly used fields in a base class. this means i made a new plugin called CustomTypes which contains both Base classes.
This commit is contained in:
Fries 2023-05-23 21:48:30 -07:00
parent 3e61187065
commit 8072cf4961
12 changed files with 113 additions and 67 deletions

View file

@ -1,4 +1,4 @@
[gd_scene load_steps=4 format=3] [gd_scene load_steps=4 format=3 uid="uid://dts6gwgqbre22"]
[ext_resource type="Script" path="res://Scripts/Objects/Ball.cs" id="1_474si"] [ext_resource type="Script" path="res://Scripts/Objects/Ball.cs" id="1_474si"]

View file

@ -1,4 +1,4 @@
[gd_scene load_steps=5 format=3] [gd_scene load_steps=5 format=3 uid="uid://ch0fhyeawosrh"]
[ext_resource type="PhysicsMaterial" uid="uid://e05n66x8ug77" path="res://Resources/BouncyMaterial.tres" id="1_e3kk5"] [ext_resource type="PhysicsMaterial" uid="uid://e05n66x8ug77" path="res://Resources/BouncyMaterial.tres" id="1_e3kk5"]
[ext_resource type="Script" path="res://Scripts/Objects/Enemy.cs" id="1_fbrtv"] [ext_resource type="Script" path="res://Scripts/Objects/Enemy.cs" id="1_fbrtv"]

View file

@ -1,12 +1,12 @@
[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"]
[ext_resource type="PackedScene" path="res://Scenes/Objects/Ball.tscn" id="2_u2ksv"] [ext_resource type="PackedScene" uid="uid://dts6gwgqbre22" path="res://Scenes/Objects/Ball.tscn" id="2_u2ksv"]
[ext_resource type="PackedScene" uid="uid://cmk6ierwi7sdt" path="res://Scenes/Objects/Walls.tscn" id="3_jfis7"] [ext_resource type="PackedScene" uid="uid://cmk6ierwi7sdt" path="res://Scenes/Objects/Walls.tscn" id="3_jfis7"]
[ext_resource type="PackedScene" path="res://Scenes/Objects/Enemy.tscn" id="4_uwvof"] [ext_resource type="PackedScene" uid="uid://ch0fhyeawosrh" path="res://Scenes/Objects/Enemy.tscn" id="4_uwvof"]
[node name="Pong" type="Node2D"] [node name="Pong" type="Node2D"]
script = ExtResource("1_ee533") script = ExtResource("1_ee533")
@ -19,7 +19,7 @@ offset_bottom = 270.0
[node name="Paddle" parent="." instance=ExtResource("1_5rs0o")] [node name="Paddle" parent="." instance=ExtResource("1_5rs0o")]
position = Vector2(-350, 0) position = Vector2(-350, 0)
_moveSpeed = 50.0 MoveSpeed = 50.0
[node name="Camera2D" type="Camera2D" parent="."] [node name="Camera2D" type="Camera2D" parent="."]
@ -31,7 +31,7 @@ _maxRandomAngle = 0.42
[node name="Enemy" parent="." instance=ExtResource("4_uwvof")] [node name="Enemy" parent="." instance=ExtResource("4_uwvof")]
position = Vector2(350, 0) position = Vector2(350, 0)
_moveSpeed = 50.0 MoveSpeed = 50.0
[node name="ScalingManager" type="Node" parent="."] [node name="ScalingManager" type="Node" parent="."]
script = ExtResource("2_dc5sv") script = ExtResource("2_dc5sv")

View file

@ -0,0 +1,9 @@
namespace Pong.Scripts.Data;
public static class DoubleExtensions
{
public static double ByMeter(this double num)
{
return num * Constants.Meter;
}
}

View file

@ -0,0 +1,19 @@
namespace Pong.Scripts.Managers;
public partial class BasePaddle: RigidBody2D
{
[Export] protected double MoveSpeed;
protected ScalingManager ScalingManager;
protected Vector2? NewPosition;
public override void _EnterTree()
{
ScalingManager = GetNode<ScalingManager>("../ScalingManager");
}
protected void SetNewPosition(Vector2 newPosition)
{
NewPosition = newPosition;
}
}

View file

@ -19,9 +19,9 @@ public partial class ScalingManager : Node
private Vector2I _gameResolution; private Vector2I _gameResolution;
private GameArea _gameArea; private GameArea _gameArea;
public event EventHandler<Vector2> NewPaddlePosition; public event Action<Vector2> NewPaddlePosition;
public event EventHandler<Vector2> NewEnemyPosition; public event Action<Vector2> NewEnemyPosition;
public event EventHandler<Vector2> NewBallPosition; public event Action<Vector2> NewBallPosition;
public override void _EnterTree() public override void _EnterTree()
{ {
@ -68,6 +68,7 @@ public partial class ScalingManager : Node
SetWallPosition(); SetWallPosition();
SetScorePosition(); SetScorePosition();
SetPaddlePosition(normalizedPaddlePosition); SetPaddlePosition(normalizedPaddlePosition);
SetEnemyPosition(normalizedEnemyPosition);
} }
/// <summary> /// <summary>
@ -105,18 +106,22 @@ public partial class ScalingManager : Node
private void SetPaddlePosition(Vector2 normalizedPosition) private void SetPaddlePosition(Vector2 normalizedPosition)
{ {
var newPaddlePos = _gameArea.GlobalizePosition(normalizedPosition with { X = 0 }) + new Vector2(48, 0); var newPaddlePos = _gameArea.GlobalizePosition(normalizedPosition with { X = 0 }) + new Vector2(48, 0);
NewPaddlePosition?.Invoke(this, newPaddlePos); NewPaddlePosition?.Invoke(newPaddlePos);
} }
private void SetEnemyPosition(Vector2 normalizedPosition) private void SetEnemyPosition(Vector2 normalizedPosition)
{ {
var newEnemyPos = _gameArea.GlobalizePosition(normalizedPosition with {X = 0}) + new Vector2(48,0); var newEnemyPos = _gameArea.GlobalizePosition(normalizedPosition with { X = 1 }) + new Vector2(-48, 0);
NewEnemyPosition?.Invoke(this, newEnemyPos); NewEnemyPosition?.Invoke(newEnemyPos);
} }
private void SetBallPosition(Vector2 normalizedPosition) private void SetBallPosition(Vector2 normalizedPosition)
{ {
var newBallPos = _gameArea.GlobalizePosition(normalizedPosition); var newBallPos = _gameArea.GlobalizePosition(normalizedPosition);
NewBallPosition?.Invoke(this, newBallPos); NewBallPosition?.Invoke(newBallPos);
}
public static void SetNewPosition(ref Vector2 newPositionField)
{
} }
} }

View file

@ -1,16 +1,17 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using Godot.Collections; using Godot.Collections;
using Pong.Scripts.Data;
using Pong.Scripts.Managers;
namespace Pong.Scripts.Objects; namespace Pong.Scripts.Objects;
public partial class Enemy : RigidBody2D public partial class Enemy : BasePaddle
{ {
/// <summary> /// <summary>
/// draw shapes to the screen (like <see cref="_scanArea"/>). /// draw shapes to the screen (like <see cref="_scanArea"/>).
/// </summary> /// </summary>
[Export] private bool _drawDebugShapes; [Export] private bool _drawDebugShapes;
[Export] private double _moveSpeed;
private CollisionShape2D _collisionShape; private CollisionShape2D _collisionShape;
private Rect2 _scanArea; private Rect2 _scanArea;
@ -19,8 +20,10 @@ public partial class Enemy : RigidBody2D
private readonly Variant _collider = "collider"; private readonly Variant _collider = "collider";
private PhysicsShapeQueryParameters2D _query; private PhysicsShapeQueryParameters2D _query;
public override void _Ready() public override void _EnterTree()
{ {
base._EnterTree();
ScalingManager.NewEnemyPosition += SetNewPosition;
_collisionShape = GetNode<CollisionShape2D>("CollisionShape2D"); _collisionShape = GetNode<CollisionShape2D>("CollisionShape2D");
GenerateCastArea(); GenerateCastArea();
@ -34,7 +37,17 @@ public partial class Enemy : RigidBody2D
public override void _PhysicsProcess(double delta) public override void _PhysicsProcess(double delta)
{ {
Scan(delta); }
public override void _IntegrateForces(PhysicsDirectBodyState2D state)
{
if (NewPosition.HasValue)
{
state.Transform = new Transform2D(0, NewPosition.Value);
NewPosition = null;
}
Scan(GetPhysicsProcessDeltaTime(), state);
} }
public override void _Draw() public override void _Draw()
@ -43,7 +56,7 @@ public partial class Enemy : RigidBody2D
DrawRect(_scanArea, Colors.Aqua); DrawRect(_scanArea, Colors.Aqua);
} }
private void Scan(double delta) private void Scan(double delta, PhysicsDirectBodyState2D state)
{ {
var result = _spaceState.IntersectShape(_query); var result = _spaceState.IntersectShape(_query);
@ -53,27 +66,28 @@ public partial class Enemy : RigidBody2D
return; return;
} }
TrackBall(delta, result); TrackBall(delta, result, state);
} }
/// <summary> /// <summary>
/// track the distance between the ball and the enemy paddle on the y axis and move velocity accordingly. /// track the distance between the ball and the enemy paddle on the y axis and move velocity accordingly.
/// </summary> /// </summary>
/// <param name="delta">how long it took to complete the last frame in seconds. this should be constant as /// <param name="delta">how long it took to complete the last frame in seconds. this should be constant as
/// should be executed in the physics process method which should be separate from the main frame rate.</param> /// should be executed in the physics process method which should be separate from the main frame rate.</param>
/// <param name="result">a dictionary of objects that collided with the cast. this method only works if /// <param name="result">a dictionary of objects that collided with the cast. this method only works if
/// theres an object that has the Ball class.</param> /// theres an object that has the Ball class.</param>
private void TrackBall(double delta, IReadOnlyList<Dictionary> result) /// <param name="state"></param>
private void TrackBall(double delta, IReadOnlyList<Dictionary> result, PhysicsDirectBodyState2D state)
{ {
// checks if the collider is a ball, if not, return. // checks if the collider is a ball, if not, return.
if (result[0][_collider].As<Ball>() is not { } ball) return; if (result[0][_collider].As<Ball>() is not { } ball) return;
// gets the sign of the distance between the ball and the paddle on the y axis // gets the sign of the distance between the ball and the paddle on the y axis
var normalisedDistance = new Vector2 { Y = Mathf.Sign(ball.Position.Y - Position.Y) }; var normalisedDistance = new Vector2 { Y = Mathf.Sign(ball.Position.Y - Position.Y) };
var linearVelocity = normalisedDistance * _moveSpeed * Constants.Meter; var linearVelocity = normalisedDistance * MoveSpeed.ByMeter();
// lerp the velocity to smooth out jerky movement. // lerp the velocity to smooth out jerky movement.
LinearVelocity = LinearVelocity.Lerp(linearVelocity, delta); state.LinearVelocity = LinearVelocity.Lerp(linearVelocity, delta);
} }
/// <summary> /// <summary>

View file

@ -1,30 +1,21 @@
using Pong.Scripts.Data;
using Pong.Scripts.Managers; using Pong.Scripts.Managers;
namespace Pong.Scripts.Objects; namespace Pong.Scripts.Objects;
public partial class Paddle : RigidBody2D public partial class Paddle : BasePaddle
{ {
[Export] private double _moveSpeed;
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 bool _canMove = true;
private Vector2 _originalPosition; private Vector2 _originalPosition;
private Vector2? _newPosition;
/// <summary>
/// property that multiples the moveSpeed by the <see cref="Constants.Meter">Meter</see> constant.
/// </summary>
private double MoveSpeed => _moveSpeed * Constants.Meter;
public override void _EnterTree() public override void _EnterTree()
{ {
_scalingManager = GetNode<ScalingManager>("../ScalingManager"); base._EnterTree();
_scalingManager.NewPaddlePosition += (_, vector2) => _newPosition = vector2; ScalingManager.NewPaddlePosition += SetNewPosition;
} }
public override void _Process(double delta) public override void _Process(double delta)
@ -34,13 +25,13 @@ public partial class Paddle : RigidBody2D
public override void _IntegrateForces(PhysicsDirectBodyState2D state) public override void _IntegrateForces(PhysicsDirectBodyState2D state)
{ {
if (_newPosition.HasValue) if (NewPosition.HasValue)
{ {
state.Transform = new Transform2D(0, _newPosition.Value); state.Transform = new Transform2D(0, NewPosition.Value);
_newPosition = null; NewPosition = null;
} }
state.LinearVelocity = Vector2.Up * MoveSpeed * _verticalInput; state.LinearVelocity = Vector2.Up * MoveSpeed.ByMeter() * _verticalInput;
} }
/// <summary> /// <summary>

View file

@ -1,20 +0,0 @@
#if TOOLS
using Godot;
namespace Pong.addons.BaseMenu;
[Tool]
public partial class BaseMenu : EditorPlugin
{
public override void _EnterTree()
{
var baseMenuScript = GD.Load<Script>("res://Scripts/Managers/UI/BaseMenu.cs");
AddCustomType("BaseMenu", "VBoxContainer", baseMenuScript, GetEditorIcon("VBoxContainer"));
}
private Texture2D GetEditorIcon(string iconName)
{
return GetEditorInterface().GetBaseControl().GetThemeIcon(iconName, "EditorIcons");
}
}
#endif

View file

@ -0,0 +1,28 @@
#if TOOLS
namespace Pong.addons.CustomTypes
{
[Tool]
public partial class Plugin : EditorPlugin
{
public override void _EnterTree()
{
var baseMenuScript = GD.Load<Script>("res://Scripts/Managers/UI/BaseMenu.cs");
var basePaddleScript = GD.Load<Script>("res://Scripts/Managers/BasePaddle.cs");
AddCustomType("BaseMenu", "VBoxContainer", baseMenuScript, GetEditorIcon("VBoxContainer"));
AddCustomType("BasePaddle", "RigidBody2D", basePaddleScript, GetEditorIcon("RigidBody2D"));
}
public override void _ExitTree()
{
RemoveCustomType("BaseMenu");
RemoveCustomType("BasePaddle");
}
private Texture2D GetEditorIcon(string iconName)
{
return GetEditorInterface().GetBaseControl().GetThemeIcon(iconName, "EditorIcons");
}
}
}
#endif

View file

@ -1,7 +1,7 @@
[plugin] [plugin]
name="BaseMenu" name="CustomTypes"
description="" description=""
author="Fries" author="Fries"
version="" version=""
script="BaseMenu.cs" script="Plugin.cs"

View file

@ -35,7 +35,7 @@ version_control/autoload_on_startup=true
[editor_plugins] [editor_plugins]
enabled=PackedStringArray("res://addons/BaseMenu/plugin.cfg") enabled=PackedStringArray("res://addons/CustomTypes/plugin.cfg")
[input] [input]