PDA

View Full Version : Weird problems with collision in Super Heli Land



Darkhog
08-08-2013, 12:01 AM
I thought this'd be most appropriate board to ask. I have fixed crashes (and hopefully there won't be more for a time), but now I have more mundane and less critical problem, namely shaking (and occasional stuck) in collision detection.

To reproduce and help debug me issue, clone my git repository: https://github.com/darkhog/SuperHeliLand and follow instructions found in COMPILING.txt

You'll need to get to debug mode (right CTRL+left Shift+D) and then collide into other Marine Pop (submarine) to see it.

Here's the code that handles movement and reacting to collisions:

//movement if al_key[Options.binding_up]<>0 then begin MarioGO.y:=MarioGO.y-4; lastup:=true; end;
if al_key[Options.binding_down]<>0 then begin MarioGO.y:=MarioGO.y+4; lastdown:=true; end;
if al_key[Options.binding_left]<>0 then begin MarioGO.x:=MarioGO.x-4; lastleft:=true; end;
if al_key[Options.binding_right]<>0 then begin MarioGO.x:=MarioGO.x+4; lastright:=true; end;


//reacting to collisions;
if ((MarioGO.isColliding(OtherMarioGO)) and (lastup)) then MarioGO.y:=MarioGO.y+8;
if ((MarioGO.isColliding(OtherMarioGO)) and (lastdown)) then MarioGO.y:=MarioGO.y-8;
if ((MarioGO.isColliding(OtherMarioGO)) and (lastleft)) then MarioGO.x:=MarioGO.x+8;
if ((MarioGO.isColliding(OtherMarioGO)) and (lastright)) then MarioGO.x:=MarioGO.x-8;


//if ESC was pressed, return to main menu
if al_key[AL_KEY_ESC]<>0 then CurrentState:=MainMenuState;
inherited Update;

All of it is in TDebugState.Update (States unit).
Problem is that when I'm trying to subtract/add in reacting to collisions phase exact same amount that was added to position in movement phase, object get stuck and can't get out of it by other means than going sideways if that was collision from top/bottom or by moving vertically, if I was moved horizontally when collision occurred. When I'm subtract 8 instead of 4, I get object shaking, like it has epilepsy. What gives?

Can someone help me debug that issue? I also can't move object by smaller/bigger amount that 4 as my game is scaled up and single pixel is 4x4 square on screen and as you know, it'd look weird if character can move by half of pixel.

//edit: Blue square that sometimes pops on screen means that collision between both objects has been detected. Collision itself is fine, just reaction to it is not.

Super Vegeta
08-08-2013, 07:11 AM
I'll try to compile this when I get home from work, but looking at the code, I must give a simple suggestion: You should either check for collision right after moving in every single direction, or check for collision once and then retract in all directions.

SilverWarior
08-08-2013, 08:54 AM
I tested this and have no clue why this is happening.
The thing that caught my curiosity is that sometimes TDebugState.Update fires several times even if I press key once for short time. So if you are lucky you can get two characters to overlap each other for more than 4 pixels even if you are moving it only by 4 pixels each time the TDebugState.Update fires.

Darkhog
08-08-2013, 09:53 AM
You should either check for collision right after moving in every single direction, or check for collision once and then retract in all directions.

Tried that, now it is always stuck. My code looks like this now, will check that in so you can check if you can help:

if al_key[Options.binding_up]<>0 then begin MarioGO.y:=MarioGO.y-4;
if MarioGO.isColliding(OtherMarioGO) then MarioGO.y:=MarioGO.y+4;
end;
if al_key[Options.binding_down]<>0 then begin
MarioGO.y:=MarioGO.y+4;
if MarioGO.isColliding(OtherMarioGO) then MarioGO.y:=MarioGO.y-4;
end;
if al_key[Options.binding_left]<>0 then begin
MarioGO.x:=MarioGO.x-4;
if MarioGO.isColliding(OtherMarioGO) then MarioGO.x:=MarioGO.x+4;
end;
if al_key[Options.binding_right]<>0 then begin
MarioGO.x:=MarioGO.x+4;
if MarioGO.isColliding(OtherMarioGO) then MarioGO.x:=MarioGO.x-4;
end;

User137
08-08-2013, 02:40 PM
I did some debugging with this kind of code:

//oldX:=MarioGO.x;
oldY:=MarioGO.y;
oldX:=10; // TEST

//movement
if al_key[Options.binding_up]<>0 then begin
MarioGO.y:=MarioGO.y-4;
end;
if al_key[Options.binding_down]<>0 then begin
MarioGO.y:=MarioGO.y+4;
end;
if al_key[Options.binding_left]<>0 then begin
MarioGO.x:=MarioGO.x-4;
end;
if al_key[Options.binding_right]<>0 then begin
MarioGO.x:=MarioGO.x+4;
end;
if MarioGO.isColliding(OtherMarioGO) then begin
MarioGO.x:=oldX;
MarioGO.y:=oldY;
end;
End effect is that player is no longer stuck but warps to left side, and i can clearly see that the pixel collision, if that is the intention, is not accurate. Character moves well inside the other until collision triggers. Also debugger says that MarioGO is nil for some reason. Clearly it is not nil because this code doesn't stop the procedure

if MarioGO=nil then exit;

Darkhog
08-08-2013, 10:48 PM
It may be bug in debugger - it may think it is nil, but since MarioGO is instantiated in another method (constructor)...

Hm... but I don't know why it might make it few pixels inside, unless it is related to my recent fix for crash bug (see alletest.lpr)... I'm kinda confused.

SilverWarior
09-08-2013, 06:18 AM
Also debugger says that MarioGO is nil for some reason. Clearly it is not nil because this code doesn't stop the procedure

For some reason the Lazarus has trouble debuging SuperHeliLand. I don't know why since I don't have much expirience with Lazarus.
Yesterday when I played a bit with project options I managed to athleast get insifght into Mario.X variable. But don't ask me how as I have no idea. Maybe this might help those of you who has more expirience with Lauzarus.

Darkhog
09-08-2013, 07:24 PM
Yeah, it might be that it has problems with projects that refer to C code, like Allegro? Or project that contains allegro.pas. Anyone tried to test that?

WILL
10-08-2013, 10:46 AM
Try setting a debugger breakpoint before where it crashes on you when your game gets to that point it'll stop and allow you to use the Evaluate & Modify tool. Go to Run -> Evaluate / Modify... and the tool will come up. In the Expression textbox you will want to put the name of your declared object in here.

It should either tell you it's null for sure or give you a list of all it's contents. If it is null then you may be referencing it improperly or freeing unknowingly.

What version of Lazarus are you using and on what OS? (I'm guessing Windows most likely?)

SilverWarior
10-08-2013, 06:07 PM
@Will
I folowed your advice but I had no much sucsess in debugging Drkhog's code.
When I use Evalueate tool it usually shows that object is "nil" which is verry strange as the object gets destroyed only on one place and that code isn't called.
Other times the Evaluate tool shows that memory at adress "x" cant be acsessed.
But based on the fact that the character is moving without the problem even when Evaluate tool shows that MarioGO is either "nil" or that its memory can't be read it clearly shows that something is wrong with debugging.

I'm using Lazarus 1-0.10 with FPC 2.6.2.


BTW: Does Lazarus have auto-evaluate functionality like Delphi has?

WILL
11-08-2013, 06:41 AM
When I use Evalueate tool it usually shows that object is "nil" which is verry strange as the object gets destroyed only on one place and that code isn't called.
Other times the Evaluate tool shows that memory at adress "x" cant be acsessed.

Could also be that it's not being created properly. If we cancel out the debugger issue.


I'm using Lazarus 1-0.10 with FPC 2.6.2.

BTW: Does Lazarus have auto-evaluate functionality like Delphi has?

I've not done a lot in Lazarus lately and I think I only just got into Lazarus 1.x just after it hit the new major version number so I couldn't tell much about it's stability unfortunately. Though I have had problems with the GBD debugger on Mac using Lazarus in the past while it was in 0.9x.

You mean hovering your mouse over the code to see the values as you step through each line of your code? Yes, but if that's not what you mean, I don't know.

Guess I'm not much help here.

User137
11-08-2013, 08:41 AM
You mean hovering your mouse over the code to see the values as you step through each line of your code? Yes, but if that's not what you mean, I don't know.
Lazarus can't always evaluate class variables, but shouldn't have issues with unit variables and constants, or those that are declared inside procedures. Sometimes i declare such variable just to copy the value from class var into unit var, to be able to see its contents.
(Lazarus uses GDB, which is not perfectly compatible with FPC or Lazarus. In that sense Delphi's debugger might be way ahead.)

And sorry about derailing the thread, i only mentioned the nil value quickly, and even told you that i made sure that it's not actually nil. I did also try compile and run the actual project, and couldn't find reason for weird collisions yet.

Darkhog
13-08-2013, 10:50 PM
SilverWarrior, I'm using Laz 1.0 with FPC 2.6.0. Maybe that's the problem? Dunno.

@User137, @Will - it's not much of a crash now, as I've eliminated source of it (I call State.Update differently now and threads don't get in the way). It's more collision either being stuck (app doesn't freeze as when I press ESC in Debug State game is returning to main menu) or gets epilepsy.

I have strong feeling that it may have something to do with how I now update states, but can't pinpoint exact source of a problem (calling too often?). Last night (12/13 august) I've spend debugging issue. Nothing came out of it.

WILL
14-08-2013, 05:01 AM
I'm afraid I'm not very knowledgeable with threading so my advice stops there. :)

That would make a great PGD tutorial btw! (How To Use Multithreading In Your Games 101)

Darkhog
20-08-2013, 04:04 PM
In timer thread only variable is increased, which serves as queue. Actual update now takes place in main loop, but I can't find out why it does bad things to collision (not as bad as previous code which cased crashing, mid you).

SilverWarior
20-08-2013, 08:38 PM
When I tried to port your game to Delphi the other day (which I failed due to allegro.pas not being compatible with Delphi) I noticed that Delphi warned me about overloading several of your functions.
In Delphi if you have more than one function with the same name you need to mark all of them with "overload" command. I belive FPC should do this automatically. But I remember reading once somewhere that there was some problems with automatic overloading of functions in FPC.

Another thing that puzles me greatly is the way how you are handling colision detection. I simply don't get it how that could even work and not end up in infinite cycle. Of course since I can't debug your game properly I can't step through your colision detection system to learn how it works properly. Well I could step trough it but since I can't see what information is stored in certain variables it isn't helpfull.

If you manage to convince Nuno Martines zo make allegro.pas Delphi compatible I would be able to help you more.


Anywhay until 3rd PGD competition is over don't expect much help since many mebers are participating and therefore working on their own projects now.