Collisions and solid objects

Monkey Forums/Monkey Programming/Collisions and solid objects

mteo77(Posted 2013) [#1]
Hello everybody.
It's been a couple of days that i am trying to figure out the best way to tackle collisions and solid objects in a dynamic environment and i can't decide which way is better.
I will describe the scenario: object1 move in a 64 pixel step in every direction, before moving it checks if the next position is occupied by a solid object, if not occupied it then moves there and wait for the next input.
Not entirely sure i have done the move code in the right way.
x=x+speed
y=y+speed

This is always running...the only thing i am doing to tell the objects to not move is to reset the speed to 0.
So what i do is:
if object next position=solid then speed =0
The problem with this is if i stop using the step by step movement and i opt for a fluid one, every collision get messed up because the "solid prediction" code works using steps.
I would like to change it and use a rectangle to rectangle collision, the problem with this is that i don't quite understand what to do when they overlap!
If i naively do:
if b overlap c then b speed=0
The object b will never be able to get out of the overlap zone...
What i want to implement is:
if overlap speed=0
check where object was coming from and set it's coords to the previous one before the overlap
check for input, if input will put you in overlap again don't move
if input will take object out of overlap then move

Is there a better way to handle this?


Paul - Taiphoz(Posted 2013) [#2]
is it a must that the player moves in 64 pixel steps ? thinking of something like snake or pacman where the steps per update would be important, if the 64 pixels are just the total speed then the best thing to do is detect a collision, and then move the player back along the vector that it was traveling on just enough so that it's 1 pixel away from a collision, then check for player input.

I would also not alter speed at all as a method to stop the player moving, instead I would only do a x=x+speed if there has been an input, but if your doing something like snake where the object is always moving then set a few variables up for each of the directions like North,south,east,west and then if the player input tells the object to go left or west then set west to true, then in your update loop where your doing x=x+speed do something like..

select true
  case North = true
    'moving north.
    y=y-speed
  case East = true
    'moving east.
    x=x+speed
  case...
  default
    'not moving do nothing.
end select


I kinda rambled there a little , hope you were able to understand what I was trying to say :)


mteo77(Posted 2013) [#3]
Hello.
Yes i was thinking at something like pacman.
Basically my game is all about blocks, everything is made in the size of 32*32 (sorry 32 not 64 like i wrote before!).
The player, objects etc are all 32*32; it's a puzzle game with fixed movements.
Example:
Object B is stationary in it's block position, i press right and it goes right in a fluid motion and it stops until it reached another block position (a 32 pixel offset), so my collisions at the moment are based on "predictions" and not actually overlaps, cause if another block is occupied by a solid it can't move at all (hope it make sense).
Everything works but my system is very "untidy" and i was wondering if there was a better way to do it, and i was curious on how other people have tackled something similar.
Lets say for example that i would scrap the idea of steps altogether and opt for a fluid motion, how would i tackle the collision/stop_if direction_is_same kind of logic?
Cause if i check for collisions, it actually have to happen before i can do something with it, so i am not entirely sure on how i can tell my logic to stop when it start to overlap and to reset it's position to not overlap, then wait for movements.
Hope my rambling make sense!
I do agree my method using offsets and speeds etc is a tad overkill...


Midimaster(Posted 2013) [#4]
to test a collision you would never move the object first, then test if this is possibe:
wrong:
X=X+ XSpeed
If IsThereACollision(X,Y)=True then
     XSpeed=0
Endif


better test the "future":
If IsThereACollision(X+1,0)=False then
     X= X+1
Endif

So the figure will never move if the future position is occupied.


To check a rectangular collision you would check image corners of the current object with all others objects:
' test moving to east:
If Collision (Player, XSpeed, 0)
    Player.X= Player.X+ XSpeed
Endif


Function Collision%(Me:Figure, Xadd%, Yadd%)
   Local x%= Me.X+Xadd
   Local y%= Me.Y+Yadd

   For local loc:Figure = Eachin FigureList
      If  x>loc.X +loc.Picture.Width() Continue
      If  y>loc.Y +loc.Picture.Height() Continue

      If  x+Me.Picture.Width()<loc.X  Continue
      If  y+Me.Picture.Height()<loc.Y  Continue

      Return TRUE
   Next
   Return False
End

Class Figure
    Field X%, Y%, Picture:Image
End



Midimaster(Posted 2013) [#5]
A third possibility is to "reserve" the future field, if you want to keep working with "grids".

Player is on field "2", a other figure Enemy is on field "4". And field "3" is still free:

1 2 3 4 5
. M . E .

It is your turn. You want to move eastward and check field 3. It is free and you "reserve" it:

1 2 3 4 5
. M R E .

Now you can move 1 pixel ahead and ater also all other all 31 pixels

Now the enemy tries to go westward and checks field 3. But it already "occupied" by a reserving flag "R". So he is not aloowed to move any more.


mteo77(Posted 2013) [#6]
Hello.
Testing for future collisions is what i am doing at the moment.
It is working fine with my step movement code, it doesn't seem to work when i have a fluid motion movement...maybe because i make the prediction to far away instead of maybe checking few pixels before it happens (at the moment it still uses the 32 pixel prediction..that's probably why it isn't working, because something make the collision "skip" somehow).
I was also thinking about a grid system as you described, and have reserved spaces and positions (i will probably have to put everything into an array and check it when there's a change).


Midimaster(Posted 2013) [#7]
If you want to have only position on exact x*32 positions you should use a grid representing the "fields". In such a playground you can also do a smooth pixel movement, but you should use the "reservated" flag for fields, which are target of a "occupation process" by a figure during the next 31 pixel steps.

If you want to have fine positioning you should give up the 32er grid and allow fine movement of all actors.

In my game "Guitar vs Football"...

http://www.midimaster.de/download/GitarreVsFussball.exe

... I did something similar: It looks like a grid, but I allowed fine pixel positions and controlled the "collisions" by simply calculating the distance of two objects.

diffX=PosAx-PosBx
diffY=PosAy-PosBy
If (diffX²+diffY²)<(HalfSizeA+HalfSizeB)²

HalfSize was the rounded half pixel size of the figure. So I got a very realistic collision check, also when both figures did not have the same size. (like "Player" and "Ball"). This proved to be realistic enough.


Gerry Quinn(Posted 2013) [#8]
Indeed, reserving the future position is probably the way to go.

An object moving between two squares can be considered to occupy both of them from the start of its move. That way another object trying to move onto the same square won't be allowed, as it is told that the square is occupied. (Unless it is a monster that is able to eat the first - Pacman monsters can move onto Pacman.)

You might be more flexible about allowing objects to move onto the square you are leaving, to encourage fluid movement. Perhaps you would consider that square empty before the move is complete.


mteo77(Posted 2013) [#9]
I would like to have a free movement system but i think the complexity is too much for me at the moment.
What i am trying to do is:
actor 1 can move in all 4 directions
if one of the directions is occupied by a block it can push it in the same direction is facing
if one of the direction is occupied by a solid it can't move there

That's why i am sticking with a step by step system, so if actor 1 push a block that block will always be in the right place since it can move only by steps (hope it make sense).

its a sort of puzzle like tetris but you have to push blocks yourself instead of just moving them when they fall down.


therevills(Posted 2013) [#10]
For fast moving objects I prefer raycasting collisions.


Midimaster(Posted 2013) [#11]
smooth grid movement:




mteo77(Posted 2013) [#12]
Thanks Midimaster!
My system works(i spent few hours yesterday implementing smooth movements in a "step" way) but i haven't thought of using mod... thats probably why sometimes my movements get funny, cause i never check if they are in the right coordinate (mod).
In fact i got every single strange effect, like when colliding in a position they don't like they just froze, or jump at me, or jump away!
Was kinda funny to see how they behaved in a way that i haven't even thought hehe
When i will be back home i will try to implement a better system with the example you gave me.
Thank you!