Guest User

On Slopes and Grids by Ariak

a guest
Aug 6th, 2016
1,084
1
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 9.85 KB | None | 1 0
  1. On Slopes and Grids: subpixel-perfect top-down movement and collision line without objects - Game Maker Studio
  2. by Ariak
  3.  
  4. Includes:
  5. * Scripts for place_meeting and collision_point, factoring in 45° triangles using only grids
  6. * Script for collision line that is subpixel perfect - including 45° triangles and many other shapes in grids
  7. * subpixel 2D topdown movement code for moving along 45° slopes (grid based - no objects, easily adaptable though)
  8.  
  9. *NOTE* 1. cell dimensions is 32x32 px! 2. This code assumes a square player hitbox.
  10.  
  11. /// ========================================= GRID PLACE MEETING===================================================================
  12. Place Meeting: This is actually 2 scripts - it needs to know the sprite_widht,height of the calling object!
  13.  
  14. /// ========== 1: gridcol_place_meeting ===============================
  15. ///gridcol_place_meeting(xx,yy);
  16.  
  17. var xx=argument0;
  18. var yy=argument1;
  19. var col=false;
  20.  
  21. // Adjust for object dimensions => find the borders from the sprite-origin given by xx,yy
  22. var left,right,up,down;
  23. left = xx-sprite_width/2;
  24. right= xx+(sprite_width/2)-1;
  25. up = yy-sprite_height/2;
  26. down = yy+(sprite_height/2)-1;
  27.  
  28. // Check object/sprite borders
  29. col = ( gridcol_quadrant_rectangle(xx,yy,left,up) ||
  30. gridcol_quadrant_rectangle(xx,yy,right,up) ||
  31. gridcol_quadrant_rectangle(xx,yy,left,down) ||
  32. gridcol_quadrant_rectangle(xx,yy,right,down));
  33.  
  34. return col;
  35.  
  36. /// ========== 2: gridcol_quadrant_rectangle ===============================
  37. ///gridcol_quadrant_rectangle(ox,oy,xx,yy);
  38.  
  39. var ox=argument0; // origin of sprite,object
  40. var oy=argument1;
  41. var xx=argument2; // target coordinates to check as determined by gridcol_place_meeting
  42. var yy=argument3;
  43. var ax=31*(ox>xx); // Quadrant intersections along border - see the visualization for this
  44. var ay=31*(oy>yy);
  45. var tx = xx mod 32;
  46. var ty = yy mod 32;
  47. var col=false;
  48.  
  49. switch (obj_player.grid[# xx div 32, yy div 32]){
  50. case 2: col = ( (tx >= ty) || (tx >= ay) || (ax >= ty) ); break;
  51. case 3: col = ( (tx <= ty) || (tx <= ay) || (ax <= ty) ); break;
  52. case 1: col = ( (31-tx >= ty) || (31-tx >= ay) || (31-ax >= ty) ); break;
  53. case 4: col = ( (31-tx <= ty) || (31-tx <= ay) || (31-ax <= ty) ); break;
  54. case 5: col = true; break;
  55. }
  56. return col;
  57.  
  58. /// ========================================== COLLISION POINT ==================================================================
  59. ///gridcol_point(x,y)
  60.  
  61. //Determines if the given coordinates collide with a wall - much easier then the quadrant_rectangle!
  62.  
  63. var tx = argument0 mod 32;
  64. var ty = argument1 mod 32;
  65. var col=false;
  66.  
  67. switch (obj_player.grid[# argument0 div 32, argument1 div 32]){
  68. case 2: col = (tx >= ty); break;
  69. case 3: col = (tx <= ty); break;
  70. case 1: col = (31-tx >= ty); break;
  71. case 4: col = (31-tx <= ty); break;
  72. case 5: col=1; break;
  73. }
  74. return col;
  75.  
  76. /// ========================================== COLLISION LINE ==================================================================
  77. ///gridcol_line(x1,x1,x2,y2);
  78.  
  79. //=== INPUT ===
  80. var sx=argument0; var sy=argument1; var tx=argument2; var ty=argument3;
  81.  
  82. // Check Start + End Point
  83. var col=(gridcol_point(sx,sy)||gridcol_point(tx,ty)); if col return col;
  84.  
  85. // Check INTEGER X coordinates that intersect with grid, determine according y values mathmatically
  86. var deltax=abs((tx div 32) - (sx div 32));
  87. if deltax>0{
  88. var xslope=((ty-sy)/(tx-sx));
  89. var cx=(sx&~31)+31*(tx>sx);
  90. var cy=sy+xslope*(cx-sx)
  91. col = (gridcol_point(cx,cy)||gridcol_point((tx&~31)+31*(tx<sx),ty+xslope*(((tx&~31)+31*(tx<sx))-tx))); if col return col;
  92. var dirx=(tx>sx)-(tx<sx);
  93. repeat(deltax-1){
  94. col = (gridcol_point(cx+dirx,cy+xslope*dirx)||gridcol_point(cx+32*dirx,cy+xslope*32*dirx)); if col return col;
  95. cx+=32*dirx;
  96. cy+=xslope*32*dirx;
  97. }
  98. }
  99.  
  100. // Check INTEGER Y coordinates that intersect with grid, determine according x values mathematically
  101. var deltay=abs((ty div 32) - (sy div 32));
  102. if deltay>0{
  103. var yslope=((tx-sx)/(ty-sy));
  104. var cy=(sy&~31)+31*(ty>sy);
  105. var cx=sx+yslope*(cy-sy)
  106. col=(gridcol_point(cx,cy)||gridcol_point(tx+yslope*(((ty&~31)+31*(ty<sy))-ty),(ty&~31)+31*(ty<sy))); if col return col;
  107. var diry=(ty>sy)-(ty<sy);
  108. repeat(deltay-1){
  109. col = (gridcol_point(cx+yslope*diry,cy+diry)||gridcol_point(cx+yslope*32*diry,cy+32*diry)); if col return col;
  110. cy+=32*diry;
  111. cx+=yslope*32*diry;
  112. }
  113. }
  114.  
  115. return col;
  116.  
  117.  
  118. /// ========================================== 2D TOP DOWN MOVEMENT ==================================================================
  119. PLAYER CREATE EVENT:
  120.  
  121. ///Variables for Movement
  122. mspd = 3; // maximum movement speed
  123. avx = 0; // actual velocity x - is used for saving uneven number remainder!
  124. avy = 0; // actual velocity y
  125.  
  126.  
  127. PLAYER STEP EVENT:
  128. /// Movement and Collision
  129.  
  130. // Grab Keyboard Inputs
  131. var horizontal = keyboard_check(ord('D'))-keyboard_check(ord('A'));
  132. var vertical = keyboard_check(ord('S'))-keyboard_check(ord('W'));
  133.  
  134. // Technically unneccesary as mspd can simply be multiplied with the keyboard checks above! Tutorial purpose.
  135. var vx=horizontal*mspd;
  136. var vy=vertical*mspd;
  137.  
  138. // Move with Collision checks
  139. gridcol_move_speeds(vx,vy);
  140.  
  141.  
  142. /// ========================= Collision Script ===========================================
  143. Collision Movement Script for 2D topdown with subpixels, along 45° slopes based on grids.
  144.  
  145. ///gridcol_move_speeds(vx,vy)
  146.  
  147. //Input
  148. avx+=argument0;
  149. avy+=argument1;
  150. var vx=avx div 1;
  151. var vy=avy div 1;
  152. avx-=vx;
  153. avy-=vy;
  154.  
  155. // Y + X AXIS
  156. var angle=point_direction(0,0,vx,vy);
  157. var pvx=vx*abs(dcos(angle));
  158. var pvy=vy*abs(dsin(angle));
  159. if !gridcol_place_meeting(x+pvx,y+pvy) {x=round(x+pvx);y=round(y+pvy);}
  160. else{
  161.  
  162. // X AXIS
  163. if vx!=0{
  164. if vy!=0 {vy=((vy>0)-(vy<0))*abs(vx)}
  165. var sx=x;
  166. var svx=(vx>0)-(vx<0);
  167. repeat(abs(vx)){
  168. if !gridcol_place_meeting(x+svx,y) {x+=svx;}
  169. else {break;}
  170. }
  171. vx=round((vx-(x-sx))*dsin(45));
  172. if vx!=0{
  173. var ydir=(!gridcol_place_meeting(x+svx,y+1))-(!gridcol_place_meeting(x+svx,y-1));
  174. if ydir!=0{
  175. x+=svx;y+=ydir;
  176. repeat(abs(vx)-1){
  177. if (!gridcol_place_meeting(x+svx,y+ydir)) {x+=svx;y+=ydir;}
  178. else {break;}
  179. }
  180. }
  181. }
  182. }
  183.  
  184. // Y AXIS
  185. if vy!=0{
  186. var sy=y;
  187. var svy=(vy>0)-(vy<0);
  188. repeat(abs(vy)){
  189. if !gridcol_place_meeting(x,y+svy) {y+=svy;}
  190. else {break;}
  191. }
  192. vy=round((vy-(y-sy))*dsin(45));
  193. if vy!=0{
  194. var xdir=(!gridcol_place_meeting(x+1,y+svy))-(!gridcol_place_meeting(x-1,y+svy));
  195. if xdir!=0{
  196. x+=xdir;y+=svy;
  197. repeat(abs(vy)-1){
  198. if (!gridcol_place_meeting(x+xdir,y+svy))
  199. {x+=xdir;y+=svy;}
  200. else {break;}
  201. }
  202. }
  203. }
  204. }
  205.  
  206. } //END
Add Comment
Please, Sign In to add comment