Hi, I need help with a match pair card game

Godot Version

Question

Hi there. Thank you for reading my post. =)
I’m trying to make a match card game (match 2 or match 3) and I got stuck in middle.
This is what I did in project:

  • Open 2D Scene, rename root “game”
  • Add child Node2D “Card”, then add a Sprite2D image name “777” (size 150x200), save as scene “card”
  • And I add cards to deck by this way:
    (by the way, I used 3 cards + 6 copies = 9 total)
var cardTexture = [
	preload("res://card/A.png"),
	preload("res://card/B.png"),
	preload("res://card/C.png"),
]
var Card = preload("res://card.tscn")
var deck = []
func make_card():	
	var a1 = Card.instantiate()
	a.get_node("777").texture = preload("res://card/A.png")
	var a2 = Card.instantiate()
	a.get_node("777").texture = preload("res://card/A.png")
	var a3 = Card.instantiate()
	a.get_node("777").texture = preload("res://card/A.png")
	var b1 = Card.instantiate()
	a.get_node("777").texture = preload("res://card/B.png")
	var b2 = Card.instantiate()
	a.get_node("777").texture = preload("res://card/B.png")
	var b3 = Card.instantiate()
	a.get_node("777").texture = preload("res://card/B.png")
	var c1 = Card.instantiate()
	a.get_node("777").texture = preload("res://card/C.png")
	var c2 = Card.instantiate()
	a.get_node("777").texture = preload("res://card/C.png")
	var c3 = Card.instantiate()
	a.get_node("777").texture = preload("res://card/C.png")
	deck.append(a1)
	deck.append(a2)
	deck.append(a3)
	deck.append(b1)
	deck.append(b2)
	deck.append(b3)
	deck.append(c1)
	deck.append(c2)
	deck.append(c3)
	deck.shuffle()
  • Then I place cards from deck like this: # (3x3) square
func _ready():
	for i in 3:
		for j in 3:
			var a = deck[randi() % deck.size()]
			a.position = Vector2(80,110) + Vector2(150 * i, 200 * j)
			add_child(a)
  • And then… I stuck

So, here are my questions:

  • How can I tell GODOT that I clicked 2 cards and want to compare them?
    (I don’t know how to count clicked card in the first place)
  • What (and how) to compare? Like: texture = texture (?), or var a1 = var a2 (???)
  • Anything else that make the game better would be nice. (like, 2 matched cards removed, etc…)
  • I know my script is clumsy and awkward.
    So if there is a way to improve it, I would love to listen and learn from you.

Thank you again =)
And thanks GODOT’s community.

How can I tell GODOT that I clicked 2 cards and want to compare them?

The easiest way would be to use an Area2D node.

In your card.tscn, add an Area2D node, and add a CollisionShape2D child to the area, with a rectangle shape.

You’ll need to have a script attached to the root node of your card scene.

Then, you can connect the Area2D’s input_event signal to your card script:

image

You’ll probably want to write your card script like this:

# card.gd

extends Node2D

signal clicked(card: Node)

func _on_area_2d_input_event(viewport: Node, event: InputEvent, shape_idx: int) -> void:
	if event is InputEventMouseButton:
		if event.pressed and event.button_index == MOUSE_BUTTON_LEFT:
			clicked.emit(self)

Creating your own clicked signal like this will make it a lot easier to detect when cards are clicked at a higher level.

Now, in your main make_card() function, you can connect to that clicked signal like this:

func make_card():	
	var a1 = Card.instantiate()
	a1.get_node("777").texture = preload("res://card/A.png")
	a1.clicked.connect(_on_card_clicked)
	# ...

func _on_card_clicked(card: Node):
	print("Player clicked on card: ", card)
	# handle card click/compare logic here

(btw I think there’s a typo in your posted code where you use a. for everything instead of e.g. a1., a2., etc.)

You should be able to test with just that and see the message printed when you click a card.

What (and how) to compare? Like: texture = texture (?), or var a1 = var a2 (???)

Simple comparing the card references (a1 == a2) won’t work, because the copies of each card will be different instances, which won’t compare as equal even if they’re exact duplicates of each other.

Comparing the .texture of their sprites should work. However, this isn’t a great way to do it, since in the future you may want equivalent cards to have different textures (for animations, perhaps).

Since you’ll need to add a card.gd script to handle the clicks anyways, I would recommend adding a card_name variable to the card’s script:

# card.gd

extends Node2D

signal clicked(card: Node)

@export var card_name: String = "?"

# ...

And then make sure to set that variable when creating the cards:

func make_card():	
	var a1 = Card.instantiate()
	a1.card_name = "A"
	# ...

Then, you can use that variable to check if two cards are equal using a1.card_name == a2.card_name.

Anything else that make the game better would be nice. (like, 2 matched cards removed, etc…)

To get started, I would just call card.queue_free() on each card that needs to be removed. If you want to play animations when the cards are removed, it’s easy to change this later. You’ll probably also want to deck.erase(card) as well, if you plan on using the deck for anything.

I know my script is clumsy and awkward.
So if there is a way to improve it, I would love to listen and learn from you.

The only real problem I see with your code is that make_card() is extremely repetitive, and if you ever need to add more cards or card types, it’ll be annoying to touch that code.

So the first thing I would do is convert some of your code into data, because data is much easier to edit.

e.g.:

var Card = preload("res://card.tscn")
var deck = []

var cardTexture = {
	"A": preload("res://card/A.png"),
	"B": preload("res://card/B.png"),
	"C": preload("res://card/C.png"),
}

func make_single_card(card_name: String):
	assert(card_name in cardTexture)
	
	var card = Card.instantiate()
	card.card_name = card_name
	card.get_node("777").texture = cardTexture[card_name]
	card.clicked.connect(_on_card_clicked)
	
	deck.append(card)

func make_all_cards():
	for card_name in ["A", "B", "C"]:
		for i in 3:
			make_single_card(card_name)
	deck.shuffle()

With that, I think you can handle the rest on your own.

1 Like

I’m doing a merge game that’s very similar.
This is very helpful. Thank you.