0
votes

So I have a dynamic rectangular physicsbody (the player) that collides with the ground, which is not dynamic and is also a rectangle.

Whenever the two collide the player's physicsbody passes slightly through the ground and then bounces back up. I can see this visually and through using println() to log the character's Y position every frame:

117.405
107.206
96.3573
84.8607
72.7158
59.9225
46.4809
50.826   <-- Player's position dips down below surface of ground
52.3426
52.3685
52.3703
52.3704

Restitution is set to 0.0 for both physics bodies. I've even tested this in a blank project and it seems to happen no matter what.

Is there a better way to detect this collision, using raycasts, intersections of rectangles, or some other custom implementation other than Spritekit's bizarre physics?

3

3 Answers

1
votes

Have you tried adjusting the velocity for the SKPhysicsBody at all? For example, you could adjust the y velocity to never exceed a maximum value in an update loop. Or, reduce the velocity (maybe even to 0) when a contact occurs.

For the latter suggestion, you should use an additional physics body that resides below the main body as sensor. The sensor is an SKNode or SKSpriteNode (in the image below) with a dynamic SKPhysicsBody that is unaffected by gravity and pinned to the parent node. The body should not collide with anything, but simply respond to contacts with other physics bodies via its contactTestBitMask. It looks something like this.

enter image description here

This may not be the "Mario way" of doing it, but it might get you closer to something that feels like it is.

0
votes

Don't give up on SpriteKit's physics engine just yet! First of all, set this property on your physics bodies:

yourPhysicsBody.usesPreciseCollisionDetection = YES;

Keep in mind this is advantageous when you are trying to perform precise high speed collisions. SpriteKit physics is normally limited by the Sprite Kit frame cycle where it calls update then does actions, then physics, then drawing, and etc. over and over again. Thus, if you have a very quick collision there can simply be not enough time for it to register within certain frames. With precise collisions, on the other hand, you can employ SpriteKit algorithms that test multiple movement positions to pinpoint the contact.

If this fails, you can always attach a thin physics body to the site of contact before the collision occurs (if you know that the nodes will collide at a high speed). This will act as a buffer to create space between them.

0
votes

Not sure if this constitutes as an answer per se, but I've decided to implement my own physics for the platformer.

And to anyone who may be facing a similar issue as I was, I would suggest you do the same. In one of my other games, Piston Flip, I used the Spritekit physics because the game included some variation of the physics bodies and I never needed to exactly recreate the same physics interaction twice. So if you're making something that requires a little more complex physics and you don't require exact replication, go with spritekit physics.

Now if you need precision for something like a platformer, I suggest implementing it yourself. I used this tutorial as a starting point and customized from there. The irritating initial implementation aside, I am now really glad that I can control everything so accurately.