Is C# easier to learn than C++?

Well, the above code is a bit outdated already, so…

Update: I started from anew and made a new script for two nodes called “Player1” and “Player2”.

using Godot;
using System;

public class Player : Area2D
{
    // Private fields here

    // 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(float delta)
    {
        float deltaY;
        
        if (IsPlayer1() == true)
        {
            if (Input.IsKeyPressed((int)KeyList.W))
            {
                deltaY = -0.0625f / delta;
                GetNode<Area2D>("/root/Pong/Player1").Translate(new Vector2(0.0f, deltaY)); // Player1 moves up
            }
            else if (Input.IsKeyPressed((int)KeyList.S))
            {
                deltaY = 0.0625f / delta;
                GetNode<Area2D>("/root/Pong/Player1").Translate(new Vector2(0.0f, deltaY)); // Player1 moves down
            }
        }
        else if (IsPlayer2() == true) 
        {
            if (Input.IsKeyPressed((int)KeyList.Up))
            {
                deltaY = -0.0625f / delta;
                GetNode<Area2D>("/root/Pong/Player2").Translate(new Vector2(0.0f, deltaY)); // Player2 moves up
            }
            else if (Input.IsKeyPressed((int)KeyList.Down))
            {
                deltaY = 0.0625f / delta;
                GetNode<Area2D>("/root/Pong/Player2").Translate(new Vector2(0.0f, deltaY)); // Player2 moves down
            }
        }
    }

    public bool IsPlayer1() // determines if the node is Player1
    {
        if (GetPath() == "/root/Pong/Player1")
        {
            return true;
        }
        else 
        {
            return false;
        }
    }

    public bool IsPlayer2() // determines if the node is Player2
    {
        if (GetPath() == "/root/Pong/Player2")
        {
            return true;
        }
        else
        {
            return false;
        }
    }
}

I decided not to worry about the screensize to block the paddles and I will use Area2D nodes as boundaries. I kept the _Ready() function just in case I need it in the near future.

Simplicity is the ultimate sophistication.

— Leonardo Da Vinci

I’m big smart.

Why are you dividing here? The more time has passed since the last frame the more should the object move in one frame. In your case the opposite would happen. You might see some differences in player movement speed when going to Project > Project settings > General > Force fps and testing it with different values. Multiplication would be the appropriate operation.

1 Like

But physically speaking :

v_y = \frac {\Delta y} {\Delta t}

And what if Translate() wouldn’t take time into account?

Oh wait! Okay, I get it.

v_y \times \Delta t =\Delta y

Yeah, you know the velocity and the time passed and you want to know how much space should be traveled. So you multiply the velocity by the time passed, like in the second equation in your post.

2 Likes

Now, it doesn’t move.

Nevermind. It works now.

You have to change the speed to something higher as it currently is very low. Try setting it to something above 1.

For some reason, I can’t clamp Position.y without creating issues.

It’s really annoying that the paddles can get passed the screen!

using Godot;
using System;

public class Player : Area2D
{
    private float _velocityY = 250.0f;
    private float _screenSizeY;

    // Called when the node enters the scene tree for the first time.
    public override void _Ready()
    {
        _screenSizeY = GetViewport().Size.y;
    }

    //  // Called every frame. 'delta' is the elapsed time since the previous frame.
    public override void _Process(float delta)
    {
        float deltaY;

        if (Input.IsKeyPressed((int)KeyList.W))
        {
            deltaY = -_velocityY * delta; // px = px/s * s
            deltaY = (0 + deltaY < 0) ? deltaY : 0.0f;
            GetNode<Area2D>("/root/Pong/Player1").Translate(new Vector2(0.0f, deltaY)); // Player1 moves up
        }
        else if (Input.IsKeyPressed((int)KeyList.S))
        {
            deltaY = _velocityY * delta;
            deltaY = (_screenSizeY + deltaY > _screenSizeY) ? deltaY : 0.0f;
            GetNode<Area2D>("/root/Pong/Player1").Translate(new Vector2(0.0f, deltaY)); // Player1 moves down
        }

        if (Input.IsKeyPressed((int)KeyList.Up))
        {
            deltaY = -_velocityY * delta;
            deltaY = (0 + deltaY < 0) ? deltaY : 0.0f;
            GetNode<Area2D>("/root/Pong/Player2").Translate(new Vector2(0.0f, deltaY)); // Player2 moves up
        }
        else if (Input.IsKeyPressed((int)KeyList.Down))
        {
            deltaY = _velocityY * delta;
            deltaY = (_screenSizeY + deltaY > _screenSizeY) ? deltaY : 0.0f;
            GetNode<Area2D>("/root/Pong/Player2").Translate(new Vector2(0.0f, deltaY)); // Player2 moves down
        }
    }
}

I’ve been struggling with this issue for days even with the first attempt. I thought I could use collision to prevent the paddles from leaving the screen without having to create a function but I was wrong.

Maybe I’ll have to use a signal.

Have you taken a look at this node?

also using a KinematicBody2D be better than using a Area2d node which would allow for proper collision

or you could use a proper clamping function from c# or godot

or you could directly move the node position like in the “your first game” example

3 Likes

The method used in the example will only prevent the object’s origin from going beyond the screen. One will have take into account the height of the object, by subtracting/adding the object’s height relative to the origin to the min and max values.

With KinematicBody2D you could do stuff like move_and_collide.

2 Likes

By starting from anew, I actually thought of using this but because I didn’t know how to use it, I went to the Pong C# demo to see how they did it; they used Area2D nodes. I thought that they found a proper “collision”, but no. At that point, it was too late. I hope I can change a node’s type without having too many consequences.

That’s the problem. Before showing my example in my previous post, I actually tried to use Clamp(), but it didn’t work. No matter what I did, it would either just not move at all or completely ignore my instructions about the screen limit.

That’s what I tried in my first attempt; it didn’t work.


Overall, I might make the paddles Kinematic bodies and the ceiling and floor Static bodies.

Yes, it works! Finally! Thanks, guys. By the way, can I remove the collision shapes from the Players?

I restructured my game a bit. Tomorrow, I might implement more things to the ball and borders.

You could, but the players will not be able to collide with anything if they don’t have a collision shape. That’s why Godot generally warns one that a collision shape should be added after creating a KinematicBody.

Eh, I’m in a period of exams. Development training might slow down.

Update: The ball can finally bounce!

Ball.cs

using Godot;
using System;

public class Ball : KinematicBody2D
{
    [Export]
    private float _speed = 4.0f;
    
    private Vector2 _initialPosition;
    private Vector2 _direction;
    private Random _randomNumber;
    private int[] _possibleDirection;

    // Called when the node enters the scene tree for the first time.
    public override void _Ready()
    {
        _initialPosition = Position;
        _randomNumber = new Random((int) DateTime.Now.Ticks); // uses time as seed
        _possibleDirection = new int[] {-1, 1}; // -1 for left and 1 for right
        _direction = new Vector2(_possibleDirection[_randomNumber.Next(0, _possibleDirection.Length)], 0); // if index = 0, then go left. if index = 1, go right.
    }

    // Called every frame. 'delta' is the elapsed time since the previous frame.
    public override void _Process(float delta)
    {
        KinematicCollision2D collision = MoveAndCollide(_direction * _speed);

        if (collision != null && _direction.y == 0) // if the ball collides for the first time, reflect in another way
        {
            _randomNumber = new Random((int) DateTime.Now.Ticks);
            _direction = new Vector2(-_direction.x, _possibleDirection[_randomNumber.Next(0, _possibleDirection.Length)]);
            _direction = _direction.Normalized();
            MoveAndCollide(_direction * _speed);
        }
        else if (collision != null && _direction.y != 0) // otherwise, just reflect
        {
            _direction = collision.Remainder.Bounce(collision.Normal);
            _direction = _direction.Normalized();
            MoveAndCollide(_direction * _speed);
        }
    }

    public void Reset() 
    {
        Position = _initialPosition;
    }
}

Now, I’m trying to figure out how to signal a score.

Wall.cs

using Godot;
using System;

public class Wall : Node2D
{
    [Signal]
    public delegate void PlayerOneScored(int scorePoint);

    [Signal]
    public delegate void PlayerTwoScored(int scorePoint);

    private int _scoreOne, _scoreTwo;

    public int ScoreOne 
    {
        get { return _scoreOne; }
        set { _scoreOne = value; }
    }

    public int ScoreTwo
    {
        get { return _scoreTwo; }
        set { _scoreTwo = value; }
    }

    // Called when the node enters the scene tree for the first time.
    public override void _Ready()
    {
        _scoreOne = 0;
        _scoreTwo = 0;
    }

    public void OnLeftWallBodyEntered() 
    {
        ++_scoreTwo; // increment, then output
        EmitSignal("PlayerTwoScored", _scoreTwo);
        /* One point for player 2 */
    }

    public void OnRightWallBodyEntered() 
    {
        ++_scoreOne;
        EmitSignal("PlayerOneScored", _scoreOne);
        /* One point for player 1 */
    }
}

HUD.cs

using Godot;
using System;

public class HUD : CanvasLayer
{


    // Called when the node enters the scene tree for the first time.
    public override void _Ready()
    {
        GetNode("/root/Pong/Wall").Connect("PlayerOneScored", this, "OnPlayerOneScored");
        GetNode("/root/Pong/Wall").Connect("PlayerTwoScored", this, "OnPlayerTwoScored");
    }

    public void OnPlayerOneScored() 
    {
        // GetNode<Label>("ScoreOne").Text;
    }

    public void OnPlayerTwoScored()
    {

    }
}
1 Like

*double post

Ok, so I’ve stopped working on it because I realize that whenever I do something like this, I’m always lacking preparation. Improvising is just not good enough. On top of that, my room might be lacking some oxygen, which makes it even harder for me to think clearly.

To be honest, scripting languages such as Python might actually become more useful for me considering that I’m going in biology. Anyway, I’ll come back to this topic later. Gotta go get some fresh air.

From what I’ve seen in this case and before, I feel like many people who are starting programming hit a wall at some point where they really struggle to push through in order to increase their understanding of programming and learning the programming mindset. I think you just need to push through, and if you can’t find guidance on the parts that aren’t clicking for you. Moving to a different language, just moves when you hit the wall, as even in python you really need to understand things as your program grows, otherwise you end up with a really hacked together unmaintainable mess of a script.

1 Like

Yeah, I always collide with a wall at some point, but improvising certainly doesn’t help it. For now, I’m experimenting a bit with Source 2, trying to make a mod off from HL: A (not an addon).

Like a map or an actual mod?

No, it’s an actual mod, but I’m using an existing map for testing. You can use source2mod to branch off from HL: A.

https://developer.valvesoftware.com/wiki/Half-Life:_Alyx_Workshop_Tools/Modding/Source2mod

1 Like

I’ve used both programming languages and in my opinion, C++ is easier to use but harder to learn, while C# is easier to learn but a bit harder to use.
Maybe its because C++ gives you a lot more control than C#.

I didn’t start out with C# so it’s a bit hard for me to say, but wouldn’t beginners find it easier exactly because you don’t need to think about a bunch of extra details? So it would be faster to create realworld programs that do something complex as you have slightly less mental load from the technical implementation side? I guess there are some C# pitfalls if you don’t understand what it’s doing but, but I thought those would be minor.

That’s why I said that C# is easier to learn, but once you really get to using it it can get annoying.