2D Scene Collision

No problem, I am already happy you spent your valuable time to help me! :slight_smile:
I am sure I will encounter more problems that I need help with trying to find my way around CGE.
:wink:

The upload size has been increased to 100 MB and I hope @Carring can upload it here. This way others can help – I do not want to be a bottleneck :slight_smile:

I know TFloatRectangle.Collides works but remember my topic "starling vs. castle-sprites :slight_smile: It is too rough as it takes the largest sprite-scene in the atlas (for instance character walking with wide legs) and does not shrink/bound with a smaller scene (standing character).

If this is the reason why you use physics, then it’s not a good reason.

If you use .castle-sprite-sheet and the default bounding box is too large for you, you can:

  • continue using .starling-xml with TexturePacker for now.

  • or decrease the rectantangle size manually, by whatever is needed. E.g. using BoundingBox.RectangleXY.Grow(-10, -20).Collides(OtherRectangle) instead of BoundingBox.RectangleXY.Collides(OtherRectangle) .

Trying to use physics will not change anything here. Physics engine doesn’t calculate bounding box by default, and if you try to pass there BoundingBox you will land in the same problem.

If you have too large bounding box/rect, then you have to make it smaller.

I thought when I watched the white bounding box expanding and shrinking around the walking character in the editor that it would make the collision “corners” directly around the image (scene).
With BoundingBox.Rectangle I noticed there is always collision around the size of the maximum sized image, so it does not “look” at smaller images / scenes (for instance when the character is less wide with his legs), even not with starling-xml. So there is no real “bounding” box it appears?

With the physics thing you were my last resort. :slight_smile:

Thanks for increasing the upload size but it appears not to be 100 mb?

Which is why I say to use Grow(-10, -20) in my examples above. You need to make collision bounds smaller manually, at least in .castle-sprite-sheet without trimming.

Using physics does not help you here, and likely complicate things.

Hm that is 100 MB (100 * 1024 KB). Can I just upload what you send me through email here?

You could also upload it yourself wherever you prefer (Google Drive, Dropbox), or put on GitHub. I want 1. others to have chance to answer 2. others to benefit from answers :slight_smile:

Yes, sure.

Text is:
Character moves or holds by pressing arrow keys once.

With line 230 in the code switched off (MakePlayerPhysics) the character moves okay with all scenes following the parent Playerscene translation.

Problems:

With line 230 “on” and thus calling procedure MakePlayerPhysics the character slowly moves down (unwanted).

and now switching direction the scenes do not follow the parent PlayerScene translation anymore which results in’scene jumping’.

There should be collision between mouse scene (eye icon) and playerscene but there is not. What is wrong?

I am reposting here @Carring sample code (relevant to above question) with permission. It turns out I did not increase attachment size successfully on Discourse last time – now it is 100 MB, so your next attachments should work, if need arises.

Rescue_Island.zip (68.8 MB)

I’ll try to analyze the problem and answer this weekend (although if anyone can help, you’re more than welcome :slight_smile: ). Have a good weekend everyone :slight_smile:

1 Like

On compiling I noticed a message in the editor about max physics ticks, this maybe a clue?

These are not messages from the compiler, these are messages emitted by CGE when running your application.

They indicate that physics has difficulty with processing necessary calculations “fast enough”. It may indicate that you have some very complicated physics setup, or you did something time-consuming (like loading something heavy) during the game, i.e. once physics is running. It may also be completely ignored – if it happens very seldom during very long application execution, it may be that your system was just busy doing something else with other applications.

@Carring First of all, thanks for preparing a good minimal testcase of your problem. This was exactly what I asked for – a simple, instantly working, minimal application that demonstrated your questions. This allowed me to investigate the problem very quickly.

I finally got to test it, sorry for delay :slight_smile:

Note: While I provide some solutions to your physics questions below, I also found a problem in CGE physics engine that prevents it from really doing what you want. I write more details below, but you basically need collisions between 2 rigid bodies that both have Dynamic = false, and this is just not supported. Use TFloatRectangle.Collides for this case instead.

This points me back to what I wrote before in this thread and in other: Your usage of physics in this example is somewhat unnecessary. You have

  • 2 bodies,
  • 2D,
  • and you want to calculate a collision between their bounding volumes.

This is easy using TFloatRectangle.Collides. Setting up physics for this purpose is a bit “overkill” :slight_smile:

Use Mouse.WorldBoundingBox.RectangleXY.Collides(PlayerScene.WorldBoundingBox.RectangleXY) in every Update to test for collisions, and you can throw away physics code. I confirmed it adding

if Mouse.WorldBoundingBox.RectangleXY.Collides(PlayerScene.WorldBoundingBox.RectangleXY) then 
  Label1.Caption := 'collision!' 
else 
  Label1.Caption := ' ';

to the TStatePlay.Update. You have there similar code already, just commented out, so I guess you know it works :slight_smile:

Note that I just used WorldBoundingBox instead of BoundingBox — it doesn’t really matter in your case. Although I should have pointed you to WorldBoundingBox earlier, it is better if in the future you will have more complicated transformation hierarchy and PlayerScene will have some additional parent transformation moving it.

If you want to make the rectangle smaller than bounding box calculated by the engine, you need to account for it manually, using Grow(...) as I shown above. Using physics doesn’t help you here at all – you still provide explicit collider sizes to the physics engine, it doesn’t know any “better” collider sizes than what you set, and you set it based on LocalBoundingBox size.

OK, onward with physics questions:

Once you assign PlayerScene.RigidBody, the PlayerScene is affected by gravity. See the manual, Physics | Manual | Castle Game Engine “”“You can turn any TCastleTransform instance into a rigid body, which means that it will be affected by gravity and collisions with other rigid bodies.”“”.

Solution: You can toggle TRigidBody.Gravity to false. See Castle Game Engine: CastleTransform: Class TRigidBody . I.e. just add RBody.Gravity := false; to PlayerScenePhysics.

Your code sets PlayerScene.Translation and PlayerScene.Scale. But once you assign PlayerScene.RigidBody, then physics takes care of updating this object transformation, and it assumes that nothing “interferes”. Dynamic is documented at Castle Game Engine: CastleTransform: Class TRigidBody , by default it is true and as we say there “”“In this case you cannot change the TCastleTransform.Translation and other transformation properties of the related TCastleTransform after assigning TCastleTransform.RigidBody. They are under the control of the physics engine. You can still reliably read them.”“” .

Note: Your code sets RBody.Dynamic:= true;, which doesn’t do anything, Dynamic is by default true.

Solution: From what I understand your usecase, you just don’t want physics to touch your object. So you want RBody.Dynamic := false; . Moreover, as you update the transformation of PlayerScene potentially every frame, it is good for performance to set RBody.Animated := true (see Castle Game Engine: CastleTransform: Class TRigidBody ). So just add

RBody.Dynamic := false;
RBody.Animated := true;

to your PlayerScenePhysics.

Note: This advise actually makes my previous advise (RBody.Gravity := false;) not relevant anymore. If you set RBody.Dynamic := false;, then gravity is also deactivated, regardless of RBody.Gravity value. It will not hurt, but feel free to remove RBody.Gravity := false; now.

I found here 3 problems, and I’m afraid 3rd is a problem in CGE physics engine that we simply cannot fix now:

  1. Same advise as above needs to be applied to TStatePlay.MakeMousePhysics: you want to modify Mouse transformation (like Mouse.Translation) yourself, you don’t want physics engine to actually calculate any gravity etc. for it. So place

    RBody.Dynamic := false;
    RBody.Animated := true;
    

    inside MakeMousePhysics as well.

  2. The collisions of physics are resolved using 3D boxes, so the Z position and Z size of everything matters. (It would be easier if one day we’ll have a dedicated 2D-only physics engine as an option, like Box2d, it may happen one day. But for now, our physics engine is 3D, and you need to account for it, even when you want to just do 2D games.)

    And you have used boxes that have very small size in Z (both PlayerScenePhysics and MakeMousePhysics set box size in Z to 0.1, effectively) and at the same time you have spread your objects in Z far away: PlayerScene has Z = 1, PlayerScene children like StandIdleAnim have Z = 1 + 1 = 2 (as designed in CGE editor), and Mouse ha Z = 9 (as set by Mouse.Translation := Vector3(Mainviewport.PositionTo2DWorld(Container.MousePosition, true), 9)).

    So the boxes of mouse and sprites never touch in Z.

    Solution: Do not set small size, like Size.Z := Max(0.1, Size.Z);. Instead set big size, like Size.Z := 1000;, in both MakeMousePhysics and PlayerScenePhysics. This way you don’t need to modify Z position of anything, everything will work the same, and you will see collisions.

    I recall that line Size.Z := Max(0.1, Size.Z); was coming from my earlier advise, but I didn’t know your usecase, that you will spread boxes far away in Z :slight_smile: Sorry!

  3. Unfortunaltey, we are forced into a situation not supported by Kraft, our physics engine, as far as I can see in testing (I also adjusted a similar approach to examples/physics/physics_2d_collisions/ to confirm).

    You have now 2 bodies with Dynamic = false, and our current physics engine doesn’t detect collisions between them. I do not have a solution for this one, I just spent an evening searching. Using TRigidBody.Trigger doesn’t help, Kraft just doesn’t set “collides” flag on these bodies.

The 3rd point above is CGE / Kraft problem, and it doesn’t have a solution for now. You are trying to use physics engine as a mere “collision detection”, and this internally is not supported, and it is not a case we can easily fix without changing physics engine. We plan to support other physics engines (in particular, Bullet, I also mentioned Box2d above) as an option, but this is for the future.

1 Like

Thanks for sorting this out!
Overall conclusion is that I should stick to the RectangleXY.Collides.
Which is not bad after all because I use different spritescreens for different animations, so a ‘standidle’ animation by default has a smaller rectangle around it than a ‘wide legged’ walking character, so the scene box will be smaller also.
:wink: