- Title: Beautiful collisions in top-down games using motion_add() and arrow key movement
- Description: Using directional keys to control movement using motion_add() and friction, which adds a realistic look to top-down player movement, and collisions with rectangular walls.
- GM Version:

- Registered: no
- File Type: .gmk
- File Size: 12 kb
- File Link: http://www.mediafire...fk1joj2ii5bgze2
- Required Extensions: N/A
- Required DLLs: N/A
- Tags: wall collision motion_add motion add arrow keys direction directional w a s d top down top-down topdown friction
I have had this problem for a long time: creating movement based on motion_add() and the arrow keys (or in this case, W, A, S and D) and friction, with smooth, good-looking collisions against walls in a top-down game. Just yesterday, I found a simple solution after hours of toiling (which makes me feel silly for spending so much time). Keep in mind this has only been tested on bounding boxes of rectangles and squares. Also keep in mind the wall object/parent must be solid unless you modify the code (examples of this are below the code)
//create event of player object friction = .5 acceleration = 1 max_speed = 5
replace .5 with an amount of friction suitable to your game.
//step event of player object
motion_add(90, keyboard_check(ord('W')) * place_free(x, y - 1) * acceleration)
motion_add(270, keyboard_check(ord('S')) * place_free(x, y + 1) * acceleration)
motion_add(180, keyboard_check(ord('A')) * place_free(x - 1, y) * acceleration)
motion_add(0, keyboard_check(ord('D')) * place_free(x + 1, y) * acceleration)
//this is the same code, but drawn out in if statements
if keyboard_check(ord('W')) == 1
{
if place_free(x, y - 1)
motion_add(90, acceleration)
}
if keyboard_check(ord('S')) == 1
{
if place_free(x, y + 1)
motion_add(270, acceleration)
}
if keyboard_check(ord('A')) == 1
{
if place_free(x - 1,y)
motion_add(180, acceleration)
}
if keyboard_check(ord('D')) == 1
{
if place_free(x + 1, y)
motion_add(0, acceleration)
}
if speed > max_speed
{
speed = max_speed
}
replace ord('W') with vk_up, etc. if you want to use arrow keys.
replace the 1s in the motion_add()s and the 5s in the last line of code with other numbers to suit your game.
//player object: collision event with wall object/parent x = round(x) y = round(y) move_outside_solid(direction - 180, speed) move_contact_solid(direction, speed) speed = 0
If I take any piece of this code out, it doesn't work properly so I believe that every single character in the codes belongs there and is in its rightful place. However, I suppose you could do
move_outside_solid(direction,-speed) instead of the move_outside_solid() code I used. I think you could also use move_contact_all() and move_outside_all(), but I wouldn't, because it could cause problems. If you don't want the wall to be solid, I would set solid=1 before the collision, then solid=0 after the collision for the wall object/parent.
This code works PERFECTLY for my game (and I don't use caps lock lightly). If anyone finds a problem with this code that involves what I mentioned, please post below, as I would need to update both this post and my game's code.
The editable GM8 file goes more in-depth and provides an example of the code in action.
I hope the community will benefit from this knowledge as I have.
Edit:
Fixed code to be easier to read and it should work/look better. (I never use spaces in between math signs or commas, and never indent, and never use == signs, I just use = signs. I did that to make it more "correct" and possibly easier to read. I know these are "bad coding habits" but I've got my own method for making code easier to read.) New link should be better-commented.
Also, I had a problem with using the step event code that *doesn't* use the if statements. It can cause problems in that you'll need to add a wall object to the corner every time. This can be avoided, as far as I can tell, by using the code for the step event that is drawn out in if statements instead. It shouldn't be noticeably slower to do it this way.
It has also come to my attention that this code will cause the player to accelerate (gain speed) quicker by moving diagonally. I'll post a fix to this as soon as possible. (Thanks Mr
Thank you, icuurd12b42! I never thought this would be a staff pick. It's an honor.
Edited by eyeCube, 05 July 2012 - 09:15 PM.











