I’ve started making a simple card game, I’m making a card game but I’m not sure how best to update rendering based on the state of the hands/board.
I have lists of integers for both player’s hands, and the state of the board. These integers simply allow me to lookup card data from a big list of cards. Logically I can add/remove cards to the lists at any time. However I’m not sure how to go about drawing the hands or the board. My game is completely 2D at the moment, so I’m using UI objects.
I’ve made a prefab which I can instantiate and change the image/text on. The question is how do I know when to add/remove these objects? I can think of some methods, but I might not be considering some alternatives.
-
Every time the board or hand changes, tell the GUI to delete all UI objects and re-create them based on the current state. Positives are it’s simple and easy, negatives are that it’s adding/removing an unnecessary amount of objects every time the state changes.
-
Every time a card is added/remove from the hand/board, send an event to the GUI so it can remove or add that card. Positives, it’s elegant and efficient. Negatives are that I have nothing linking the cards in hand with the cards being rendered, so I wouldn’t know which card to remove if there’s a duplicate in hand.
-
Actually store the UI object in the hand/board lists, so we know exactly which one to add/remove. The downside of this is I want to keep logic and rendering separate, since eventually logic will be done on the server. Possibly some sort of identifier or hash to link the two would work?
Advice? Thanks.
I recently made a card game with a dual system like this and this is what I ended up doing. I am by no means an expert but I hope this can at least help you out a little.
I made two lists of integers, one for the cards in play and one for the cards in the player’s hand
I made a special tag for the UI cards in play, and I made a tag for the UI cards in hand
I made two display methods, one for the board and one for the hand, inside of the script that handles the logical cards. These methods handle turning logical cards into game objects.
Example (C#): This method is marked RPC to allow it to be called over a network (When a card is played, it can be called in rpc mode to all players to refresh their displays)
[RPC]
void Display(){
//First check to see if there are UI cards with the tag "hand" in the scene, then clear them all from the scene
if (GameObject.FindGameObjectsWithTag ("hand").Length > 0) {
GameObject[] dispCards = GameObject.FindGameObjectsWithTag ("hand");
foreach (GameObject go in dispCards) {
Destroy (go);
}
}
//For loop to go through each of the cards currently in hand (integer list "inHand") and instantiate a new UI card object "cardFab", change its tag so it can easily be deleted later. resize and posHand are values based on screen size I have declared earlier to give it a "liquid" layout
for (int i = 0; i < inHand.Count; i++) {
GameObject newCard = (GameObject)Instantiate (cardFab, posHand*, Quaternion.identity);*
-
newCard.tag = "hand";*
-
newCard.transform.localScale = new Vector3(resize, resize, 1);*
-
//An example of setting the text on the card based on the integer ID that is currently in spot "i" of the "inHand" list. The GetText method is not relevant to your project, so do this however you have already managed to do it*
_ newCard.transform.GetChild(0).gameObject.GetComponent().text = GetText(inPlay*);_
_ //You will probably need to add a script to your card prefab. This sets an integer called “place” in the UI Card’s script that points to the index of the logical card list that corresponds to that card. Useful later with selection*_
* newCard.GetComponent().place = i;*
* }*
* }*
Like I said it may be helpful to add a script to your UI card prefabs, not only to help detect clicks, but to store some values
Here is an example of a script that could be attached to a UI card GameObject that would work well with the above example (This one requires the card have a box collider 2D/3D)
public class DispCard : MonoBehaviour {
* public int place;*
* void OnMouseDown(){*
* Camera.main.gameObject.GetComponent().selected = place;*
* }*
* }*
This script simply stores the index of the corresponding card in the logical list, and will update an integer “selected” in the script where the logical cards are. In the integer list of card IDs currently in the player’s hand, selected represents the index of the selected card ID.
Of course, there are probably many ways you could go about doing this kind of game… Mine may not even be the best, but I hope it was helpful to you. I also hope it wasn’t too confusing, I had to change a bunch of stuff to fit your scenario better. Good luck! (Especially if you are doing multiplayer… you’ll need it >.<)