I need a little help with this:
I use mouse keys arrows or left mouse clicking on screen coordinates to make a transform move over an ImageTransform.
The key presses switches between walking and standing idle.
But if and while the transform collides with another transform it should not respond anymore if user clicks in the same direction.
I have
if Transform.LocalBoundingBox.RectangleXY.Collides(WestbeachScene8.LocalBoundingBox.RectangleXY) then
begin
If Transform.Worldboundingbox.Min.Y > WestbeachScene8.Worldboundingbox.Min.Y then
if Walkback then StandBack;
end;
Now with every click the transform “tries” to move in the direction where it collided despite of the collision.
if Event.IsKey(keyArrowUp) and not Event.KeyRepeated then
begin
if Player.Stand then Player.GoBack else Player.StandBack;
end;
So on collision the key press should be ignored when player tries to move in the same direction as long as it collides with another Transform.
When user selects another ‘key’ direction (away from the transform it collides with) it should move again in that direction.
You can just extend the condition when the key is checked? I’m not sure do I understand the problem correctly Basically you can wrap if Transform.LocalBoundingBox.RectangleXY.... check in a routine (e.g. nested function, or a method) and use it to extend the check:
function TMyState.CheckCollision: Boolean;
begin
Result :=
Transform.LocalBoundingBox.RectangleXY.Collides(WestbeachScene8.LocalBoundingBox.RectangleXY) and
(Transform.Worldboundingbox.Min.Y > WestbeachScene8.Worldboundingbox.Min.Y);
end;
procedure TMyState.Press(...)
begin
...
if Event.IsKey(keyArrowUp) and (not Event.KeyRepeated) and (not CheckCollision) then
begin
if Player.Stand then Player.GoBack else Player.StandBack;
end;
end;
I may have mixed up the conditions above, so please check this code, don’t use directly
Sorry for late reply, I had to try things out.
The extended key condition got me in the right direction but while collision is true it also prevents moving the character in another direction.
So the collision routine had to be extended too.
I have now this. It works but has its flaws because of the multiple conditions that not always work while combining and sometimes still make the character prevent walking in a different direction while colliding or make it move anyway a bit in the same direction while pressing the key for the same direction before it eventually stops.
Maybe there are better methods that are more accurate and reliable?
if NOT Player.Transform.WorldBoundingBox.RectangleXY.Collides(WestbeachScene8.WorldBoundingBox.RectangleXY) then
begin
CollisionBack := false;
CollisionFront := false;
CollisionRight := false;
CollisionLeft := false;
end;
if Player.Transform.WorldBoundingBox.RectangleXY.Collides(WestbeachScene8.WorldBoundingBox.RectangleXY) then
begin
if (CollisionBack = false) and (CollisionFront = false) and (CollisionLeft = false) and (CollisionRight = false) then Label2.Caption := 'just passing by';
if Player.WalkRight then
begin
CollisionBack := false;
CollisionFront := false;
CollisionRight := false;
if (Player.Transform.WorldBoundingBox.Max.X > WestbeachScene8.WorldBoundingBox.Min.X) and
(Player.Transform.WorldBoundingBox.Max.X < WestbeachScene8.WorldBoundingBox.Min.X + 20) and
(Player.Transform.WorldBoundingBox.Min.Y > WestbeachScene8.WorldBoundingBox.Min.Y - 10) and
(Player.Transform.WorldBoundingBox.Min.Y < WestbeachScene8.Translation.Y) then
begin
Label2.Caption:= 'colliding object at left side';
CollisionLeft := true;
Player.StandRight;
end;
end;
if Player.WalkLeft then
begin
CollisionFront := false;
CollisionBack := false;
CollisionLeft := false;
if (Player.Transform.WorldBoundingBox.Min.X <= WestbeachScene8.WorldBoundingBox.Max.X) and
(Player.Transform.WorldBoundingBox.Min.X >= WestbeachScene8.WorldBoundingBox.Min.X) and
(Player.Transform.WorldBoundingBox.Min.Y > WestbeachScene8.WorldBoundingBox.Min.Y - 10) and
(Player.Transform.WorldBoundingBox.Min.Y < WestbeachScene8.Translation.Y) then
begin
Label2.Caption:= 'colliding object at right side';
CollisionRight := true;
Player.StandLeft;
end;
end;
if Player.WalkBack then
begin
CollisionBack := false;
CollisionLeft := false;
CollisionRight := false;
if (Player.Transform.WorldBoundingBox.Max.X > WestbeachScene8.WorldBoundingBox.Min.X + 10) and
(Player.Transform.WorldBoundingBox.Min.Y > WestbeachScene8.WorldBoundingBox.Min.Y - 20) and
(Player.Transform.WorldBoundingBox.Min.Y < WestbeachScene8.Translation.Y) then
begin
Label2.Caption:= 'colliding object at front side';
CollisionFront := true;
Player.StandBack;
end;
end;
if Player.WalkFront then
begin
CollisionFront := false;
CollisionLeft := false;
CollisionRight := false;
if (Player.Transform.WorldBoundingBox.Max.X > WestbeachScene8.WorldBoundingBox.Min.X + 10) and
(Player.Transform.WorldBoundingBox.Min.Y < WestbeachScene8.Translation.Y) and
(Player.Transform.WorldBoundingBox.Min.Y > WestbeachScene8.WorldBoundingBox.Min.Y + 20) then
begin
Label2.Caption:= 'colliding object at rear side';
CollisionBack := true;
Player.StandFront;
end;
end;
And key events:
function TStatePlay.Press(const Event: TInputPressRelease): Boolean;
var I: Integer;
begin
Result := inherited;
if Result then Exit; // allow the ancestor to handle keys
if Event.IsKey(keyArrowLeft) and not Event.KeyRepeated and (CollisionRight = false) then
begin
if Player.Stand then Player.GoLeft else Player.StandLeft;
end;
if Event.IsKey(keyArrowRight) and not Event.KeyRepeated and (CollisionLeft = false) then
begin
if Player.Stand then Player.GoRight else Player.StandRight;
end;
if Event.IsKey(keyArrowUp) and (not Event.KeyRepeated) and (CollisionFront = false) then
begin
if Player.Stand then Player.GoBack else Player.StandBack;
end;
if Event.IsKey(keyArrowDown) and not Event.KeyRepeated and (CollisionBack = false) then
begin
if Player.Stand then Player.GoFront else Player.StandFront;
end;
On a first glance, to simplify this code, maybe it would be better to generalize the idea of “4 directions” into an enum type?
I.e. right now we seem to have a lot of logic doing things to “right”, and then similar logic for “left”, and then similar logic for “forward” and “back”.
Maybe it would be a good idea to instead use an enumerated type, like
This will be a bigger change, you will have to redo some logic you show me. But it may be worth it – you will have a more concise description of what is going on, and you will “force yourself” to make it really consistent for all 4x directions.