• Hey Guest! Ever feel like entering a Game Jam, but the time limit is always too much pressure? We get it... You lead a hectic life and dedicating 3 whole days to make a game just doesn't work for you! So, why not enter the GMC SLOW JAM? Take your time! Kick back and make your game over 4 months! Interested? Then just click here!

If I want cards in my game what's most correct / easy way? Such as MTG or Hearthstone type cards

R

R3ZN4

Guest
Just wondering about methods of getting my objects to be cards. (I by no means want the answer handed to me, but a general idea of what direction to head in would really be helfpful ) I have it in a sort of form right now using mainly math outputs to make the card game psuedo playable. I would like to expand this base form and try to add cards like we would normally see with different abilities. I thought perhaps making 1 card pool to pull from and then defining enemy decks based on a few random values... my main question would be how should I approach making the cards? Would it be multiple arrays kind of? So I set a group of sprites in an array and then based on which 1 is loaded those corresponding stats are then loaded and then "some code somewhere that I don't have done yet" is also loaded to perform actions such as taunt or block some damage next round etc etc.
 

NightFrost

Member
I would first define the cards as pure data. At least until GMS 2.3 update comes out with various new stuff (lightweight data objects etc), the most straightforward method to define data - at least I use this a lot - is enumerator indexed arrays. For basic example, let's assume all the data we have for the cards is name, cost, attack and defense. Let's also define just two cards, a Goblin and a Knight.

First we define all our cards as enumerator values. An enumerator assigns an integer value for each of its member, starting from zero. Enumerators are global variables and can be referenced anywhere. (When game is compiled, enumerator references are replaced with actual numbers. You use them in code for convenience so you don't need to remember a bunch of numbers and have descriptive names instead.)
Code:
// Set these enumerators up in some descriptively named object, like obj_cards
enum Card_Type {
   Goblin,
   Knight
}
This means Card.Goblin stands for value 0, and Card.Knight is 1. We define card data in same manner.
Code:
enum Card_Data {
   Name,
   Cost,
   Attack,
   Defense
}
With these, we can define arrays to hold the card data, and a convenience function that creates the cards, to save us some typing time.
Code:
// Card creation function:
///@function scr_card_create(type, name, cost, attack, defense)
///@description Creates a card data array.
///@param enum Card type enumerator.
///@param name Card name.
///@param cost Cost value.
///@param attack Attack value.
///@param defense Defense value.

var _Card = [];
_Card[Card_Data.Name] = argument[1];
_Card[Card_Data.Cost] = argument[2];
_Card[Card_Data.Attack] = argument[3];
_Card[Card_Data.Defense] = argument[4];
global.Cards[@ argument[0]] = _Card;
Code:
// Setting up the cards in obj_cards continues with this:
global.Cards = [];
scr_card_create(Card_Type.Goblin, "Goblin", 1, 1, 1);
scr_card_create(Card_Type.Knight, "Knight", 3, 4, 4);
Now you have a global.Cards array tha contains an array in each entry for a specific card. To for example figure out the attack value of the knight, you would:
Code:
var _This_Card = global.Cards[Card_Type.Knight];
var _Attack_Value = _This_Card[Card_Data.Attack];
Now you can just create a generic obj_card object and when you create instances out of it, you pass it the Card_Type enumerator value, which the instance can then use to fetch and display correct sprite, values and so on.
Code:
var _New_Card = instance_create_layer(_PosX, _PosY, "Card_Layer", obj_card);
_New_Card.Type = Card_Type.Knight;
 
Last edited:
R

robproctor83

Guest
That's a good thought out system NightFrost, almost identical to how I have things in my own project. My biggest complaint though is that you have to manage the enums separate from the cards. I would prefer to define the enum in the card create function, but alas it's not possible with enums.

And, maybe I am misunderstanding, but wouldn't you use _this_card instead of _card here?

Code:
var _This_Card = global.Cards[Card_Type.Knight];
var _Attack_Value = _This_Card[Card_Data.Attack];
 

NightFrost

Member
That's a good thought out system NightFrost, almost identical to how I have things in my own project. My biggest complaint though is that you have to manage the enums separate from the cards. I would prefer to define the enum in the card create function, but alas it's not possible with enums.
I picked the idea from this forum, as it had been discussed by one or more of the resident wizards. It has served me well enough as a database-lookalike. In addition to setters, I also tend to write getter scripts. Multiple layers of arrays in arrays can become a complex structure so I'll have the scripts do the spelunking for me, and I don't need to remember the exact array layout I had built. Accessor chaining coming in 2.3 will simplify writing that stuff too...
And, maybe I am misunderstanding, but wouldn't you use _this_card instead of _card here?

Code:
var _This_Card = global.Cards[Card_Type.Knight];
var _Attack_Value = _This_Card[Card_Data.Attack];
Good catch, I fixed several typos right after posting but that one slipped me. I've fixed it in the earlier post now.
 
R

R3ZN4

Guest
With these, we can define arrays to hold the card data, and a convenience function that creates the cards, to save us some typing time.
Code:
// Card creation function:
///@function scr_card_create(type, name, cost, attack, defense)
///@description Creates a card data array.
///@param enum Card type enumerator.
///@param name Card name.
///@param cost Cost value.
///@param attack Attack value.
///@param defense Defense value.

var _Card = [];
_Card[Card_Data.Name] = argument[1];
_Card[Card_Data.Cost] = argument[2];
_Card[Card_Data.Attack] = argument[3];
_Card[Card_Data.Defense] = argument[4];
global.Cards[@ argument[0]] = _Card;
In the section "///@function scr_card_create(type, name, cost, attack, defense)" are you actually creating your own script within this code or is this a script that would be defined in another section? I am less than novice in coding to be sure so it's probably a dumb question sorry. ;)

And then I don't quite understand the naming conventions where you are doing _Name_of_Stuff... does this allow you to then create an array Goblin_Name_of_Stuff??
 

FrostyCat

Redemption Seeker
All that in the chunk you showed except for the first line is meant to go into a script named scr_card_create, and the ///@ comments are JSDoc comments.

The "naming conventions" you talked about are enums, which in NightFrost's setup are named aliases for plain numbers used reference entries in an array. He doesn't want to be in a situation where he hard codes something like global.Cards[0], then later forgets that 0 stands for Goblin.

Please, learn your basics and stop skipping steps. If you can't read the intent of NightFrost's script within 15 minutes, you're nowhere near the level needed to make a card game tick.
 
Last edited:
R

R3ZN4

Guest
All that in the chunk you showed except for the first line is meant to go into a script named scr_card_create, and the ///@ comments are JSDoc comments.

The "naming conventions" you talked about are enums, which in NightFrost's setup are named aliases for plain numbers used reference entries in an array. He doesn't want to be in a situation where he hard codes something like global.Cards[0], then later forgets that 0 stands for Goblin.

Please, learn your basics and stop skipping steps. If you can't read the intent of NightFrost's script within 15 minutes, you're nowhere near the level needed to make a card game tick.

Umm gee thanks I guess?!? edit: it had quoted it twice
 
R

R3ZN4

Guest
In the section "///@function scr_card_create(type, name, cost, attack, defense)" are you actually creating your own script within this code or is this a script that would be defined in another section? I am less than novice in coding to be sure so it's probably a dumb question sorry. ;)
So when FrostyCat "answered" me he/she never actually answered this part of the question. I found it just now and wanted to post it for others to learn if they come across this. In the help manual in game maker type in the search JSDoc Script Comments. Basically if you use these correctly in making your scripts they will behave like the in game functions giving you cue's on what info is needed when you type in your script_name().
 
Top