Hi.
This is part of code I use to detect collision between a (Avatar) class with transforms (walking characters) and scenery images on screen.
The problem is that if a transform within Avatar collides with a scenery image all other avatar transforms behave if they collide too. In this case if the Y value of the colliding transform < scenery image all avatar transforms y values will be - 0.01 (and disappear).
So every available avatar transform (there are 4 present in this situation) should individually check with all scenery scenes.
Avatar transforms:
Player.transform
Location.npc[1].transform
Location.npc[2].transform
Location.npc[3].transform
How can this be done?
procedure TAvatar.Scenery_Collision;
var
I: Integer;
PlayerT: TVector3;
begin
with StatePlay do
begin
if Location.SceneryAmount > 0 then
begin
For I := 1 to SceneryAmount do
begin
if Transform.WorldBoundingBox.RectangleXY.Collides(Location.Scenery[I].Image.WorldBoundingBox.RectangleXY) then
begin
PlayerT := Transform.Translation;
If Transform.Worldboundingbox.Min.Y > Location.Scenery[I].Image.Worldboundingbox.Min.Y then
begin
PlayerT.Z := Location.Scenery[I].Image.Translation.Z - 0.01;
Transform.Translation := PlayerT;
end
else
PlayerT.Z := Location.Scenery[I].Image.Translation.Z + 0.01;
Transform.Translation := PlayerT;
end
end;
;
Hm, I admit I do not folow the question (or example code) with enough precision to answer.
Can you provide more context and/or reformulate the question to be simpler – what exactly is missing, what is that you don’t know how to implement? I want to help but I’m not sure how in this case
@michalis
First I want to check collision between player transform (which is a transform in my TAvatar type) and the array of scenes (scenery images) so if I make Transform into Player.Transform this works okay:
procedure TAvatar.Scenery_Collision;
var
I: Integer;
PlayerT: TVector3;
begin
with StatePlay do
begin
if Location.SceneryAmount > 0 then
begin
For I := 1 to SceneryAmount do
begin
if Player.Transform.WorldBoundingBox.RectangleXY.Collides(Location.Scenery[I].Image.WorldBoundingBox.RectangleXY) then
begin
PlayerT := Transform.Translation;
If Player.Transform.Worldboundingbox.Min.Y > Location.Scenery[I].Image.Worldboundingbox.Min.Y then
begin
PlayerT.Z := Location.Scenery[I].Image.Translation.Z - 0.01;
Player.Transform.Translation := PlayerT;
end
else
PlayerT.Z := Location.Scenery[I].Image.Translation.Z + 0.01;
Player.Transform.Translation := PlayerT;
end
end;
But there are more player transforms in TAvatar, for every character on screen.
These are Location.npc[1], Location.npc[2] etcetera.
So for collision between npc and the array I could make:
procedure TAvatar.Scenery_Collision;
var
I: Integer;
PlayerT: TVector3;
begin
with StatePlay do
begin
if Location.SceneryAmount > 0 then
begin
For I := 1 to SceneryAmount do
begin
if Location.NPC[1].Transform.WorldBoundingBox.RectangleXY.Collides(Location.Scenery[I].Image.WorldBoundingBox.RectangleXY) then
begin
PlayerT := Player.Transform.Translation;
If Location.npc[1].Transform.Worldboundingbox.Min.Y > Location.Scenery[I].Image.Worldboundingbox.Min.Y then
begin
PlayerT.Z := Location.Scenery[I].Image.Translation.Z - 0.01;
Location.NPC[1].Transform.Translation := PlayerT;
end
else
PlayerT.Z := Location.Scenery[I].Image.Translation.Z + 0.01;
Location.NPC[1].Transform.Translation := PlayerT;
end
end;
But how can I put this in one procedure (loop? ) so player and npc transforms are all read one by one and check individually with the array of image scenes?
Hm, I don’t understand all details, but maybe you just want a for loop within a for loop?
for I := 1 to SceneryAmount do
for NpcIndex := 1 to ... do
begin
if Location.NPC[NpcIndex].Transform.WorldBoundingBox.RectangleXY.Collides(Location.Scenery[I].Image.WorldBoundingBox.RectangleXY) then
...
Note: Use local variables to make a long lines like that shorter. E.g.
SceneryImage := Location.Scenery[I].Image;
NpcTransform := Location.NPC[NpcIndex].Transform;
if NpcTransform.WorldBoundingBox.RectangleXY.Collides(SceneryImage.WorldBoundingBox.RectangleXY) then
...
You can also define helper routines, like
function BoxesCollideIn2D(const T1, T2: TCastleTransform): Boolean;
begin
Result := T1.WorldBoundingBox.RectangleXY.Colldes(T2.WorldBoundingBox.RectangleXY);
end;
Great! This is indeed what I looked for. Why did I not think of that?
Hm, I don’t understand this function, sorry