1

I have one platform which is colliding with the main character, and that works now. But if I want to add two or more platforms, the game sticks. I work with GameMaker Studio now.

// React to inputs
move = key_left + key_right;
hsp = move * movespeed;
if (vsp < 10)
    vsp += grav;

if (place_meeting(x, y+1, obj_platform) || place_meeting(x, y+1, obj_platform1)) {
    vsp = key_jump * -jumpspeed;
}

// Horizontal collision
if (place_meeting(x+hsp, y, obj_platform) || place_meeting(x+hsp, y, obj_platform1)) {
    while (!place_meeting(x+sign(hsp), y, obj_platform) || place_meeting(x+sign(hsp), y, obj_platform1)) {
        x += sign(hsp);
    }
    hsp = 0;
}
x += hsp;

// Vertical collision
if (place_meeting(x, y+vsp, obj_platform) || place_meeting(x, y+vsp, obj_platform1)) {
    while (!place_meeting(x, y+sign(vsp), obj_platform) || place_meeting(x,y + sign(vsp), obj_platform1)) {
        y += sign(vsp);
    }
    vsp = 0;
}
y += vsp;

// Diagonal collision
if(place_meeting(x+hsp, y+vsp, obj_platform) || place_meeting(x+hsp, y+vsp, obj_platform1)) {
    while(!place_meeting(x+sign(hsp), y + sign(vsp), obj_platform) || place_meeting(x+sign(hsp), y + sign(vsp), obj_platform1)) {
        x += sign(hsp);
        y += sign(vsp);
    }
    hsp = 0;
    vsp = 0;
}

What mistake am I making? Platform works like it should, but if you jump on platform1, the whole game sticks.

I have been working with Unity and GameMaker for the past two months, so I'm not really good at it.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
D. Verboom
  • 11
  • 2

2 Answers2

0

It probably sticks in the while loop. The sign function returns 1 for positive numbers, -1 for negative numbers, and 0 for 0.

If GameMaker has a logging feature, or some kind of console output, write something in the while loop. Or, if it doesn't, try something like this:

counter = 0;
while(!place_meeting(x+sign(hsp), y + sign(vsp), obj_platform) || place_meeting(x+sign(hsp), y + sign(vsp), obj_platform1)) {
    counter += 1;
    x += sign(hsp);
    y += sign(vsp);
    if (counter>100) {
        // Do something visible, for example teleport player.
    }
}

I know it's not a very efficient method, but I remember GameMaker was always a terrible IDE in terms of debugging.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
user3387666
  • 237
  • 1
  • 3
  • 9
0

Regarding:

while (!place_meeting(x+sign(hsp), y, obj_platform) || place_meeting(x+sign(hsp), y, obj_platform1)) {
    x += sign(hsp);
}

The logical NOT operator ! applies only to the first place_meeting here, so the while loop will continue as long as either

  1. you are not colliding with obj_platform or
  2. you are colliding with obj_platform1

Instead, you probably want the while loop to continue as long as you are not colliding with either of them, so you have to put brackets around everything and then negate the whole thing, like this:

while (!(place_meeting(x + sign(hsp), y, obj_platform) || place_meeting(x + sign(hsp), y, obj_platform1)))

Note that first the logical OR operator || inside the brackets gets applied, and then the whole thing is negated with ! outside the brackets.

You would have to do the same thing in the while loops for vertical and diagonal collision.

However, you should actually do this differently.

You seem to have separate objects for the first platform (obj_platform) and the second platform (obj_platform1). If you continue to use this method, you would have to add a new object for each platform you want to add to your game even though they share the same functionality, and you would have to add a new place_meeting check to your collision code for every single one of them. This is obviously very tedious and would make your collision code incredibly long.

Instead, you want to make a single object in GameMaker, for example called oPlatform, and then create multiple instances of this object. See here for more information on instances in GameMaker. The way you probably want to create the instances in this case is by placing them in the room with the room editor.

To do this, double click on your room to open the room editor, make sure the "Instances" layer is selected and not the background layer, select the object you want to place instances of in the asset browser and drag-and-drop it into the room to place an instance.

You can also "paint" with instances by holding down Alt and then pressing the left mouse button while the object is selected (make sure you have laptop mode turned off). You can also create instances in code with functions such as instance_create_layer (documentation).

When your platforms are all instances of the same object, you just have to check for collision with the object and it will check whether you are colliding with any instance of it, like this:

// Horizontal collision
if (place_meeting(x + hsp, y, oPlatform)) {
    while (!place_meeting(x + sign(hsp), y, oPlatform)) {
        x += sign(hsp);
    }
    hsp = 0;
}
x += hsp;

Remember that I called the platform object oPlatform in this example, and yours could be called differently. With this setup, you won't need to add anything to your collision code when you add more platform instances.

If you ever need to know which instance(s) of an object you collided with, use instance_place (documentation) or instance_place_list (documentation) instead of place_meeting (documentation). If you have an instance ID saved in a variable, you can also use place_meeting with that instance ID instead of the name of the object, and it will check for collision with only that instance.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Tajoshu
  • 47
  • 10