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.