A Card Game

I am in the process of creating a game that will simulate a table with a deck of cards. That way I can use the neutral set up to play a number of different card games.

It should work something like this. There is a deck object. When it is clicked a card appears face down. This card can be dragged around with the mouse. When it is shift clicked it will turn over. I have created the script that drags the cards around and turns the cards over but I am having problems with the script that assign a new image to each prefeb card object and I’m not sure how to randomly shuffle the deck and then produce a new card from a single deck each time.

In REALbasic I would create an array with 52 spaces and then assign a value of 1 once a card had been chosen. When the next card was chosen I would keep choosing cards until it found one that hadn’t been picked yet. How would you do this in Unity or is there a better way?

Here is my “pick a card” script which currently doesn’t work.

var card : Transform;
var whichcard = 1;

function OnMouseDown () {
	Instantiate (card,  Vector3(0, 0, 0), Quaternion.identity);
	
	//choose a suit
	if (whichcard == 1){
    card.renderer.material.mainTexture = "3Hearts";
	}
	if (whichcard == 2){
    card.renderer.material.mainTexture = "3Clubs";
	}
	if (whichcard == 3){
    card.renderer.material.mainTexture = "3Diamonds";
	}
		
	whichcard++;
}

I’m not exactly a Unity veteran myself, but I have done lots of dynamic asset creation.

You’re passing a transform to the script through the inspector, and instantiating it, but you aren’t assigning the newly created object to a new variable. Ie.

var newcard = Instantiate (card, Vector3(0,0,0), Quaternion.identity);

If you do, you can then access that unique instance of the card:
(not really code):
newcard.renderer.material.etc ;

As for how to keep track of a deck, an array would be my first impulse as well. However, I’d remove cards from the array instead of flagging them. That way you wouldn’t have to keep hitting “picked” cards. Remove the cards as you pick them and place them in another array for cards in play or something. It all depends on what kind of card game you want, I suppose.

Good luck!

That makes sense. I updated the code to this and it is now assigning a new material to each Instantiated card.

var card : Transform;
var whichcard = 1;
var material1 : Material;
var material2 : Material;
var material3 : Material;

function OnMouseDown () {
	var newcard = Instantiate (card, Vector3(0,0,0), Quaternion.identity);
	
	//choose a suit
	if (whichcard == 1){
    newcard.renderer.material = material1;
	}
	if (whichcard == 2){
    newcard.renderer.material = material2;
	}
	if (whichcard == 3){
    newcard.renderer.material = material3;
	}
		
	whichcard++;
}

I’m not too familiar with how to use arrays in Unity. Would it make sense to do the following?

  1. OnStart - create the array with 52 elements and assign a card value to each element

  2. Shuffle the array - is there a way to do this in Unity?

  3. OnMouse Down - take the first element in the array and match it to the corresponding card

  4. Instantiate the card using the above code and assign the material

  5. Move to the next element in preparation for picking another card

Does that seem like the best approach?

Found this article on it that you might find useful:

You will probably want to dump your {if} statements for a switch case statement, more effecient.

Why shuffle the array at all?

When your game starts, create a “master deck” array for your specific game. Then duplicate the array whenever you add a deck to play.

Now, when you pick a card, just draw it from a random location and delete that entry. You’ll never pull the same card twice and you don’t have to flag the card, and the draw order will be fully random.

Sure, it’s not exactly “realistic” as the card order is always in flux, but it shouldn’t matter at all as far as the outcome is concerned as long as you seed the randomizer before each round.

Just an idea. :slight_smile:

It would be much easier to use an array for the materials. Especially since you need 52 different materials, yes?

var card : Transform;
var cardMaterial : Material[];  // Make this size 52 in the inspector
var cardDeck : Array;

function Start () {
     for (i = 0; i < 52; i++) {cardDeck(i) = i;}
}

function OnMouseDown () {
	var newcard = Instantiate (card, Vector3(0,0,0), Quaternion.identity);
	
	//choose a card
	var whichCard = cardDeck(Random.Range(0,cardArray.length));
	cardDeck.RemoveAt(whichCard);
	newcard.renderer.material = cardMaterial[whichCard];
}

Warning…totally untested code above. :wink:

–Eric

I got the code working and it seems to do exactly what I want. Thanks for everyone’s help.

My only question now is how can I reset the code when I want to play a new hand?

var card : Transform; 
var cardMaterial : Material[];  // Make this size 52 in the inspector 
var cardDeck = Array(); 

function Start () { 
     for (var i = 0; i < 52; i++) {
     	cardDeck.Push(i);
     	} 
} 

function OnMouseDown () { 
   var newcard = Instantiate (card, Vector3(0,0,0), Quaternion.identity); 
    
   //choose a card 
   var whichCard = Random.Range(0,cardDeck.length); 
   newcard.renderer.material = cardMaterial[cardDeck[whichCard]]; 
   cardDeck.RemoveAt(whichCard); 
}

Probably the simplest thing is to change Start to this:

function Start() {
     InitializeDeck();
}

and then have this somewhere in the script:

function InitializeDeck() {
     cardDeck = new Array();
     for (var i = 0; i < 52; i++) { 
        cardDeck.Push(i); 
        } 
}

Then you can call InitializeDeck() whenever you want a new hand. Warning: yet more totally untested code above. :wink:

–Eric

Everything works great. Thanks for the help.