Advertisement
Badwrong

GMS2 AABB Collision Resolution

Feb 2nd, 2022 (edited)
1,742
1
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. // ******************* CREATE *************************************** //
  2.  
  3. on_ground   = 0;
  4. facing      = 1;
  5. speed_max   = 20;
  6. speed_accel = 5;
  7.  
  8. friction = 4;
  9. gravity  = 6;
  10.  
  11. // You must set the mask_index of the object to something or use the following line:
  12. if (!mask_index) mask_index = sprite_index;
  13.  
  14.  
  15. // ******************* STEP ***************************************** //
  16.  
  17. // Counters
  18. on_ground = on_ground >> 1;
  19.  
  20. // Inputs
  21. var _x_axis = keyboard_check(ord("D")) - keyboard_check(ord("A")),
  22.     _jump   = keyboard_check_pressed(vk_space);
  23.  
  24. // Horizontal movement
  25. if (_x_axis != 0)
  26. {
  27.     facing = sign(_x_axis);
  28.     motion_add(darccos(_x_axis), speed_accel);
  29.    
  30.     // Use motion_set() and no accel value if you want instant movement
  31.     // then add and else branch with hspeed = 0;
  32. }
  33.  
  34. // Set sprite and check for jump
  35. if (on_ground)
  36. {
  37.     if (_jump)
  38.     {
  39.         on_ground = 0;
  40.         motion_add(-gravity_direction, 200);  // Or jump power variable
  41.         image_index  = 0;
  42.     }
  43.     // Here is where you set run or idle sprite (hspeed == 0 ? idle : run )
  44. }
  45. else if (!_jump) vspeed = max(vspeed, vspeed * 0.5);   
  46. /* Here you would add full else { } block of code where you set jump sprite
  47.  * This is one way to stop the jump sprite at the end
  48.  * image_index = min(image_index, image_number - 1);
  49.  */
  50.    
  51.    
  52. // Clamp speeds and set left/right facing direction
  53. image_xscale = facing;
  54. hspeed = clamp(hspeed, -speed_max, speed_max);
  55. vspeed = clamp(vspeed, -200, 200);  // Or some terminal velocity macro
  56. // Adding delta time should be done on the above few lines with hspeed and vspeed
  57. // Multiply them by the change in delta time, i.e., no difference would be 1
  58.  
  59.  
  60.  
  61. // ********** COLLISION EVENT WITH STATIC COLLISION OBJECT ********** //
  62.  
  63. /* General AABB collision algorithm: Move back and resolve collisions per axis.
  64.  *
  65.  * By placing this solution in an actual "collision event" it automatically
  66.  * provides information about each specific collision, as if instance_place_list()
  67.  * were being used.  However, as an internally triggered event the extra overhead and
  68.  * cost of manually checking is eliminated.
  69.  *
  70.  * This solution uses built-in vspeed and hspeed, along with setting the instance
  71.  * variables for gravity and friction.  Note, built-in movement occurs between step and
  72.  * end-step events.  There is no loss of control or scary "black box" to worry about when
  73.  * using such a solution.  This also means automatic acceleration and deceleration if desired.
  74.  */
  75.  
  76. // First store the vector that caused the collision
  77. var _vx = x - xprevious,
  78.     _vy = y - yprevious;
  79. x = xprevious;
  80. y = yprevious;
  81.  
  82. /*
  83.  * With static objects many of the values below can be precomputed on create and assigned to variables.
  84.  * We find exact centers based on bbox and not instance x/y, and
  85.  * collisions are then resolved through the mask offsets
  86.  *
  87.  * This solution does allow for non-centered origins, although it is recommended in most cases.
  88.  * If image_xscale is used to mirror a sprite, then the x-axis should be centered at least.
  89.  */
  90.  
  91. // Horizontal
  92. if place_meeting(x + _vx, y, other)
  93. {
  94.     // Offset by exact values from centers
  95.     if (x < other.x) x = other.bbox_left - sprite_get_width(mask_index) + sprite_get_xoffset(mask_index);
  96.     else x = other.bbox_right + sprite_get_xoffset(mask_index);
  97.    
  98.     // If you want wall jumping an on_wall variable with a sign +/- is appropriate here
  99.    
  100. } else x += _vx;
  101.  
  102. // Vertical
  103. if place_meeting(x, y + _vy, other)
  104. {
  105.     // Same as horizontal but with the y-axis
  106.     if (y < other.y)
  107.     {
  108.         y = other.bbox_top - sprite_get_height(mask_index) + sprite_get_yoffset(mask_index);
  109.         vspeed = 0;
  110.         on_ground = 10; // Or some variable or macro for "coyote frames"
  111.     }
  112.     else
  113.     {
  114.         y = other.bbox_bottom + sprite_get_yoffset(mask_index);
  115.         vspeed *= 0.9; // Don't stop instantly when hitting ceiling
  116.     }
  117.    
  118. } else y += _vy;
  119.  
  120. // And ya, that's like 90% comments and very little code.
  121.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement