- Home /
Card Game [C#]
Hi everyone...I'm new to all of this, especially Unity3D. I started to design a pack of cards i could use for a game idea i have, Basically i want to have a card show up randomly when you tap a button on the screen (Android / IoS). Essentially giving you a shuffled pack feel, But... i want the cards called to be removed from the Random List of cards that Haven't been called, that way the same card won't show in the same game, until Reset.
Could anyone point me in the right direction with this?
I've made all the cards using Photoshop and imported them onto a Plane (Of which i made a prefab). How would i assing a specific number (array?) to each of these Card Prefabs...allowing me to call them to position randomly using a button?
Thanks in advance.
How is this question different from the question you already asked at http://answers.unity3d.com/questions/253031/random-tag-call-script-c.html? Please close (or append to) the old question if you need more information.
mmm, I didn't know this was a duplicate question. Perhaps you should read and try those answers , there's alot of good info there actually. And also leave comments to those that answered your other question , if you don't understand the scripts they provided , just politely mention that you need some explanation to help you learn and use Lists for yourself.
see my last comment on @whydoidoit 's answer. Then check my answer (with screenshots).
Answer by AlucardJay · May 17, 2012 at 03:14 PM
I have edited the answer to include all considerations in the comments. First though, make sure your script name is the same as the class name (e.g. public class DeckOfCards : MonoBehaviour -> script name should be DeckOfCards) :
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public class DeckOfCards : MonoBehaviour
{
public List<GameObject> deck = new List<GameObject>();
private List<GameObject> cards = new List<GameObject>();
private List<GameObject> hand = new List<GameObject>();
private int cardsDealt = 0;
private bool showReset = false;
void ResetDeck()
{
cardsDealt = 0;
for (int i = 0; i < hand.Count; i++) {
Destroy(hand[i]);
}
hand.Clear();
cards.Clear();
cards.AddRange(deck);
showReset = false;
}
GameObject DealCard()
{
if(cards.Count == 0)
{
showReset = true;
return null;
//Alternatively to auto reset the deck:
//ResetDeck();
}
int card = Random.Range(0, cards.Count - 1);
GameObject go = GameObject.Instantiate(cards[card]) as GameObject;
cards.RemoveAt(card);
if(cards.Count == 0) {
showReset = true;
}
return go;
}
void Start()
{
ResetDeck();
}
void GameOver()
{
cardsDealt = 0;
for (int v = 0; v < hand.Count; v++) {
Destroy(hand[v]);
}
hand.Clear();
cards.Clear();
cards.AddRange(deck);
}
void OnGUI()
{
if (!showReset) {
// Deal button
if (GUI.Button(new Rect(10, 10, 100, 20), "Deal"))
{
MoveDealtCard();
}
}
else {
// Reset button
if (GUI.Button(new Rect(10, 10, 100, 20), "Reset"))
{
ResetDeck();
}
}
// GameOver button
if (GUI.Button(new Rect(Screen.width - 110, 10, 100, 20), "GameOver"))
{
GameOver();
}
}
void MoveDealtCard()
{
GameObject newCard = DealCard();
// check card is null or not
if (newCard == null) {
Debug.Log("Out of Cards");
showReset = true;
return;
}
//newCard.transform.position = Vector3.zero;
newCard.transform.position = new Vector3((float)cardsDealt / 4, (float)cardsDealt / -4, (float)cardsDealt / -4); // place card 1/4 up on all axis from last
hand.Add(newCard); // add card to hand
cardsDealt ++;
}
}
Now here's where you drag and drop your card prefabs. Look in the inspector and you'll see Deck : Size : 0 .
Now change the 0 to 52. you should have the second screenshot.
This is where you drag and drop into the list. So ignore my last comment, you really should do it this way , and not the long-hand way =]
@whydoidoit this is from your JS answer, I hope you don't mind. I just needed a place to upload screenshots. I saw your link on another qn (orbit cam), I think it's really nice that you are sharing scripts. Thanks , I shall be browsing your 'site later. All the best =]
I tried to convert the OnGUI Javascript posted above to C#
using UnityEngine;
using System.Collections;
public class Deal : $$anonymous$$onoBehaviour {
void OnGUI (){
if(GUILayout.Button("Deal")) {
GameObject newCard = DeckOfCards();
newCard.transform.position = Vector3.zero; }
}
}
It isnt working tho =/ ... how can i run the script you gave me with the cards so that when i click a button .. its runs the script , eventually getting to the end and then changing to a reset button ... allowing me to start a fresh deck.
I updated the answer with the buttons. But when you reset, the previously instantiated cards are Not destroyed.
Excellent :P , i just need to work out how to get them to destroy :) thanks guys...this has been a massive learning curve for me lol. i hope to be helping out people like me verysoon .. il keep you guys updated on my progress :)
ty again!
The 'Reset' button should show when all the cards have been dealt. It is displayed when the boolean is set to true :
if(cards.Count == 0) {
showReset = true;
}
I just updated the answer to include a 'GameOver' button. I have added another list 'hand' , that stores all the cards that have been dealt. This will be useful in a card game, esp with this example showing how to destroy the cards in the 'hand' list.
Answer by whydoidoit · May 15, 2012 at 11:08 PM
You could create a script with a list of prefabs, use the inspector to make it 52 long and then drop the prefabs into each slot. That gives you 52 cards that you can access.
Your then need to make a copy of the deck and deal out the cards one at a time in random order, removing it from the copied deck.
This script might help:
#pragma strict
import System.Collections.Generic;
var deck : List.<GameObject>;
private var cards : List.<GameObject> = new List.<GameObject>();
function ResetDeck()
{
cards.Clear();
cards.AddRange(deck);
}
function DealCard() : GameObject
{
if(cards.Count==0)
{
return null;
//Alternatively to auto reset the deck:
//ResetDeck();
}
var card : int = Random.Range(0, cards.Count-1);
var go : GameObject = GameObject.Instantiate(cards[card]) as GameObject;
cards.RemoveAt(card);
return go;
}
function Start()
{
ResetDeck();
}
function RemainingCardCount()
{
return cards.Count;
}
When you call DealCard it will create a new GameObject from the prefab - you'd then need to position it etc. After 52 cards it would start returning "null" or you could check the RemainingCardCount(). In the script you could delete the return null; line and uncomment the ResetDeck() line to have it automatically start again.
You would probably want to call this in an OnGUI function that would show your button and then position the created game object according to the camera you have and where you want the item to appear. A simple OnGUI might look like this:
function OnGUI()
{
if(GUILayout.Button("Deal"))
{
var newCard : GameObject = DealCard();
newCard.transform.position = Vector3.zero; //Replace with your location
}
}
@Lodas , if you drag your cards into individual var Transforms, then you'll have to do some setting up to load those cards into the deck List :
public GameObject Club1;
public GameObject Club2;
public GameObject Club3;
public GameObject Club4;
List<GameObject> deck = new List<GameObject>();
void LoadDeckList()
{
deck.Add(Club1);
deck.Add(Club2);
deck.Add(Club3);
deck.Add(Club4); // ect ect for all cards
}
try using the method in the answer , load your card prefabs into the deck List. I have tried to convert the above answer to C# , but it is untested and could very well contain errors (C# is not my native) =]
using UnityEngine;
using System.Collections;
public class DeckAndCards : $$anonymous$$onoBehaviour
{
List<GameObject> deck = new List<GameObject>();
private List<GameObject> cards = new List<GameObject>();
void ResetDeck()
{
cards.Clear();
cards.AddRange(deck);
}
void DealCard() : GameObject
{
if(cards.Count == 0)
{
return null;
//Alternatively to auto reset the deck:
//ResetDeck();
}
int card = Random.Range(0, cards.Count - 1);
GameObject go = GameObject.Instantiate(cards[card]) as GameObject;
cards.RemoveAt(card);
return go;
}
void Start()
{
ResetDeck();
}
void RemainingCardCount()
{
return cards.Count;
}
}
To use the List in either JS or C# you just need to attach the script to a GameObject and view it in the inspector. When you expand Deck it will say 0 items, change this to 52 and you will get 52 slots. Drag the cards into those slots.
I've done this, i attached it to a Blank plane called DealCard. The prefabs are in the slots ready to go...But how do i define the list?
Ok, I am guessing this help has stopped because you don't quite understand : "attach the script to a GameObject and view it in the inspector. When you expand Deck it will say 0 items, change this to 52 and you will get 52 slots. Drag the cards into those slots". That's ok, list's and arrays are hard to get your head around when starting.
The advice you have been given is to Forget putting all your cards into separate Transforms in the Inspector, and put then into the List deck in the Inspector. This is the best method by far, soo much extra typing doing it your way.
However , if you want to write some code that populates List deck, I can help. But first you need to change your typecasting . What this means is you are putting your cards into a variable that is typecast as a Transform. e.g. public Transform Diamond1; Now if you look at the List it is typecast as GameObject. e.g. List deck = new List();
Can you see Transform and GameObject? To put Diamond1 into (the List) deck, the Diamond has to be typecast as GameObject , or the deck has to be typecast as Transform. I suggest you store the GameObject, as you can access all the components from this typecast (inc transform).
Here is the Long method for populating the list. You'll need to do the other suits (just the same as clubs):
using UnityEngine;
using System.Collections;
public class DeckAndCards : $$anonymous$$onoBehaviour
{
List<GameObject> deck = new List<GameObject>();
private List<GameObject> cards = new List<GameObject>();
public GameObject Club1;
public GameObject Club2;
public GameObject Club3;
public GameObject Club4;
public GameObject Club5;
public GameObject Club6;
public GameObject Club7;
public GameObject Club8;
public GameObject Club9;
public GameObject Club10;
public GameObject Club11;
public GameObject Club12;
public GameObject Club13; // you can do the other suits!
void LoadDeckList()
{
deck.Add(Club1);
deck.Add(Club2);
deck.Add(Club3);
deck.Add(Club4);
deck.Add(Club5);
deck.Add(Club6);
deck.Add(Club7);
deck.Add(Club8);
deck.Add(Club9);
deck.Add(Club10);
deck.Add(Club11);
deck.Add(Club12);
deck.Add(Club13);
Debug.Log(" List deck = " + deck); // this should show your List deck in the console, and show that the cards have been added
}
void ResetDeck()
{
// NOW load the List deck first
deck.Clear();
LoadDeckList();
//
cards.Clear();
cards.AddRange(deck);
}
void DealCard() : GameObject
{
if(cards.Count == 0)
{
return null;
//Alternatively to auto reset the deck:
//ResetDeck();
}
int card = Random.Range(0, cards.Count - 1);
GameObject go = GameObject.Instantiate(cards[card]) as GameObject;
cards.RemoveAt(card);
return go;
}
void Start()
{
ResetDeck();
}
void RemainingCardCount()
{
return cards.Count;
}
}
Your answer
Follow this Question
Related Questions
Multiple Cars not working 1 Answer
Distribute terrain in zones 3 Answers
Random Shuffle Listing 2 Answers
List woes. (C#) 1 Answer