Collisions and solid objects
Monkey Forums/Monkey Programming/Collisions and solid objects
| ||
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? |
| ||
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 :) |
| ||
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... |
| ||
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 |
| ||
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. |
| ||
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). |
| ||
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. |
| ||
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. |
| ||
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. |
| ||
For fast moving objects I prefer raycasting collisions. |
| ||
smooth grid movement: |
| ||
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! |