walls can reset the ball to its starting position

WallManager binds to the BodyEntered signal on the Area2D class and
detects if the body that entered the area is the ball class, and if it
is, it will reset the ball to its starting position. right now, theres
no scoring system. this will be added later.
This commit is contained in:
Fries 2023-05-19 00:18:38 -07:00
parent 2805cd0e95
commit 9b0ebcefba
13 changed files with 78 additions and 51 deletions

View file

@ -1,6 +1,6 @@
[gd_scene load_steps=4 format=3 uid="uid://cggi01qnnlnwg"] [gd_scene load_steps=4 format=3]
[ext_resource type="Script" path="res://Scripts/Ball.cs" id="1_474si"] [ext_resource type="Script" path="res://Scripts/Nodes/Ball.cs" id="1_474si"]
[sub_resource type="PlaceholderTexture2D" id="PlaceholderTexture2D_yq7ub"] [sub_resource type="PlaceholderTexture2D" id="PlaceholderTexture2D_yq7ub"]
size = Vector2(50, 50) size = Vector2(50, 50)
@ -9,6 +9,7 @@ size = Vector2(50, 50)
size = Vector2(50, 50) size = Vector2(50, 50)
[node name="Ball" type="CharacterBody2D"] [node name="Ball" type="CharacterBody2D"]
collision_mask = 3
script = ExtResource("1_474si") script = ExtResource("1_474si")
[node name="Sprite2D" type="Sprite2D" parent="."] [node name="Sprite2D" type="Sprite2D" parent="."]

View file

@ -1,7 +1,7 @@
[gd_scene load_steps=5 format=3 uid="uid://krt6x241s3x6"] [gd_scene load_steps=5 format=3]
[ext_resource type="PhysicsMaterial" uid="uid://e05n66x8ug77" path="res://BouncyMaterial.tres" id="1_e3kk5"] [ext_resource type="PhysicsMaterial" uid="uid://e05n66x8ug77" path="res://BouncyMaterial.tres" id="1_e3kk5"]
[ext_resource type="Script" path="res://Scripts/Enemy.cs" id="1_fbrtv"] [ext_resource type="Script" path="res://Scripts/Nodes/Enemy.cs" id="1_fbrtv"]
[sub_resource type="PlaceholderTexture2D" id="PlaceholderTexture2D_iw3nx"] [sub_resource type="PlaceholderTexture2D" id="PlaceholderTexture2D_iw3nx"]
size = Vector2(50, 75) size = Vector2(50, 75)
@ -10,6 +10,7 @@ size = Vector2(50, 75)
size = Vector2(12, 150) size = Vector2(12, 150)
[node name="Enemy" type="RigidBody2D"] [node name="Enemy" type="RigidBody2D"]
collision_mask = 3
physics_material_override = ExtResource("1_e3kk5") physics_material_override = ExtResource("1_e3kk5")
gravity_scale = 0.0 gravity_scale = 0.0
lock_rotation = true lock_rotation = true

View file

@ -1,7 +1,7 @@
[gd_scene load_steps=5 format=3 uid="uid://bklo6torhapa0"] [gd_scene load_steps=5 format=3]
[ext_resource type="PhysicsMaterial" uid="uid://e05n66x8ug77" path="res://BouncyMaterial.tres" id="1_76uik"] [ext_resource type="PhysicsMaterial" uid="uid://e05n66x8ug77" path="res://BouncyMaterial.tres" id="1_76uik"]
[ext_resource type="Script" path="res://Scripts/Paddle.cs" id="1_uv7s3"] [ext_resource type="Script" path="res://Scripts/Nodes/Paddle.cs" id="1_uv7s3"]
[sub_resource type="PlaceholderTexture2D" id="PlaceholderTexture2D_iw3nx"] [sub_resource type="PlaceholderTexture2D" id="PlaceholderTexture2D_iw3nx"]
size = Vector2(50, 75) size = Vector2(50, 75)
@ -10,6 +10,7 @@ size = Vector2(50, 75)
size = Vector2(12, 150) size = Vector2(12, 150)
[node name="Paddle" type="RigidBody2D"] [node name="Paddle" type="RigidBody2D"]
collision_mask = 3
physics_material_override = ExtResource("1_76uik") physics_material_override = ExtResource("1_76uik")
gravity_scale = 0.0 gravity_scale = 0.0
lock_rotation = true lock_rotation = true

View file

@ -1,10 +1,10 @@
[gd_scene load_steps=6 format=3 uid="uid://kmfgtiugs4m0"] [gd_scene load_steps=6 format=3 uid="uid://wn48xnd0lstq"]
[ext_resource type="PackedScene" uid="uid://bklo6torhapa0" path="res://Scenes/Paddle.tscn" id="1_5rs0o"] [ext_resource type="PackedScene" path="res://Scenes/Paddle.tscn" id="1_5rs0o"]
[ext_resource type="Script" path="res://Scripts/SceneManager.cs" id="1_m8437"] [ext_resource type="Script" path="res://Scripts/Managers/SceneManager.cs" id="1_m8437"]
[ext_resource type="PackedScene" uid="uid://cggi01qnnlnwg" path="res://Scenes/Ball.tscn" id="2_u2ksv"] [ext_resource type="PackedScene" path="res://Scenes/Ball.tscn" id="2_u2ksv"]
[ext_resource type="PackedScene" uid="uid://c5n541vsuvfk8" path="res://Scenes/Walls.tscn" id="3_jfis7"] [ext_resource type="PackedScene" path="res://Scenes/Walls.tscn" id="3_jfis7"]
[ext_resource type="PackedScene" uid="uid://krt6x241s3x6" path="res://Scenes/Enemy.tscn" id="4_uwvof"] [ext_resource type="PackedScene" path="res://Scenes/Enemy.tscn" id="4_uwvof"]
[node name="Pong" type="Node2D"] [node name="Pong" type="Node2D"]
script = ExtResource("1_m8437") script = ExtResource("1_m8437")

View file

@ -1,6 +1,6 @@
[gd_scene load_steps=8 format=3 uid="uid://c5n541vsuvfk8"] [gd_scene load_steps=8 format=3]
[ext_resource type="Script" path="res://Scripts/WallManager.cs" id="1_mxer2"] [ext_resource type="Script" path="res://Scripts/Managers/WallManager.cs" id="1_mxer2"]
[sub_resource type="PlaceholderTexture2D" id="PlaceholderTexture2D_f7jy5"] [sub_resource type="PlaceholderTexture2D" id="PlaceholderTexture2D_f7jy5"]
size = Vector2(30, 600) size = Vector2(30, 600)
@ -48,6 +48,8 @@ shape = SubResource("RectangleShape2D_sip7s")
[node name="Top" type="StaticBody2D" parent="."] [node name="Top" type="StaticBody2D" parent="."]
position = Vector2(2.08165e-12, -287) position = Vector2(2.08165e-12, -287)
collision_layer = 2
collision_mask = 2
[node name="Top" type="Sprite2D" parent="Top"] [node name="Top" type="Sprite2D" parent="Top"]
position = Vector2(2.08165e-12, 2.08165e-12) position = Vector2(2.08165e-12, 2.08165e-12)
@ -59,6 +61,8 @@ shape = SubResource("RectangleShape2D_rw4mt")
[node name="Bottom" type="StaticBody2D" parent="."] [node name="Bottom" type="StaticBody2D" parent="."]
position = Vector2(2.08165e-12, 283) position = Vector2(2.08165e-12, 283)
collision_layer = 2
collision_mask = 2
[node name="Bottom" type="Sprite2D" parent="Bottom"] [node name="Bottom" type="Sprite2D" parent="Bottom"]
position = Vector2(2.08165e-12, 2.08165e-12) position = Vector2(2.08165e-12, 2.08165e-12)

View file

@ -1,6 +1,6 @@
using Godot; using Godot;
namespace Pong.Scripts; namespace Pong.Scripts.Managers;
public partial class SceneManager : Node2D public partial class SceneManager : Node2D
{ {

View file

@ -0,0 +1,29 @@
using Godot;
namespace Pong.Scripts.Managers;
public partial class WallManager : Area2D
{
public override void _Ready()
{
BodyEntered += OnBodyEntered;
}
private void OnBodyEntered(Node2D body)
{
if (body is not Nodes.Ball ball) return;
ResetBall(ball);
}
/// <summary>
/// reset the ball to the starting position and flick it again.
/// </summary>
/// <param name="ball">a <see cref="Nodes.Ball"/> object that you want to reset.</param>
private async void ResetBall(Nodes.Ball ball)
{
ball.Velocity = Vector2.Zero;
ball.Position = Vector2.Zero;
await ToSignal(GetTree().CreateTimer(0.25), "timeout");
ball.FlickBall();
}
}

View file

@ -1,31 +1,37 @@
using Godot; using Godot;
namespace Pong.Scripts; namespace Pong.Scripts.Nodes;
public partial class Ball : CharacterBody2D public partial class Ball : CharacterBody2D
{ {
[Export] private double _ballSpeed; [Export] private double _ballSpeed;
[Export] private double _maxRandomAngle; [Export] private double _maxRandomAngle;
private Vector2 _velocity;
/// <summary> /// <summary>
/// this property multiples the ballSpeed by the <see cref="Constants.Meter">Meter</see> constant. /// this property multiples the ballSpeed by the <see cref="Constants.Meter">Meter</see> constant.
/// </summary> /// </summary>
private double BallSpeed => _ballSpeed * Constants.Meter; private double BallSpeed => _ballSpeed * Constants.Meter;
public override void _Ready() public override void _Ready()
{
FlickBall();
}
/// <summary>
/// flick the ball in a direction.
/// </summary>
internal void FlickBall()
{ {
// this should dispose when this method goes out of scope (this means after the velocity variable is assigned) // this should dispose when this method goes out of scope (this means after the velocity variable is assigned)
using var rng = new RandomNumberGenerator(); using var rng = new RandomNumberGenerator();
rng.Randomize(); rng.Randomize();
// set the velocity currently to the left of the screen with a random y angle. // set the velocity currently to the left of the screen with a random y angle.
_velocity = GetRandomStartingDirection() * BallSpeed + new Vector2(0, rng.RandfRange(-_maxRandomAngle, _maxRandomAngle) * BallSpeed); var randomAngle = new Vector2(0, rng.RandfRange(-_maxRandomAngle, _maxRandomAngle) * BallSpeed);
Velocity = GetRandomStartingDirection() * BallSpeed + randomAngle;
} }
public override void _PhysicsProcess(double delta) public override void _PhysicsProcess(double delta)
{ {
Velocity = _velocity;
CollisionCheck(delta); CollisionCheck(delta);
} }
@ -35,9 +41,9 @@ public partial class Ball : CharacterBody2D
/// <param name="delta">delta time from the <see cref="_PhysicsProcess">_PhysicsProcess</see> method.</param> /// <param name="delta">delta time from the <see cref="_PhysicsProcess">_PhysicsProcess</see> method.</param>
private void CollisionCheck(double delta) private void CollisionCheck(double delta)
{ {
var collision = MoveAndCollide(_velocity * delta); var collision = MoveAndCollide(Velocity * delta);
if (collision == null) return; if (collision == null) return;
_velocity = _velocity.Bounce(collision.GetNormal()); Velocity = Velocity.Bounce(collision.GetNormal());
} }
/// <summary> /// <summary>
@ -45,12 +51,14 @@ public partial class Ball : CharacterBody2D
/// either returns <see cref="Vector2.Left">Vector2.Left</see> or <see cref="Vector2.Right">Vector2.Right</see> /// either returns <see cref="Vector2.Left">Vector2.Left</see> or <see cref="Vector2.Right">Vector2.Right</see>
/// based on that number. /// based on that number.
/// </summary> /// </summary>
private static Vector2 GetRandomStartingDirection() { private static Vector2 GetRandomStartingDirection()
{
using var rng = new RandomNumberGenerator(); using var rng = new RandomNumberGenerator();
rng.Randomize(); rng.Randomize();
var range = rng.RandiRange(0,1); var range = rng.RandiRange(0, 1);
if (range == 0) { if (range == 0)
{
return Vector2.Left; return Vector2.Left;
} }

View file

@ -3,7 +3,7 @@ using System.Collections.Generic;
using Godot; using Godot;
using Godot.Collections; using Godot.Collections;
namespace Pong.Scripts; namespace Pong.Scripts.Nodes;
public partial class Enemy : RigidBody2D public partial class Enemy : RigidBody2D
{ {
@ -36,9 +36,9 @@ public partial class Enemy : RigidBody2D
private void Scan(double delta) private void Scan(double delta)
{ {
var spaceState = GetWorld2D().DirectSpaceState; using var spaceState = GetWorld2D().DirectSpaceState;
var query = new PhysicsShapeQueryParameters2D using var query = new PhysicsShapeQueryParameters2D
{ {
Shape = new RectangleShape2D { Size = _scanArea.Size }, Shape = new RectangleShape2D { Size = _scanArea.Size },
Exclude = new Array<Rid>(new[] { GetRid() }) Exclude = new Array<Rid>(new[] { GetRid() })
@ -65,7 +65,7 @@ public partial class Enemy : RigidBody2D
private void TrackBall(double delta, IReadOnlyList<Dictionary> result) private void TrackBall(double delta, IReadOnlyList<Dictionary> result)
{ {
// 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<Nodes.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(0, Mathf.Sign(ball.Position.Y - Position.Y)); var normalisedDistance = new Vector2(0, Mathf.Sign(ball.Position.Y - Position.Y));

View file

@ -1,6 +1,6 @@
using Godot; using Godot;
namespace Pong.Scripts; namespace Pong.Scripts.Nodes;
public partial class Paddle : RigidBody2D public partial class Paddle : RigidBody2D
{ {

View file

@ -1,17 +0,0 @@
using Godot;
using System;
public partial class WallManager : Area2D
{
// Called when the node enters the scene tree for the first time.
public override void _Ready()
{
}
// Called every frame. 'delta' is the elapsed time since the previous frame.
public override void _Process(double delta)
{
}
}