How do I make the 8-Direction behavior slide against walls ?

  • How do I make the 8-Direction behavior slide against walls ?

    I've found R0J0hound 's example (event_motion2.capx), and works great for what I need (slide on 45° objects), but I would like to keep the 8-Direction behavior for the acceleration and deceleration.

    How can I implement the following mechanics in the game:

    I've tried different ways with collision points but no success so far ... Can someone help me ?

  • You can use the 8direction behavior to move the object but you can't use the solid behavior for the walls because the behavior will just stop when hitting a solid.

    At this point we can detect collisions with the overlap condition. The part we want now is some kind of collision response to keep the object out of the walls and do other stuff like sliding.

    The simplest collision response would be to save the object's position before moving and the if it overlaps a wall after moving then undo the move by moving back to the saved position. The drawback is this won't do any sliding and if moving fast the object will stop short of the wall.

    Another method is to move the object a pixel or so at a time until it's not overlapping. All that's needed is a direction. If we use the opposite direction of the motion we'll get the object to stop at the edge of the wall, but not slide. If we instead find the closest direction to move out we can get sliding. We just need a good way to find the closest direction.

    One idea to find the closest direction would be to save the object's position then try moving out in each of the four directions of the wall, and measure the distance moved for each. The closest direction would be the one with the shortest distance. You'll want to do this for each wall. With this you'll get wall sliding but you can get some jumping when hitting a corner which may be kind of like your third picture but not quite.

    One thing to consider is so far all that's being done is correcting the position of the object, but we will also need to correct the velocity of the object. Sliding would basically be setting the velocity perpendicular to the side of wall (or normal) to zero. The normal is also the same as the closest direction that the object moved out.

    Setting the velocity along a direction to zero can be done with some math.

    Var vx= object.velocityX

    Var vy= object.velocityY

    Var dot= vx*cos(dir)+vy*sin(dir)

    Set velocity to (vx-dot*cos(dir), vy-dot*sin(dir))

    Dot is the velocity along a direction and we're subtracting it from the velocity.

    You can avoid the position jumping by not moving out in the closest direction. Instead move out in the opposite direction, keeping track of how far we move out as this is the remaining distance to move. Then we need a way to find the normal of the collision. From that we can the correct the speed as with above and then try to move again with the new velocity, or basically just move in the same direction of the current edge with the remaining distance. This can be repeated as many times as nessisary but usually it's fine to do it once.

    One way to do the normal detection is to use overlaps at offset to check the positions around the object

    Var dx=0

    Var dy=0

    Overlaps at offset(1,0)

    --- add 1 to dx

    Overlaps at offset(1,1)

    --- add 1 to dx

    --- add 1 to dy

    Overlaps at offset(0,1)

    --- add 1 to dy

    Overlaps at offset(-1,1)

    --- add -1 to dx

    --- add 1 to dy

    ...etc

    Then the normal should equal angle(dx,dy,0,0)

    This requires that the object is all the way pushed out first before finding the normal.

    All this will cause a very high amount of collision checks and the object may jitter when repeatedly pushing out of walls due to pushing out a pixel at a time not being precise enough. Both can be solved by implimenting raycasting which can be used to find exact collision points and makes finding the normal simpler, that is once it's all setup which isn't really simple.

    Of course I may be overthinking a lot of this, and even after getting wall sliding working a few times I think it could be made a lot simpler. Instead of handling everything with equations to handle all cases you probably could get by by coming up with a list of cases and handling them one by one. For instance the third case in your image to move around a corner. For example:

    object is moving down

    Wall is below

    ---wall not below to the left

    ------ move object left

    ---wall not below to the right

    ------- move object right

    Just do that for all four directions. Still you'll still need some good collision response like above.

    Anyway I hope some of the above is useful in some way.

  • Here's a capx for wall sliding with the 8dir behavior.

    https://www.dropbox.com/s/0ll7vaonp0h5w ... .capx?dl=0

    All it is is a superior way to push the player out of solids than what the behavior does by default. Well, actually solid isn't used so that we can handle collision response ourselves instead of letting the behavior do it. The player is treated as a circle (which solves your third image), and the walls are all rectangles. The algorithm just calculates the closest corner or edge on each wall and moves out in the opposite direction. The velocity isn't messed with and it appears to work well enough without doing that.

    It has no dependence on the 8 behavior so it could be used in other ways. All that it needs is a player sprite and box sprites for walls with four image points at the corners.

  • R0J0hound

    Sorry for my late reply, I was busy with with my job and college.

    Thank you very much for your example and explanation, it is what I needed

  • Tokinsom megatronx and anyone else I linked here before.

    Update:

    Here's a more generic version of my above capx:

    https://www.dropbox.com/s/x68errm1tv6oh ... .capx?dl=0

    It no longer uses imagepoints, instead it calculates the corners regardless where the object's origin is. Also it's not tied to a particular sprite anymore, but you do have to duplicate an event or two to support more types (documented in capx).

  • Tokinsom megatronx and anyone else I linked here before.

    Update:

    Here's a more generic version of my above capx:

    https://dl.dropboxusercontent.com/u/542 ... _plus.capx

    It no longer uses imagepoints, instead it calculates the corners regardless where the object's origin is. Also it's not tied to a particular sprite anymore, but you do have to duplicate an event or two to support more types (documented in capx).

    Thanks, looks interesting. I needed one for isometric game with rectangular polygons, so this is how I did mine a while ago, which pushes out, but is not making a nice smooth slide yet but it needs some smoothing out on pushing out:

    https://drive.google.com/file/d/0B0jUjW ... sp=sharing

  • megatronx

    Here's the capx changed in a different way. It still uses imagepoints, but as long as there is three or more, and the points define a convex shape it will work. For isometric you could position the points in a diamond shape.

    https://www.dropbox.com/s/xvn63ri2yw9ir ... .capx?dl=0

  • megatronx

    Here's the capx changed in a different way. It still uses imagepoints, but as long as there is three or more, and the points define a convex shape it will work. For isometric you could position the points in a diamond shape.

    https://dl.dropboxusercontent.com/u/542 ... _poly.capx

    Looks cool,thought it is much more complex then mine. How would you go about using this engine with several types of collisions:

    with walls that are not being pushed out

    with enemies that are pushed out

    with other object that can be pushed out, but differently by enemies and differently by the player

    I know it's a lot, and I have done all of those, but I'm curious how this would go with your engine.

  • This new .capx is great R0J0hound Love how it finds its way around sharp corners too; that was another feature I was hoping to figure out! Thanks again

  • Thank you very much R0J0hound!

    I learn more reading your replies in the "How do I" section, than I do from reading any other source.

    It seems like every day you show us something new and magical.

    Thank you.

  • Try Construct 3

    Develop games in your browser. Powerful, performant & highly capable.

    Try Now Construct 3 users don't see these ads
  • megatronx

    Here's another iteration that adds other units (moving and not) that can push each other around. They're all circles.

    https://www.dropbox.com/s/98xzy7n9jrri6 ... .capx?dl=0

    @Tokinsom

    If you're interested the smooth motion around the corners is done by using voronoi region around the polygon. The light blue region is closest to an edge and dark blue to a corner. It then finds the distance and angle between the object and that point or edge of that region. With that it can calculate how far to move away if too close.

    https://www.dropbox.com/s/ethfdnbvqlfij ... n.png?dl=0

  • R0J0hound Thank you so much for the update! It does everything I could have hoped for darn-near flawlessly! It was pretty easy to integrate into my game, though I had to change one thing to make it properly recognize objects with a negative width or height--just set boxWidth and boxHeight to abs(wall.width) and abs(wall.height). The new example with pushing stuff around looks amazing too! I wish that is what the built-in collision engine did!

  • megatronx

    Here's another iteration that adds other units (moving and not) that can push each other around. They're all circles.

    https://dl.dropboxusercontent.com/u/542 ... units.capx

    Tokinsom

    If you're interested the smooth motion around the corners is done by using voronoi region around the polygon. The light blue region is closest to an edge and dark blue to a corner. It then finds the distance and angle between the object and that point or edge of that region. With that it can calculate how far to move away if too close.

    Thanks! Will be very helpful.

    @Tokinsom Yes, it should be included in all movement and solids behaviors.

  • R0J0hound This is a really cool example, but its unfortunately pretty heavy on the performance

    and it doesn't work with tilemaps without crerating lots of extra collision boxes.

    I was trying to achive a similar results with this raycasting plugin.

    The benefit would be that it works with tilemaps and i guess it would be faster than an event sheet only version?!?!

    Here is a capx of what i've tried so far.

    My biggest problem is that i dont know in what direction i should shoot the ray to get the walls normal.

    another thing is that i dont know how to calculate at what speed the player would slide along the wall?

    It would be awesome if you could take a look at the .capx and give me a hint in the right direction.

  • I found the angle here based on the closest edge or point on the collision polygon, but then if you have that then shooting a ray is excessive. In short even though I thought it over casting rays isn't useful to solve the problem. The most I can think of is to shoot a bunch of rays out and picking the closest one, but that is imperfect.

    The sliding is done by correcting the overlap oppiset the angle chosen and the canceling the velocity going in the direction of the angle. That can be done by utilizing a dot product.

    The algorithm I used can be made faster by not checking far away objects and/or implementing it in JavaScript. A plugin may be ideal but to me that's a pain to make and maintain.

Jump to:
Active Users
There are 1 visitors browsing this topic (0 users and 1 guests)