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:
parent
3e61187065
commit
8072cf4961
12 changed files with 113 additions and 67 deletions
|
@ -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"]
|
||||||
|
|
||||||
|
|
|
@ -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"]
|
||||||
|
|
|
@ -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")
|
||||||
|
|
9
Scripts/Data/DoubleExtensions.cs
Normal file
9
Scripts/Data/DoubleExtensions.cs
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
namespace Pong.Scripts.Data;
|
||||||
|
|
||||||
|
public static class DoubleExtensions
|
||||||
|
{
|
||||||
|
public static double ByMeter(this double num)
|
||||||
|
{
|
||||||
|
return num * Constants.Meter;
|
||||||
|
}
|
||||||
|
}
|
19
Scripts/Managers/BasePaddle.cs
Normal file
19
Scripts/Managers/BasePaddle.cs
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -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)
|
||||||
|
{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,29 +1,32 @@
|
||||||
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;
|
||||||
|
|
||||||
private PhysicsDirectSpaceState2D _spaceState;
|
private PhysicsDirectSpaceState2D _spaceState;
|
||||||
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();
|
||||||
|
|
||||||
_spaceState = GetWorld2D().DirectSpaceState;
|
_spaceState = GetWorld2D().DirectSpaceState;
|
||||||
_query = new PhysicsShapeQueryParameters2D
|
_query = new PhysicsShapeQueryParameters2D
|
||||||
{
|
{
|
||||||
|
@ -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>
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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
|
|
28
addons/CustomTypes/Plugin.cs
Normal file
28
addons/CustomTypes/Plugin.cs
Normal 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
|
|
@ -1,7 +1,7 @@
|
||||||
[plugin]
|
[plugin]
|
||||||
|
|
||||||
name="BaseMenu"
|
name="CustomTypes"
|
||||||
description=""
|
description=""
|
||||||
author="Fries"
|
author="Fries"
|
||||||
version=""
|
version=""
|
||||||
script="BaseMenu.cs"
|
script="Plugin.cs"
|
|
@ -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]
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue