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"]

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="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"]
[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"]
[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" 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"]
script = ExtResource("1_ee533")
@ -19,7 +19,7 @@ offset_bottom = 270.0
[node name="Paddle" parent="." instance=ExtResource("1_5rs0o")]
position = Vector2(-350, 0)
_moveSpeed = 50.0
MoveSpeed = 50.0
[node name="Camera2D" type="Camera2D" parent="."]
@ -31,7 +31,7 @@ _maxRandomAngle = 0.42
[node name="Enemy" parent="." instance=ExtResource("4_uwvof")]
position = Vector2(350, 0)
_moveSpeed = 50.0
MoveSpeed = 50.0
[node name="ScalingManager" type="Node" parent="."]
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 GameArea _gameArea;
public event EventHandler<Vector2> NewPaddlePosition;
public event EventHandler<Vector2> NewEnemyPosition;
public event EventHandler<Vector2> NewBallPosition;
public event Action<Vector2> NewPaddlePosition;
public event Action<Vector2> NewEnemyPosition;
public event Action<Vector2> NewBallPosition;
public override void _EnterTree()
{
@ -68,6 +68,7 @@ public partial class ScalingManager : Node
SetWallPosition();
SetScorePosition();
SetPaddlePosition(normalizedPaddlePosition);
SetEnemyPosition(normalizedEnemyPosition);
}
/// <summary>
@ -105,18 +106,22 @@ public partial class ScalingManager : Node
private void SetPaddlePosition(Vector2 normalizedPosition)
{
var newPaddlePos = _gameArea.GlobalizePosition(normalizedPosition with { X = 0 }) + new Vector2(48, 0);
NewPaddlePosition?.Invoke(this, newPaddlePos);
NewPaddlePosition?.Invoke(newPaddlePos);
}
private void SetEnemyPosition(Vector2 normalizedPosition)
{
var newEnemyPos = _gameArea.GlobalizePosition(normalizedPosition with {X = 0}) + new Vector2(48,0);
NewEnemyPosition?.Invoke(this, newEnemyPos);
var newEnemyPos = _gameArea.GlobalizePosition(normalizedPosition with { X = 1 }) + new Vector2(-48, 0);
NewEnemyPosition?.Invoke(newEnemyPos);
}
private void SetBallPosition(Vector2 normalizedPosition)
{
var newBallPos = _gameArea.GlobalizePosition(normalizedPosition);
NewBallPosition?.Invoke(this, newBallPos);
NewBallPosition?.Invoke(newBallPos);
}
public static void SetNewPosition(ref Vector2 newPositionField)
{
}
}

View file

@ -1,29 +1,32 @@
using System;
using System.Collections.Generic;
using Godot.Collections;
using Pong.Scripts.Data;
using Pong.Scripts.Managers;
namespace Pong.Scripts.Objects;
public partial class Enemy : RigidBody2D
public partial class Enemy : BasePaddle
{
/// <summary>
/// draw shapes to the screen (like <see cref="_scanArea"/>).
/// </summary>
[Export] private bool _drawDebugShapes;
[Export] private double _moveSpeed;
private CollisionShape2D _collisionShape;
private Rect2 _scanArea;
private PhysicsDirectSpaceState2D _spaceState;
private readonly Variant _collider = "collider";
private PhysicsShapeQueryParameters2D _query;
public override void _Ready()
public override void _EnterTree()
{
base._EnterTree();
ScalingManager.NewEnemyPosition += SetNewPosition;
_collisionShape = GetNode<CollisionShape2D>("CollisionShape2D");
GenerateCastArea();
_spaceState = GetWorld2D().DirectSpaceState;
_query = new PhysicsShapeQueryParameters2D
{
@ -34,7 +37,17 @@ public partial class Enemy : RigidBody2D
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()
@ -43,7 +56,7 @@ public partial class Enemy : RigidBody2D
DrawRect(_scanArea, Colors.Aqua);
}
private void Scan(double delta)
private void Scan(double delta, PhysicsDirectBodyState2D state)
{
var result = _spaceState.IntersectShape(_query);
@ -53,27 +66,28 @@ public partial class Enemy : RigidBody2D
return;
}
TrackBall(delta, result);
TrackBall(delta, result, state);
}
/// <summary>
/// track the distance between the ball and the enemy paddle on the y axis and move velocity accordingly.
/// </summary>
/// <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
/// theres an object that has the Ball class.</param>
private void TrackBall(double delta, IReadOnlyList<Dictionary> result)
/// theres an object that has the Ball class.</param>
/// <param name="state"></param>
private void TrackBall(double delta, IReadOnlyList<Dictionary> result, PhysicsDirectBodyState2D state)
{
// checks if the collider is a ball, if not, 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
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.
LinearVelocity = LinearVelocity.Lerp(linearVelocity, delta);
state.LinearVelocity = LinearVelocity.Lerp(linearVelocity, delta);
}
/// <summary>

View file

@ -1,30 +1,21 @@
using Pong.Scripts.Data;
using Pong.Scripts.Managers;
namespace Pong.Scripts.Objects;
public partial class Paddle : RigidBody2D
public partial class Paddle : BasePaddle
{
[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;
/// <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()
{
_scalingManager = GetNode<ScalingManager>("../ScalingManager");
_scalingManager.NewPaddlePosition += (_, vector2) => _newPosition = vector2;
base._EnterTree();
ScalingManager.NewPaddlePosition += SetNewPosition;
}
public override void _Process(double delta)
@ -34,13 +25,13 @@ public partial class Paddle : RigidBody2D
public override void _IntegrateForces(PhysicsDirectBodyState2D state)
{
if (_newPosition.HasValue)
if (NewPosition.HasValue)
{
state.Transform = new Transform2D(0, _newPosition.Value);
_newPosition = null;
state.Transform = new Transform2D(0, NewPosition.Value);
NewPosition = null;
}
state.LinearVelocity = Vector2.Up * MoveSpeed * _verticalInput;
state.LinearVelocity = Vector2.Up * MoveSpeed.ByMeter() * _verticalInput;
}
/// <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]
name="BaseMenu"
name="CustomTypes"
description=""
author="Fries"
version=""
script="BaseMenu.cs"
script="Plugin.cs"

View file

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