• 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!

Drawing Sprite from DS_Grid/Map?

B

BJO13

Guest
Hey!

I'm creating a collectible card game and I have the cards in an array in the global object that is created in the first room. You're able to visit the 'shop' and buy a pack and it will give three random cards.

The array is 2D so that I can keep track of the card name alongside the amount of the card that is owned. Now what I'm struggling to do is display the collection of cards.

So I have my array:
Card[0,0]=0
Card[0,1]="Card One"

It's all set up like that.

When I display the collection, I want to display one card at a time. Obviously, I only want to display cards that are owned by the player, so the value on the [0,0], [1,0], [2,0] etc.. has to be greater than 0. But it has to draw the card and then the amount of the card will be shown through text below the card.

How would I go about displaying this?

And the card would change for example if I clicked a button to the right, it would go to the next card with a value greater than 0.

I know this sounds complicated and maybe there is even a better way to do this, but if I could get some help, I'd appreciate it.
 

Freddy Jones

Your Main Detective
So, you've outlined the general logic needed for trying to display it correctly, but don't know how to "draw" the cards? Correct? If you don't have a problem trying to put together what you've already made a rough draft of, then the actual "drawing" part should be easy.

You already have a 2d array which is "x" by 2, it wouldn't hurt you to make it "x" by 3. The third index I'd recommend you add is the actual card sprite. If you already have drawn out cards, you can simply refer to them later on by adding them to your Card array like you have with the name.


Code:
/// setting up
enum CardE{
    contains = 0,
    name, // 1
    sprite, // 2
};

Card[0, CardE.contains ] = 0;
Card[0, CardE.name ] = "Card One";
Card[0, CardE.sprite ] = one_of_my_sprites_actual_names;
This is almost exactly the same thing you posted above, but I added the use of the "enum"(enumarator) which makes remembering what each index represents IE ( 1 is the name, 2 is the sprite ).
You don't have to use the enumerator approach, just a recommendation.

Then drawing it would be as easy as this:

Code:
// index -> meaning, whatever card is selected
var cardSprite = Card[ index, CardE.sprite];
draw_sprite( cardSprite, subImg, x, y);
 
B

BJO13

Guest
Code:
// index -> meaning, whatever card is selected
var cardSprite = Card[ index, CardE.sprite];
draw_sprite( cardSprite, subImg, x, y);
I think this index thing is throwing me off a little.. I'm sure it's really quite simple.
The thing about the card being selected though.. how do I know what is selected? You know what I mean?
 
A

Aura

Guest
Using a variable would be the easiest approach IMO. You can keep a variable to hold the index of the card that has been selected and draw it accordingly.

Create:
Code:
current_card = 0; //Index of the current card with respect to the array
Step:
Code:
if (keyboard_check_pressed(vk_left)) {
   if (current_card <= 0) {
      current_card = 51; //51 since the array holds the 52nd card at the 51st slot
   }
   else {
      current_card -= 1;
   }
}
if (keyboard_check_pressed(vk_right)) {
   if (current_card >= 51) {
      current_card = 0; 
   }
   else {
      current_card += 1;
   }
}
...then you can easily go about drawing the appropriate card.

Code:
draw_sprite(Card[current_card, CardE.sprite], subImg, x, y);
 

Micah_DS

Member
LOL, oops, I made a quick little gmz example using a few GBC pokeyman card sprites because normal playing cards were boring (EDIT: changed and removed the sprites, as I realized I was being brainless with posting content that I do not own, even if it were for educational purposes and for fun, sigh, goodbye pokeymanz). But yeah, I got super side-tracked along the way with various things, so I'm only posting it now.
I guess, if you still don't get it after the above responses, my code should help. It's a very simple thing, really.

The example sets up the array with all the values, lets you press left and right to cycle through cards, automatically skipping any cards you do not have, cycling through until it comes to one you do have (not sure if you want to do this or not), and it displays the card name, card, and number of cards. You can also press "Q" to quit, haha.

Screenshot of the example running:
Screenie.png
Dropbox link to the gmz project file (198 kb)

I suppose I should put the code in though as well:
Code:
///CREATE

//a_cards[  0-3 card id  ,  0 number owned  1 card's name  ]
a_cards[3,1] = "Gold";
a_cards[3,0] = 2;
a_cards[2,1] = "Green";
a_cards[2,0] = 0;
a_cards[1,1] = "Red";
a_cards[1,0] = 7;
a_cards[0,1] = "Blue";
a_cards[0,0] = 1;

mycard = 1;
Code:
///STEP

/*
** NOTES
** this script allows you to press left and right to cycle through the deck of cards
** it skips over any cards that you don't have any of, and it wraps around when it comes to the end of the deck
**
** ! IMPORTANT ! this code assumes you have at least one card in the deck. IF NOT, IT WILL LOOP FOREVER!
*/

if keyboard_check_pressed(vk_left){

    if mycard > 0{
        mycard -= 1;
       
        while a_cards[mycard,0] == 0{
       
            if mycard > 0{
                mycard -= 1;
            }else{
                mycard = array_height_2d(a_cards)-1;
            }
        }
       
    }else{
        mycard = array_height_2d(a_cards)-1;
       
        while a_cards[mycard,0] == 0{
            mycard -= 1;
        }
    }
}

if keyboard_check_pressed(vk_right){

    if mycard < array_height_2d(a_cards)-1{
        mycard += 1;
       
        while a_cards[mycard,0] == 0{
       
            if mycard < array_height_2d(a_cards)-1{
                mycard += 1;
            }else{
                mycard = 0;
            }
        }

    }else{
        mycard = 0;

        while a_cards[mycard,0] == 0{
            mycard += 1;
        }
    }
}
Code:
///DRAW

draw_set_color(c_white);
draw_text(0, 0, string(a_cards[mycard,1]) + " card"); //draw current card's name at top
draw_text(16, 64, "Own: " + string(a_cards[mycard,0])); //draw number of owned of the current card
draw_sprite(s_cards, mycard, 16, 16); //draw current card
 
Last edited:
B

BJO13

Guest
Oh, goodness, you people are AMAZING. Thank you all so ,so much!

EDIT:
If my project goes through completely, I'll give a special thanks :)
 
B

BJO13

Guest
Code:
___________________________________________
############################################################################################
FATAL ERROR in
action number 1
of Draw Event
for object obj_collection_card:

draw_sprite argument 1 incorrect type (2) expecting a Number (YYGI32)
at gml_Object_obj_collection_card_DrawEvent_1 (line 3) - draw_sprite(global.cardsowned, mycard, 16, 16); //draw current card
############################################################################################
Okay, so I'm getting this error when it tries to draw the card. I'm trying to apply the above project to my own, but I took the script apart and just put it into objects.. I'm pretty sure I messed something up.
 

Micah_DS

Member
Is global.cardsowned set to a sprite? I'm guessing not, and that's why it's throwing that error. Remember, these are the arguments for this function:

draw_sprite(sprite, sub image, x, y)

I'm not sure if you opened my example or if you just looked at the code I posted, but in my example, I used "s_cards", which is a sprite that contains all of the cards as sub images. If you want to do something similar, you will need to create a single sprite in your project that contains all of the cards (if you haven't already), then replace global.cardsowned with the name of that sprite.
And always remember, if you ever find yourself using a function and aren't sure if you know how it works, you can always look it up very easily in the GameMaker help.
 
B

BJO13

Guest
Is global.cardsowned set to a sprite? I'm guessing not, and that's why it's throwing that error. Remember, these are the arguments for this function:

draw_sprite(sprite, sub image, x, y)

I'm not sure if you opened my example or if you just looked at the code I posted, but in my example, I used "s_cards", which is a sprite that contains all of the cards as sub images. If you want to do something similar, you will need to create a single sprite in your project that contains all of the cards (if you haven't already), then replace global.cardsowned with the name of that sprite.
And always remember, if you ever find yourself using a function and aren't sure if you know how it works, you can always look it up very easily in the GameMaker help.

Oh goodness, okay. Yes, I did look at the example, but I guess I didn't take the time to understand. My apologies, that makes so much sense. I do have a sprite for this.. thank you. I'm sorry.

EDIT: Works like a charm. I feel so stupid.
 
B

BJO13

Guest
No worries. Best of luck with your game!
Hey, I don't know if you may be willing to help me again, but I've come across a situation where I actually needed this as a ds_grid/ds_map, and I have been working to try to convert the code, but I'm failing to do so.
Are grids/maps harder to understand?

EDIT: I solved it!!! I'm so proud of myself.

I just needed to make call the grid from the global variable and use the index.
I don't know if what I just said makes any sense. Sorry to bring this back up!
 
Last edited by a moderator:
Top