Legacy GM [SOLVED] Corner Collision Causing Incorrect X and Y Values?

Storm1208

Member
Hey All! I'm currently working on a recreation of the popular platformer "VVVVVV" and started using the view system in GameMaker to make small, 640x480 levels in my project. These levels are all contained within one room, and when the player walks far enough out of one view it switches to another to go to the next "level".

Here's the code I typed up to test out this system:
Code:
if((obj_player.x = room_width/2))/*one level is 640x480 and room is 1280x960,
so the player being at half the width of the room means it's time to "switch levels"*/
{
       if(view_visible[0])
       {
            view_visible[0] = false;//turning off camera for first level
            view_visible[1] = true;//turning on camera for second level
            obj_titlecards.image_index = 1;//showing level name
       }
       else if(view_visible[1])//vice versa if going from level 1 to 0
       {
            view_visible[1] = false;
            view_visible[0] = true;
            obj_titlecards.image_index = 0;
       }
}
The system was working perfectly until I noticed a small bug. For some reason, if my player object encounters a corner (i.e. they are standing on the ground and also colliding with a "wall" in front of them) the view switching no longer works. I've been able to recreate the bug consistently and here's some pictures of my player encountering corners for reference:
corner error.PNG corner error 2.PNG
After the player collides with the floor and wall in a way like shown in the images, the views will no longer switch to show you which levels you're in. I concluded that this must have had something to do with how my collision code was affecting my player's x or y values but I can't seem to spot anything wrong with them.

Horizontal Collision:
Code:
//Horizontal Collision
if(place_meeting(x+hsp,y,obj_ground)) //if we're about to collide with a ground tile
{
    while(!place_meeting(x+sign(hsp),y,obj_ground))//keep moving until...
    {
        x += sign(hsp);
    }
    hsp = 0; //BAM - stop moving
}
x += hsp;
Vertical Collision:
Code:
//Vertical Collision
if(place_meeting(x,y+vsp,obj_ground)) //if we're about to collide with a ground tile
{
    while(!place_meeting(x,y+sign(vsp),obj_ground))//keep moving until...
    {
        y += sign(vsp);
    }
    vsp = 0; //BAM - stop moving
    flip = 1;
}
y += vsp;
if(vsp != 0)
{
    flip = 0;
}
I used the "show_debug_message()" code to track my player's x value and everything seems normal even after contacting the corner. I'm not entirely sure what's causing the bug but I appreciate any and all help anyone can give me!
 

Bayesian

Member
The issue is not in the code you posted. I must be in your view or camera settings. You should be using mod to trigger the camera stages as that will give you room and resolution independence although that specify doesn't matter for a re-make it would still be the best system
 

TsukaYuriko

šŸŒ 
Forum Staff
Moderator
I think it actually is in the code that was posted.

You are checking whether the player is exactly at a specific coordinate. If your player is even a fraction of a pixel away from that, this code is not going to run. I second restructuring your code to determine the room the player is in by using the mod operator, as this will not be bound to the player being at an exact coordinate at all. To check whether the player has entered a new room, keep a copy of the player's room coordinates at all time - if the current coordinates have different values than they did in the last step, you've just changed rooms.


The original issue aside, I can see a second, not yet fully apparent issue unfolding soon. You're currently using the view system in a way where every room has its own view assigned to it. However, you are limited to having a maximum of 8 views at any given time, whether visible or not, so your current approach will work until you have exactly 8 rooms. You won't be able to add more than 8 rooms like this.

I suggest to instead have just one view and change its coordinates accordingly, by manipulating the view_xview and view_yview variables to be in the top-left corner of the room the player is currently in. Since all rooms are the same size, the rest will take care of itself.
 

Storm1208

Member
I think it actually is in the code that was posted.

You are checking whether the player is exactly at a specific coordinate. If your player is even a fraction of a pixel away from that, this code is not going to run. I second restructuring your code to determine the room the player is in by using the mod operator, as this will not be bound to the player being at an exact coordinate at all. To check whether the player has entered a new room, keep a copy of the player's room coordinates at all time - if the current coordinates have different values than they did in the last step, you've just changed rooms.


The original issue aside, I can see a second, not yet fully apparent issue unfolding soon. You're currently using the view system in a way where every room has its own view assigned to it. However, you are limited to having a maximum of 8 views at any given time, whether visible or not, so your current approach will work until you have exactly 8 rooms. You won't be able to add more than 8 rooms like this.

I suggest to instead have just one view and change its coordinates accordingly, by manipulating the view_xview and view_yview variables to be in the top-left corner of the room the player is currently in. Since all rooms are the same size, the rest will take care of itself.
Your explanation makes sense and I now see why the bug was arising, but I'm a little confused on what you and Bayesian mean about implementing the mod operator. How exactly would I apply the mod operator to my code in this situation. In your post you said that I should keep a copy of the player's room coordinates at all times and reference them with the coordinates of the current step. Are you saying I should mod the coordinates of the current step by the ones from the previous step or am I misunderstanding. When you say "room coordinates", do you mean the x and y values of my player object in the room itself, or within the view for the current level?

Also, thank you for the tip on the view system. That would've quickly become an issue if I didn't resolve it now!
 

TsukaYuriko

šŸŒ 
Forum Staff
Moderator
You could use the mod operator like this:
Imagine that your sub-rooms are in a grid. The grid starts in the top-left corner, at 0,0. The room to the right of it is at 1,0 in that grid. Each grid cell contains a sub-room.

You can get the player's position in this "grid" by applying the mod operator to its position.
x mod subroom width is the x position in the grid.
y mod subroom height is the y position in the grid.

When I said "room coordinates", I meant the player's coordinates in this imaginary grid.


Do you know the built-in variables xprevious and yprevious? They keep track of the position the instance was at during the previous step.
What I was suggesting regarding "keeping a copy of the room coordinates" is to do the same, but with the player's coordinates in the sub-room grid.
This way, you can compare them to the player's current sub-room grid coordinates to check if they entered a new room.
 

Storm1208

Member
You could use the mod operator like this:
Imagine that your sub-rooms are in a grid. The grid starts in the top-left corner, at 0,0. The room to the right of it is at 1,0 in that grid. Each grid cell contains a sub-room.

You can get the player's position in this "grid" by applying the mod operator to its position.
x mod subroom width is the x position in the grid.
y mod subroom height is the y position in the grid.

When I said "room coordinates", I meant the player's coordinates in this imaginary grid.


Do you know the built-in variables xprevious and yprevious? They keep track of the position the instance was at during the previous step.
What I was suggesting regarding "keeping a copy of the room coordinates" is to do the same, but with the player's coordinates in the sub-room grid.
This way, you can compare them to the player's current sub-room grid coordinates to check if they entered a new room.
Thank you for the clarification! Your explanation helped clear up the logic for me and it makes a lot of sense. I actually ended up implementing a different system founded on similar principles to yours, but it seems to be working so far so I think I'm going to leave it for the time being.

I changed my camera control and made use of GameMakers view_xview, view_yview, view_hview, and view_wview features. If my player object's x value surpasses that of the current view's x position plus its width (i.e. it's outside of the current view's right side) the view will shift to move to the next level. Since the entire view shifts, there's no risk of the code executing again until you surpass the borders of the new view (i.e. you "exit" the new cell in the grid); and since the check for exiting the view is less precise, the glitch I was having earlier stopped occurring. Here's a look at the code for reference:

Code:
//controlling the camera and level names
       if(obj_player.x > view_xview[0] + view_wview[0])
       {
            view_xview[0] += view_wview[0];
            obj_titlecards.x += view_wview[0];
       }
       else if(obj_player.x < view_xview[0])
       {
            view_xview[0] -= view_wview[0];
            obj_titlecards.x -= view_wview[0];
       }else if(obj_player.y > view_yview[0] + view_hview[0])
       {
            view_yview[0] += view_hview[0];
            obj_titlecards.y += view_wview[0];
       }else if(obj_player.y < view_yview[0])
       {
            view_yview[0] -= view_hview[0];
            obj_titlecards.y -= view_wview[0];
       }
This results in a system that adheres similarly to the grid like system you outlined, but in a slightly different way. This system seems to be working so far but I'll definitely keep your implementation in mind in case I run into any issues with this one.

Also, thank you for letting me know about xprevious and yprevious, I was actually unaware that they existed in GameMaker and I can certainly see myself utilizing them in the future!

Thank you so much for your help everyone! I'm going to go ahead and mark the thread as "SOLVED"!
 
Top