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

What is the best way of handling a play area that's larger than the window size?

alandor

Member
I'm doing a card game where cards are placed in numerical in a horizontal row. They are placed one by one, starting off with just one card but by the end the row can reach up to 66 cards. After a card is placed in the row a new card is dealt to a position below the row of cards and horizontally centered in the window (see image). That card should then be drawn into position. Since the row of cards quickly become wider than the window size I need to find a way to scroll along the row of cards. What is the best way to do this?

Should I make the room size wide enough to fit the full set of cards from the start, or should I keep the room size to the size of the window and instead use an offset_x value to pan the cards. Also, are there and convenient functions or tools I should know of when scrolling across the game surface like this? I'm new to GMS so if there are built in functions that could help me I'd like to know about them.

So far I've been trying to check if the active card is being dragged close to either edge of the window and change the offset_x variable - which in turn affects where each card is drawn. I have some problems with it- maybe I can get it to work but maybe there's a better solution for me to try.

Skärmavbild 2021-09-13 kl. 14.22.09.png
 

Damderiam

Member
Don't place cards unless they're visible. Store them as structs in an array and then make it so the player is essentially looking at a 5 card wide chunk of the array. Have five objects on screen where you want the cards to go, which we'll call cardObj1, cardObj2, and so forth. cardObj1 always loads whatever index leftCard says, cardObj2 always loads the one after that, and so forth. Then, based on a counter, which we'll call leftCard, each cardObj will load the correct card from the array.

So let's say you have five cards out. Your array, cards[], should have five cards in it. leftCard will be 0, AKA the first card. cardObj1 will load and display card[0], cardObj2 will load card[1], and so forth.

Now you add a sixth card to the array. cards[] now has six cards, but you can still only see five. When your player scrolls to the right, increment leftCard by 1. Now the leftmost displayed card is card[1] and the rightmost card is card[5], which is the sixth card you just added. Remember, arrays start at 0, so "5" is actually the sixth element in the array.

If you want smooth scrolling, that's going to add a lot more complexity to the code and will involve storing 7 cards at a time - the five cards you can see plus one on either side of the window. Then you swap the cards as the player "scrolls", which would actually just be the objects moving to the left and then jumping back to the right to simulate movement.

Alternatively, yes, an offset system would work just fine. Just set each card to draw at x + x_offset and then increment/decrement x_offset as the player holds right or left, or however you want to implement that. This method is going to use a lot more memory and CPU cycles and isn't very scalable, but if you're not worried about those things then technically it doesn't really matter.
 

alandor

Member
Thanks for the answer. Given what I know for now using an x_offset seems simpler so I will start there and see if I run into memory issues. When you say "draw each card at x + x_offset" how do you suggest I do that. Currently my draw event for the card object has it's x incremented by x_offset, but I then have to decrease that amount at the end of the draw event. Doesn't seem optimal but maybe that's just how programming works.

GML:
x += obj_controller.x_offset;
draw_self();

/* other code here */

x -= obj_controller.x_offset;
 

alandor

Member
Oh, I'm noticing now an error that may simply be the result of me drawing the cards the wrong way. When the offset has shifted positions for the cards the click events are no longer activated for the right cards. So if I have cards A - B - C - D - E and they have all been shifted two steps to the left (so only C - D and E are visible), clicking on the card E will be resolved as if I'm clicking on C because that's the card occupying that position. Only it isn't drawn there. Is there a way to solve this or does it mean I shouldn't use the x_offset solution?
 

alandor

Member
Alright thank you folks. I read those articles and tried to use that principle for my game but I can't get it to work.

I attach this screenshot of my room settings in case the error lies there. I made the room larger than the viewport so that the card can move outside of it. When I deal a new card I call this function which should make the camera follow that instance but it doesn't. Any suggestions on what I'm doing wrong?

GML:
function NewActiveCard(_card){
    view_object[0] = _card;
    obj_build_game_controller.activeCardBL = _card;   
    activeCardIsInStartingSlot = true;
}
Skärmavbild 2021-09-17 kl. 19.24.14.png
 

alandor

Member
Just to be clear. I didn't initialize a camera in GML code using camera_create() and camera_set_xxx functions. My understanding is that it is created with the properties I filled in under Room Settings (seen in the image I attached). Should this work?
 

alandor

Member
Alright just for the record I figured it out :)
I misunderstood the part with the camera but I have now set it up correctly.

This is the video that explained it for me:
 
Top