2
\$\begingroup\$

I have an issue with creating a proper boundary in GameMaker Studio when using a physics enabled room.

My room has a gravity of 0, as it is in Space. My player object has the default values, but a friction of 10 with a box shaped collision shape. I also use View0 on a 1280x720 room with a 1280x720 view. That is to be able to do screen shakes and other neat effects.

I really struggle with containing my player object properly to the room. When I use a collision with view0_boundary and add

phy_position_x = phy_position_previousx;
phy_position_y = phy_position_previousy;

then my ship would get stuck at the screen borders very frequently.

I also tried adding some sprites that block the player off the room and created a sprite, 1280x720 and spawned them at the borders. I gave my player empty events for them and set their density to 0, making them static. However, this resulted in the same problem, I got stuck in them.

Screenshot of the prototype

I need a smooth solution for this, obviously, to have a fun experience. I have this problem quite for a while, so please help me understanding how to do this properly.

\$\endgroup\$
3
\$\begingroup\$

I don't know the specifics of GameMaker, but this is how I achieved this effect in Unity.

First I defined a Boundary class that defines the limits of the play area. This class includes a method trimToBoundary that takes an arbitrary coordinates and clamps them to the boundary space, like this

Mathf.Clamp (x, xMin, xMax),
Mathf.Clamp (y, yMin, yMax),

Then in the player controller, I apply a force to the player ship when the player press the move button, and then fix the position by trimming it to the play area boundary.

transform.position = levelController.playersBoundary.trimToBoundary(transform.position.x,transform.position.y);

My code is inspired by this Unity3D tutorial. I hope it is useful to you.

\$\endgroup\$
  • \$\begingroup\$ Sorry, but GM:S works a whole lot differently. \$\endgroup\$ – DeleteMe Jul 22 '14 at 6:11
  • 1
    \$\begingroup\$ It can be scripted? If it can, then the underlying concepts are the same, whether you use a different programming language. \$\endgroup\$ – angarg12 Jul 22 '14 at 6:46
  • \$\begingroup\$ But your function are totally different. Also, yours work with 3D Code, mine with 2D. I don't even know what trimBoundary does and how to translate that to GMS. \$\endgroup\$ – DeleteMe Jul 22 '14 at 9:23
  • \$\begingroup\$ My code works on 3D but the z is always 0 so it is effectively 2D. The Clamp function trims a value between a minimum and maximum. Still, I have added another, more generalized answer that explain the abstract terms instead of concrete examples. I hope that one is easier to understand. \$\endgroup\$ – angarg12 Jul 22 '14 at 12:01
1
\$\begingroup\$

So you're using Box2D, you should just let the engine handle collisions. (It is generally good to avoid directly setting fixture's position/rotation/speed - just apply forces. iforce2d (https://www.iforce2d.net/b2dtut/) has some awesome related tutorials.)

What you currently are doing is manually setting the position of the ship to its previous position when the ship collides with the room boundaries.

What you should do is just simply NOT do that - just set the fixture for the ship and fixture for the room boundary (optimally an edge shape), and set them to collide.

If you don't know how to make two objects collide, you can achieve this just by creating a collision event (which may be empty if you want - just put a comment in there to prevent the event to be erased automatically) in one of those objects with the other object... like this :

example 1 This will cause object 'p_character' to collide with another object 'p_fixture'.

\$\endgroup\$
1
\$\begingroup\$

I've just had this same problem, and my step-by-step fix was this:

  • Make a new Object to own the collisions. Mine was called 'RoomBoundary'
  • Make sure the Object's 'Uses Physics' box is NOT checked. (If you check it you'll end up with the default physics properties, which you don't want).
  • In that Object, add a 'Create' Event which runs this script:

      // Excuse magic numbers - I have a 2048x1536 room
      var NewBoundary = physics_fixture_create();
      physics_fixture_set_chain_shape(NewBoundary, true);  // 'true' closes the loop
      physics_fixture_add_point(NewBoundary,    0,   0);
      physics_fixture_add_point(NewBoundary, 2048,   0);
      physics_fixture_add_point(NewBoundary, 2048, 1536);
      physics_fixture_add_point(NewBoundary,    0, 1536);
      physics_fixture_bind(NewBoundary, id);
      physics_fixture_delete(NewBoundary);

  • Add a 'Collision' Event (with player in my case) which runs a script containing a comment. This tells GameMaker to enable collisions between these objects. Add identical collision Events for all objects you want this boundary to apply to.

  • Add the RoomBoundary Object to the Room needing a boundary.

GameMaker will then take care of the collisions automatically using the physics system, no further action required.

(This solution was heavily based on Despicable's, and I'd have made this a comment on that answer and upvoted it, but I don't have enough rep to do either of those. Hopefully making this step-by-step adds something of value).

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.