Help with using preexisting variables and methods in signal methods in C#

Godot Version

4.2.1

Question

Hello, beginner user here. I am trying to practice by adapting some C# code I wrote for playing a game of Crazy Eights into a Godot program. I think there is something fundamental regarding putting together methods that require signals that I am still not understanding and having difficulty finding an explanation for.

I have already figured out the basics of using signals with C# and have successfully written some code with signals to hide a starting menu on a button press. But now I am trying to implement a method in my main node to run a method on a signal call from a button node and am running into an issue. For a signal to work it needs to be built in a separate, private method with the name “On’ButtonNodeName’Pressed” correct? But that means the variables and methods I am using in the _Ready method are out of scope for the new method. Trying to put them in as top level arguments results in the error “local variable or method defined in top level statement cannot be used in this context”. Is there any way I can build a signal method so that it can use my variables and methods defined in another method? Such as being able to build a signal method inside of another method, or syntax for calling in those out of scope variables and methods?

Here is the code from my main node below. Currently all the code inside of the OnDrawPressed method (near bottom) raises the “does not exist in current context” error.

using Godot;
using System;
using System.Collections.Generic;

public partial class main : Node2D
{
    // Called when the node enters the scene tree for the first time.
    public override void _Ready()
    {
        Random random = new Random();
        float PI = 3.14f;

        //Card class instances
        Card aceheart = new Card(1, 1);
        Card twoheart = new Card(2, 1);
        Card threeheart = new Card(3, 1);
        Card fourheart = new Card(4, 1);
        Card fiveheart = new Card(5, 1);
        Card sixheart = new Card(6, 1);
        Card sevenheart = new Card(7, 1);
        Card eightheart = new Card(8, 1);
        Card nineheart = new Card(9, 1);
        Card tenheart = new Card(10, 1);
        Card jackheart = new Card(11, 1);
        Card queenheart = new Card(12, 1);
        Card kingheart = new Card(13, 1);

        Card acespade = new Card(1, 2);
        Card twospade = new Card(2, 2);
        Card threespade = new Card(3, 2);
        Card fourspade = new Card(4, 2);
        Card fivespade = new Card(5, 2);
        Card sixspade = new Card(6, 2);
        Card sevenspade = new Card(7, 2);
        Card eightspade = new Card(8, 2);
        Card ninespade = new Card(9, 2);
        Card tenspade = new Card(10, 2);
        Card jackspade = new Card(11, 2);
        Card queenspade = new Card(12, 2);
        Card kingspade = new Card(13, 2);

        Card acediamond = new Card(1, 3);
        Card twodiamond = new Card(2, 3);
        Card threediamond = new Card(3, 3);
        Card fourdiamond = new Card(4, 3);
        Card fivediamond = new Card(5, 3);
        Card sixdiamond = new Card(6, 3);
        Card sevendiamond = new Card(7, 3);
        Card eightdiamond = new Card(8, 3);
        Card ninediamond = new Card(9, 3);
        Card tendiamond = new Card(10, 3);
        Card jackdiamond = new Card(11, 3);
        Card queendiamond = new Card(12, 3);
        Card kingdiamond = new Card(13, 3);

        Card aceclub = new Card(1, 4);
        Card twoclub = new Card(2, 4);
        Card threeclub = new Card(3, 4);
        Card fourclub = new Card(4, 4);
        Card fiveclub = new Card(5, 4);
        Card sixclub = new Card(6, 4);
        Card sevenclub = new Card(7, 4);
        Card eightclub = new Card(8, 4);
        Card nineclub = new Card(9, 4);
        Card tenclub = new Card(10, 4);
        Card jackclub = new Card(11, 4);
        Card queenclub = new Card(12, 4);
        Card kingclub = new Card(13, 4);

        Card centercard = new Card(1, 1);

        // lists of Card classes covering total possible number of players, then the discard pile

        List<Card> hand1 = new List<Card>() { };
        List<Card> hand2 = new List<Card>() { };
        List<Card> hand3 = new List<Card>() { };
        List<Card> hand4 = new List<Card>() { };
        List<Card> hand5 = new List<Card>() { };
        List<Card> hand6 = new List<Card>() { };
        List<Card> hand7 = new List<Card>() { };
        List<Card> hand8 = new List<Card>() { };
        List<Card> hand9 = new List<Card>() { };
        List<Card> hand10 = new List<Card>() { };

        List<Card> discardpile = new List<Card>() { };

        // list of every Card instance
        List<Card> deck = new List<Card>() { acespade, twospade, threespade, fourspade, fivespade, sixspade, sevenspade, eightspade, ninespade, tenspade, jackspade, queenspade, kingspade, aceheart, twoheart, threeheart, fourheart, fiveheart, sixheart, sevenheart, eightheart, nineheart, tenheart, jackheart, queenheart, kingheart, aceclub, twoclub, threeclub, fourclub, fiveclub, sixclub, sevenclub, eightclub, nineclub, tenclub, jackclub, queenclub, kingclub, acediamond, twodiamond, threediamond, fourdiamond, fivediamond, sixdiamond, sevendiamond, eightdiamond, ninediamond, tendiamond, jackdiamond, queendiamond, kingdiamond };

        // list of every hand list
        List<List<Card>> listofhands = new List<List<Card>>() { hand1, hand2, hand3, hand4, hand5, hand6, hand7, hand8, hand9, hand10 };

        // esablishing a variable used to pull a random Card instance from list deck and pass that instance between lists
        int cardsindeck = deck.Count;
        int consistantcard = random.Next(cardsindeck);

        // setting number of players, number of hand lists to use in each game
        // set to test value 
        int players = 4;

        StartGame(players);


        //Method for dealing cards at start of game
        void StartGame(int players)
        {
            int listlength = listofhands[players - 1].Count;

            // loop for applying enclosed loop to each hand
            while (players > 0)
            {
                // loop for pulling 5 Card instances into a hand list and removing them from list deck
                while (listlength < 5)
                {
                    consistantcard = random.Next(cardsindeck);
                    listofhands[players - 1].Add(deck[consistantcard]);
                    deck.Remove(deck[consistantcard]);
                    cardsindeck = deck.Count;
                    listlength = listofhands[players - 1].Count;
                }
                listlength = 0;
                players--;
            }

            // pulls one Card instance from the deck list to serve as the first center card/first card in discard pile
            consistantcard = random.Next(cardsindeck);
            centercard = deck[consistantcard];
            discardpile.Add(deck[consistantcard]);
            deck.Remove(deck[consistantcard]);
            MoveAllCards();
        }

        // Method for drawing one card from deck and adding it to a hand
        void Draw()
        {
            consistantcard = random.Next(cardsindeck);
            listofhands[players].Add(deck[consistantcard]);
            deck.Remove(deck[consistantcard]);
            cardsindeck = deck.Count;
            MoveAllCards();
        }

        // Method for moving all cards to their locations at once
        void MoveAllCards()
        {
            MoveCards(hand1, -400, 550, 200, 0, 0);

            MoveCards(hand2, 900, -400, 0, 200, ((3 * PI) / 2));

            MoveCards(hand3, -400, -550, 200, 0, ((2 * PI) / 2));

            MoveCards(hand4, -900, -400, 0, 200, (PI / 2));

            MoveCards(discardpile, 324, 0, 0, 0, 0);
        }

        // Method for moving Sprite2D nodes to locations on screen matching which list they are in
        void MoveCards(List<Card> hand, int x, int y, int xadd, int yadd, float rotation)
        {
            for (int i = 0; i < hand.Count; i++)
            {
                if (hand[i]._value == 1 && hand[i]._suit == 1)
                {
                    ((Sprite2D)GetNode("heart")).GlobalTranslate(new Vector2(x, y));
                    ((Sprite2D)GetNode("heart")).Rotation = rotation;
                }

                if (hand[i]._value == 2 && hand[i]._suit == 1)
                {
                    ((Sprite2D)GetNode("heart2")).GlobalTranslate(new Vector2(x, y));
                    ((Sprite2D)GetNode("heart2")).Rotation = rotation;
                }

                if (hand[i]._value == 3 && hand[i]._suit == 1)
                {
                    ((Sprite2D)GetNode("heart3")).GlobalTranslate(new Vector2(x, y));
                    ((Sprite2D)GetNode("heart3")).Rotation = rotation;
                }

                if (hand[i]._value == 4 && hand[i]._suit == 1)
                {
                    ((Sprite2D)GetNode("heart4")).GlobalTranslate(new Vector2(x, y));
                    ((Sprite2D)GetNode("heart4")).Rotation = rotation;
                }

                if (hand[i]._value == 5 && hand[i]._suit == 1)
                {
                    ((Sprite2D)GetNode("heart5")).GlobalTranslate(new Vector2(x, y));
                    ((Sprite2D)GetNode("heart5")).Rotation = rotation;
                }

                if (hand[i]._value == 6 && hand[i]._suit == 1)
                {
                    ((Sprite2D)GetNode("heart6")).GlobalTranslate(new Vector2(x, y));
                    ((Sprite2D)GetNode("heart6")).Rotation = rotation;
                }

                if (hand[i]._value == 7 && hand[i]._suit == 1)
                {
                    ((Sprite2D)GetNode("heart7")).GlobalTranslate(new Vector2(x, y));
                    ((Sprite2D)GetNode("heart7")).Rotation = rotation;
                }

                if (hand[i]._value == 8 && hand[i]._suit == 1)
                {
                    ((Sprite2D)GetNode("heart8")).GlobalTranslate(new Vector2(x, y));
                    ((Sprite2D)GetNode("heart8")).Rotation = rotation;
                }

                if (hand[i]._value == 9 && hand[i]._suit == 1)
                {
                    ((Sprite2D)GetNode("heart9")).GlobalTranslate(new Vector2(x, y));
                    ((Sprite2D)GetNode("heart9")).Rotation = rotation;
                }

                if (hand[i]._value == 10 && hand[i]._suit == 1)
                {
                    ((Sprite2D)GetNode("heart10")).GlobalTranslate(new Vector2(x, y));
                    ((Sprite2D)GetNode("heart10")).Rotation = rotation;
                }

                if (hand[i]._value == 11 && hand[i]._suit == 1)
                {
                    ((Sprite2D)GetNode("heart11")).GlobalTranslate(new Vector2(x, y));
                    ((Sprite2D)GetNode("heart11")).Rotation = rotation;
                }

                if (hand[i]._value == 12 && hand[i]._suit == 1)
                {
                    ((Sprite2D)GetNode("heart12")).GlobalTranslate(new Vector2(x, y));
                    ((Sprite2D)GetNode("heart12")).Rotation = rotation;
                }

                if (hand[i]._value == 13 && hand[i]._suit == 1)
                {
                    ((Sprite2D)GetNode("heart13")).GlobalTranslate(new Vector2(x, y));
                    ((Sprite2D)GetNode("heart13")).Rotation = rotation;
                }

                if (hand[i]._value == 1 && hand[i]._suit == 2)
                {
                    ((Sprite2D)GetNode("spade")).GlobalTranslate(new Vector2(x, y));
                    ((Sprite2D)GetNode("spade")).Rotation = rotation;
                }

                if (hand[i]._value == 2 && hand[i]._suit == 2)
                {
                    ((Sprite2D)GetNode("spade2")).GlobalTranslate(new Vector2(x, y));
                    ((Sprite2D)GetNode("spade2")).Rotation = rotation;
                }

                if (hand[i]._value == 3 && hand[i]._suit == 2)
                {
                    ((Sprite2D)GetNode("spade3")).GlobalTranslate(new Vector2(x, y));
                    ((Sprite2D)GetNode("spade3")).Rotation = rotation;
                }

                if (hand[i]._value == 4 && hand[i]._suit == 2)
                {
                    ((Sprite2D)GetNode("spade4")).GlobalTranslate(new Vector2(x, y));
                    ((Sprite2D)GetNode("spade4")).Rotation = rotation;
                }

                if (hand[i]._value == 5 && hand[i]._suit == 2)
                {
                    ((Sprite2D)GetNode("spade5")).GlobalTranslate(new Vector2(x, y));
                    ((Sprite2D)GetNode("spade5")).Rotation = rotation;
                }

                if (hand[i]._value == 6 && hand[i]._suit == 2)
                {
                    ((Sprite2D)GetNode("spade6")).GlobalTranslate(new Vector2(x, y));
                    ((Sprite2D)GetNode("spade6")).Rotation = rotation;
                }

                if (hand[i]._value == 7 && hand[i]._suit == 2)
                {
                    ((Sprite2D)GetNode("spade7")).GlobalTranslate(new Vector2(x, y));
                    ((Sprite2D)GetNode("spade7")).Rotation = rotation;
                }

                if (hand[i]._value == 8 && hand[i]._suit == 2)
                {
                    ((Sprite2D)GetNode("spade8")).GlobalTranslate(new Vector2(x, y));
                    ((Sprite2D)GetNode("spade8")).Rotation = rotation;
                }

                if (hand[i]._value == 9 && hand[i]._suit == 2)
                {
                    ((Sprite2D)GetNode("spade9")).GlobalTranslate(new Vector2(x, y));
                    ((Sprite2D)GetNode("spade9")).Rotation = rotation;
                }

                if (hand[i]._value == 10 && hand[i]._suit == 2)
                {
                    ((Sprite2D)GetNode("spade10")).GlobalTranslate(new Vector2(x, y));
                    ((Sprite2D)GetNode("spade10")).Rotation = rotation;
                }

                if (hand[i]._value == 11 && hand[i]._suit == 2)
                {
                    ((Sprite2D)GetNode("spade11")).GlobalTranslate(new Vector2(x, y));
                    ((Sprite2D)GetNode("spade11")).Rotation = rotation;
                }

                if (hand[i]._value == 12 && hand[i]._suit == 2)
                {
                    ((Sprite2D)GetNode("spade12")).GlobalTranslate(new Vector2(x, y));
                    ((Sprite2D)GetNode("spade12")).Rotation = rotation;
                }

                if (hand[i]._value == 13 && hand[i]._suit == 2)
                {
                    ((Sprite2D)GetNode("spade13")).GlobalTranslate(new Vector2(x, y));
                    ((Sprite2D)GetNode("spade13")).Rotation = rotation;
                }

                if (hand[i]._value == 1 && hand[i]._suit == 3)
                {
                    ((Sprite2D)GetNode("diamond")).GlobalTranslate(new Vector2(x, y));
                    ((Sprite2D)GetNode("diamond")).Rotation = rotation;
                }

                if (hand[i]._value == 2 && hand[i]._suit == 3)
                {
                    ((Sprite2D)GetNode("diamond2")).GlobalTranslate(new Vector2(x, y));
                    ((Sprite2D)GetNode("diamond2")).Rotation = rotation;
                }

                if (hand[i]._value == 3 && hand[i]._suit == 3)
                {
                    ((Sprite2D)GetNode("diamond3")).GlobalTranslate(new Vector2(x, y));
                    ((Sprite2D)GetNode("diamond3")).Rotation = rotation;
                }

                if (hand[i]._value == 4 && hand[i]._suit == 3)
                {
                    ((Sprite2D)GetNode("diamond4")).GlobalTranslate(new Vector2(x, y));
                    ((Sprite2D)GetNode("diamond4")).Rotation = rotation;
                }

                if (hand[i]._value == 5 && hand[i]._suit == 3)
                {
                    ((Sprite2D)GetNode("diamond5")).GlobalTranslate(new Vector2(x, y));
                    ((Sprite2D)GetNode("diamond5")).Rotation = rotation;
                }

                if (hand[i]._value == 6 && hand[i]._suit == 3)
                {
                    ((Sprite2D)GetNode("diamond6")).GlobalTranslate(new Vector2(x, y));
                    ((Sprite2D)GetNode("diamond6")).Rotation = rotation;
                }

                if (hand[i]._value == 7 && hand[i]._suit == 3)
                {
                    ((Sprite2D)GetNode("diamond7")).GlobalTranslate(new Vector2(x, y));
                    ((Sprite2D)GetNode("diamond7")).Rotation = rotation;
                }

                if (hand[i]._value == 8 && hand[i]._suit == 3)
                {
                    ((Sprite2D)GetNode("diamond8")).GlobalTranslate(new Vector2(x, y));
                    ((Sprite2D)GetNode("diamond8")).Rotation = rotation;
                }

                if (hand[i]._value == 9 && hand[i]._suit == 3)
                {
                    ((Sprite2D)GetNode("diamond9")).GlobalTranslate(new Vector2(x, y));
                    ((Sprite2D)GetNode("diamond9")).Rotation = rotation;
                }

                if (hand[i]._value == 10 && hand[i]._suit == 3)
                {
                    ((Sprite2D)GetNode("diamond10")).GlobalTranslate(new Vector2(x, y));
                    ((Sprite2D)GetNode("diamond10")).Rotation = rotation;
                }

                if (hand[i]._value == 11 && hand[i]._suit == 3)
                {
                    ((Sprite2D)GetNode("diamond11")).GlobalTranslate(new Vector2(x, y));
                    ((Sprite2D)GetNode("diamond11")).Rotation = rotation;
                }

                if (hand[i]._value == 12 && hand[i]._suit == 3)
                {
                    ((Sprite2D)GetNode("diamond12")).GlobalTranslate(new Vector2(x, y));
                    ((Sprite2D)GetNode("diamond12")).Rotation = rotation;
                }

                if (hand[i]._value == 13 && hand[i]._suit == 3)
                {
                    ((Sprite2D)GetNode("diamond13")).GlobalTranslate(new Vector2(x, y));
                    ((Sprite2D)GetNode("diamond13")).Rotation = rotation;
                }

                if (hand[i]._value == 1 && hand[i]._suit == 4)
                {
                    ((Sprite2D)GetNode("club")).GlobalTranslate(new Vector2(x, y));
                    ((Sprite2D)GetNode("club")).Rotation = rotation;
                }

                if (hand[i]._value == 2 && hand[i]._suit == 4)
                {
                    ((Sprite2D)GetNode("club2")).GlobalTranslate(new Vector2(x, y));
                    ((Sprite2D)GetNode("club2")).Rotation = rotation;
                }

                if (hand[i]._value == 3 && hand[i]._suit == 4)
                {
                    ((Sprite2D)GetNode("club3")).GlobalTranslate(new Vector2(x, y));
                    ((Sprite2D)GetNode("club3")).Rotation = rotation;
                }

                if (hand[i]._value == 4 && hand[i]._suit == 4)
                {
                    ((Sprite2D)GetNode("club4")).GlobalTranslate(new Vector2(x, y));
                    ((Sprite2D)GetNode("club4")).Rotation = rotation;
                }

                if (hand[i]._value == 5 && hand[i]._suit == 4)
                {
                    ((Sprite2D)GetNode("club5")).GlobalTranslate(new Vector2(x, y));
                    ((Sprite2D)GetNode("club5")).Rotation = rotation;
                }

                if (hand[i]._value == 6 && hand[i]._suit == 4)
                {
                    ((Sprite2D)GetNode("club6")).GlobalTranslate(new Vector2(x, y));
                    ((Sprite2D)GetNode("club6")).Rotation = rotation;
                }

                if (hand[i]._value == 7 && hand[i]._suit == 4)
                {
                    ((Sprite2D)GetNode("club7")).GlobalTranslate(new Vector2(x, y));
                    ((Sprite2D)GetNode("club7")).Rotation = rotation;
                }

                if (hand[i]._value == 8 && hand[i]._suit == 4)
                {
                    ((Sprite2D)GetNode("club8")).GlobalTranslate(new Vector2(x, y));
                    ((Sprite2D)GetNode("club8")).Rotation = rotation;
                }

                if (hand[i]._value == 9 && hand[i]._suit == 4)
                {
                    ((Sprite2D)GetNode("club9")).GlobalTranslate(new Vector2(x, y));
                    ((Sprite2D)GetNode("club9")).Rotation = rotation;
                }

                if (hand[i]._value == 10 && hand[i]._suit == 4)
                {
                    ((Sprite2D)GetNode("club10")).GlobalTranslate(new Vector2(x, y));
                    ((Sprite2D)GetNode("club10")).Rotation = rotation;
                }

                if (hand[i]._value == 11 && hand[i]._suit == 4)
                {
                    ((Sprite2D)GetNode("club11")).GlobalTranslate(new Vector2(x, y));
                    ((Sprite2D)GetNode("club11")).Rotation = rotation;
                }

                if (hand[i]._value == 12 && hand[i]._suit == 4)
                {
                    ((Sprite2D)GetNode("club12")).GlobalTranslate(new Vector2(x, y));
                    ((Sprite2D)GetNode("club12")).Rotation = rotation;
                }

                if (hand[i]._value == 13 && hand[i]._suit == 4)
                {
                    ((Sprite2D)GetNode("club13")).GlobalTranslate(new Vector2(x, y));
                    ((Sprite2D)GetNode("club13")).Rotation = rotation;
                }

                x = x + xadd;
                y = y + yadd;
            }
        }
    }

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

    }

    // Method for drawing one card from deck and adding it to a hand
    private void OnDrawPressed()
    {
        consistantcard = random.Next(cardsindeck);
        listofhands[players].Add(deck[consistantcard]);
        deck.Remove(deck[consistantcard]);
        cardsindeck = deck.Count;
        MoveAllCards();
    }

    //Class to create cards
    class Card
    {
        public uint _value { get; set; }

        public uint _suit { get; set; }

        public Card(uint value, uint suit)
        {

            _value = value;

            _suit = suit;
        }
    }
}
1 Like

You’re saying that you are “adapting some C# code” you wrote in Godot. Does that mean this program worked somewhere else? Just curious.

Your long verbose list of variables that you have are declared in _Ready(). This means that you cannot access them outside of _Ready() (e.g. in OnDrawPressed()); doing so will be out-of-scope. You must declare your variables and methods in the scope of the class rather than making them local to _Ready().

As an aside, I would like to comment on your crude implementation of cards. You know what a for-loop is. Why don’t you use one to create the card instances instead of manually typing out the instantiation of each?

EDIT: You’re also declaring a lot of inline functions in _Ready(). Move those into the class if you wish to access them elsewhere.

Headed out the door, before I go, here are two examples in c#. The first is how to interface with an existing signal. Second how is how to create customer signals.

Example #1 - existing signals

using Godot;
using System;
public partial class MyTimer:Timer {

	public Action m_timeout_func = null;

	void DoTimeout() {
		GD.Print("normal function");


		Disconnect(Timer.SignalName.Timeout, Callable.From(DoTimeout)); // and how to disconnect the signal
	}

	public override void _Ready() {

		Action m_variable_timeout_function = () => {
			GD.Print("function stored as a variable");
		};

		Start(2); // timer triggers every 2 secs

		// connect timeout signals

		Connect(Timer.SignalName.Timeout, Callable.From(DoTimeout)); // void DoTimeout() {}

		Connect(Timer.SignalName.Timeout, Callable.From(m_variable_timeout_function)); // Action m_timeout_func = () => {}

		Connect(Timer.SignalName.Timeout, Callable.From(() => {
			GD.Print("anonymous function");
		}));

	}
}

Example #2 - Customer signals

using Godot;
using System;

public partial class MySignal:Node {

	//////////////////////////////////////////////////////////////
	// [Signal] is how we create a signal for Godot in c#   //////
	//////////////////////////////////////////////////////////////

	// please note: delegate must end in --> EventHandler <--

	[Signal]
	public delegate void MyHelloWorldEventHandler(); // SignalName.MyHelloWorld created!

	[Signal]
	public delegate void MyTestEventHandler(); // SignalName.MyTest created!

	///////////////////////////
	// callable functions /////
	///////////////////////////

	// no arguments
	// Callable.From(DoTest)
	void DoTest() {
		GD.Print("############### This is a test ##################");
	}


	// string argument
	// Callable.From<string>(DoHelloWorld)
	void DoHelloWorld(string a_message) { 
		GD.Print(a_message);
	}




	public override void _Ready() {

		//////////////////////////
		// connect signals  //////
		//////////////////////////

		Connect(SignalName.MyTest, Callable.From(DoTest)); // no arguments
		Connect(SignalName.MyHelloWorld, Callable.From<string>(DoHelloWorld)); // string argument

		////////////////////////
		// emit signals ////////
		////////////////////////

		EmitSignal(SignalName.MyHelloWorld, "This is a message from the future");
		EmitSignal(SignalName.MyTest);
	}
}

Solved it myself after awhile. My variables needed to be given the static keyword for them to remain accessible to methods when defined outside of them, thus also allowing them to be accessed by multiple methods.

For any else that come across this topic: this is not how you solve the problem!

1 Like