I spend many days trying out but find the Kraft physics too difficult to use for 2D scene collision.
How can I use the Scene.BoundingBox.RectangleXY or a TFloatRectangle collision so it takes the dimensions of the image loaded in the scene for collision between scenes?
Or is there a more easy way to use it in TUI game stateplay?
I need a simple example. Thanks.
The âright way to do itâ is using Physics engine (currently only Kraft is available). I must admit Iâve never used it properly myself, but Iâd start with examples\physics\physics_2d_collisions example and then try checking out more advanced game-example examples\physics\physics_2d_game_sopwith.
Scene.BoundingBox solution may be easier at the beginning, but it wonât âscaleâ - i.e. it will become a burden in time. Unless you are up to implementing your own (simplified) physics engine yourself - this is also possible, but remember that itâs a huge drain of time.
Yes, you can use simple images instead of TCastleScene, yes the same comment as above applies here - this solution doesnât scale well. Itâs easier to start, but if you want to implement something complex, itâll get to a dead end eventually forcing you to implement your own sort of TCastleScene instead of using a ready solution.
My mouse is a scene and I want it to collide with Player and NPC. And between Player and NPC.
I already looked at and tried the examples you mentioned. Parts of the first one I put in my code (see topic Collison Course). I also looked at the â3d_rendering_processing/collisionsâ example that looks totally different without setting up a rigidbody but a set up in TUI state instead of the other Window examples. So this confuses me. But as I would use the CGE editor that automatically makes a setup in TUI I would like to use this.
I think I have set up the rigid body allright but I donât know how to set up the part in the update procedure.
btw: Is everything okay with Michalis? He would make an announcement the weekend before past weekend and it looks like he is almost 2 weeks not on github. I hope he is not ill?
It should then work as Mouse.BoundingBox.Collides(Player.BoundingBox) or better Mouse.BoundingBox.RectangleXY.Collides(Player.BoundingBox.RectangleXY) (as Z in your 2D setup means depth) in this case. Note, that I didnât test it - but there shouldnât be any troubles here, itâs relatively straight-forward.
Thank you. I was indeed âoffâ for most of April due to COVID, but Iâm happy to say Iâm back on my feet now!
As for the question, I see Eugene already answered it. If you just want to resolve collisions yourself, by intersecting simple 3D axis-aligned boxes (TBox3D type) or 2D rectangles (TFloatRectangle) then it is definitely possible, just use the Collides method of them.
I still have no success with the collisions.
Is this code correct and what should I set in the update procedure to make collision between mouse scene and âstandidleâ scene?
When I put
if Mouse.BoundingBox.RectangleXY.Collides(StatePlay.StandIdleAnim.BoundingBox.RectangleXY) then Label1.Caption := âYou really touched it!â else Label1.Caption := â '; in the update procedure it works okay. What is the difference with the Physics collision? Keep it track of expanding and shrinking boxes and the RectangleXY collides not?
type
TStatePlay = class(TUIState)
private
Mouse: TCastleScene;
StandIdleAnim: TCastleScene;
procedure MakeMousePhysics;
procedure MouseCollisionEnter(const CollisionDetails: TPhysicsCollisionDetails);
procedure MakeStandIdlePhysics;
public
constructor Create(AOwner: TComponent); override;
procedure Start; override;
procedure Update(const SecondsPassed: Single; var HandleInput: Boolean); override;
function Press(const Event: TInputPressRelease): Boolean; override;
end;
var
StatePlay: TStatePlay;
implementation
uses SysUtils, Math,
GameStateMenu;
{ TStatePlay ----------------------------------------------------------------- }
var
MainViewport: TCastleViewport;
Procedure TStatePlay.MouseCollisionEnter(const CollisionDetails: TPhysicsCollisionDetails);
begin
if CollisionDetails.OtherTransform <> nil then
begin
if CollisionDetails.OtherTransform = StandIdleAnim then Application.Terminate;
end;
end;
Procedure TStatePlay.MakeMousePhysics;
var
Size: TVector3;
Collider: TBoxCollider;
begin
Mouse.RigidBody := TRigidBody.Create(Mouse);
Mouse.RigidBody.Dynamic:= true;
Mouse.RigidBody.Setup2D;
Mouse.RigidBody.OnCollisionEnter:= @MouseCollisionEnter;
Collider := TBoxCollider.Create(Mouse.RigidBody);
Size := Mouse.LocalBoundingBox.Size;
Size.Z := Max(0.1, Size.Z);
Collider.Size := Size;
end;
Procedure TStatePlay.MakeStandIdlePhysics;
var
Size: TVector3;
Collider: TBoxCollider;
begin
StandIdleAnim.RigidBody := TRigidBody.Create(Mouse);
StandIdleAnim.RigidBody.Dynamic:= true;
StandIdleAnim.RigidBody.Setup2D;
Collider := TBoxCollider.Create(StandIdleAnim.RigidBody);
Size := StandIdleAnim.LocalBoundingBox.Size;
Size.Z := Max(0.1, Size.Z);
Collider.Size := Size;
end;
constructor TStatePlay.Create(AOwner: TComponent);
begin
inherited;
end;
procedure TStatePlay.Start;
begin
inherited;
DesignUrl := 'castle-data:/westbeach-gamestateplay.castle-user-interface';
MainViewport := DesignedComponent ('Viewport') as TCastleViewport;
Mouse := DesignedComponent ('Mouse') as TCastleScene;
StandIdleAnim := DesignedComponent ('StandIdleAnim') as TCastleScene;
end;
procedure TStatePlay.Update(const SecondsPassed: Single; var HandleInput: Boolean);
begin
// call procedure mousecollision here and how?
Mouse.Translation := Vector3(Mainviewport.PositionTo2DWorld(Container.MousePosition, true), 9);
end;
end.
Unfortunately I donât think I can help you much here without actually debugging your project. Just a couple of notes here:
what should I set in the update procedure to make collision
Nothing, it should work automatically, as you assign Mouse.RigidBody.OnCollisionEnter.
However, you donât seem to ever call MakeStandIdlePhysics or MakeMousePhysics. Shouldnât you do that in Start?
Also note that you should call inherited in Update the same way as you do in Start. Otherwise it may misbehave.
If it doesnât help, try setting a breakpoint or do a WriteLnLog inside MouseCollisionEnter to see if itâs called at all and what exactly is passed in CollisionDetails.
That means something is not initialized. Are you sure you are calling MakeStandIdlePhysics and MakeMousePhysicsafter you assign Mouse and StandIdleAnim variables?
Set a breakpoint inside the first procedure to call and use F8 to step over each line to see which one causes the SIGSEGV. Check if all variables are properly initialized at this line.
Can you make sure Mouse <> nil? Usually howering your mouse over it is enough if you set a breakpoint at this line. You can also check if Mouse <> nil then begin⌠before this piece of code.
Did you do the same changes in MakeStandIdlePhysics?
Note, itâs a very good idea to use a breakpoint here. It may tell a lot about when exactly SIGSEGV is happening. Is it at Mouse.RigidBody := TRigidBody.Create(Self) or on other line⌠or maybe after Start is over (i.e. somewhere around Update).
I had temporary switched off MakeStandIdlePhysics to focus on the Mouse, so this can cause no errors for now.
I tried setting up a breakpoint at every line in the code and then press F8. It gives no error indication though.