GMLscripts.com

Discuss and collaborate on GML scripts
Invert

You are not logged in.

#1 2020-09-20 10:46:19

redeyesmaster
Member
Registered: 2020-08-09
Posts: 43

Precise Tile Collision

Expand///@description tile_meeting_precise(x,y,layer)
///@param x
///@param y
///@param layer
/*
  Returns true or false
  
  place_meeting() for use with tiles.
  [Requires] obj_precise_tile_checker
  more information can be found here:
  https://www.yoyogames.com/blog/577/precise-tile-collisions-by-pixelated-pope

  make a sprite sheet with the exact same tiles. and for gms 1.4.9999 you may
  wish to expand the mask 1 in every direction (assists with sub pixel movement)
  
  Ported by Red#9475
*/
/// GMLscripts.com/license
var _layer = argument2;

_checker = obj_precise_tile_checker;
if(!instance_exists(_checker)) instance_create(0,0,_checker); 

var _x1 = bbox_left + (argument0 - x),
    _y1 = bbox_top + (argument1 - y),
    _x2 = bbox_right + (argument0 - x),
    _y2 = bbox_bottom + (argument1 - y),
    
for(var _x = _x1; _x <= _x2; _x++){
  for(var _y = _y1; _y <= _y2; _y++){
    var _tile = tile_layer_find(_layer, _x, _y);
    if(_tile){
      var bg = tile_get_background(_tile),
          bg_ww = background_get_width(bg),
          ww = tile_get_width(_tile),
          hh = tile_get_height(_tile),
          ll = (tile_get_left(_tile) / ww),
          tt = (tile_get_top(_tile) / hh);
      
      var pos = ll + tt*(bg_ww div ww);
      
     _checker.x = _x - (_x mod tile_get_width(_tile));
     _checker.y = _y - (_y mod tile_get_height(_tile));
     _checker.image_index = pos;

     if(place_meeting(argument0,argument1,_checker)) return true;
    }
 }
}

return false;

Original code base:   https://www.yoyogames.com/blog/577/prec … lated-pope

I was expressly given permission by Pixelated Pope to share this port, and he will direct people to it when they need assistance for gms 1.4.999

Offline

#2 2020-09-20 10:52:11

redeyesmaster
Member
Registered: 2020-08-09
Posts: 43

Re: Precise Tile Collision

While we're at it here are a few others I made based off the same code.

Expand///@description tile_point_precise(x,y,layer)
///@param x
///@param y
///@param layer

var _layer = argument2;

_checker = obj_precise_tile_checker;
if(!instance_exists(_checker)) instance_create(0,0,_checker); 

var _x = argument0,
    _y = argument1;

var _tile = tile_layer_find(_layer, _x, _y);
if(_tile){
  var bg = tile_get_background(_tile),
      bg_ww = background_get_width(bg),
      ww = tile_get_width(_tile),
      hh = tile_get_height(_tile),
      ll = (tile_get_left(_tile) / ww),
      tt = (tile_get_top(_tile) / hh);
  
  var pos = ll + tt*(bg_ww div ww);
  
  if(pos == 0) return true;
  
 _checker.x = _x - (_x mod tile_get_width(_tile));
 _checker.y = _y - (_y mod tile_get_height(_tile));
 _checker.image_index = pos;
  
 
 if(collision_point(argument0,argument1,_checker, true, true)) return true;
}

return false;
Expand/// tile_collision_normal(x, y, radius, resolution, prec)

// x
// y
// radius
// resolution - how many pixels of the radius to draw
// prec - (false) = outerring check only; (true) = entire circle check

var cx, cy, xx, yy, radius, res, prec, radius_i, degrees, degrees_i, rads, nx, ny;

cx = argument0
cy = argument1
xx = cx
yy = cy
radius = argument2
radius_i = radius
res = argument3
prec = argument4
degrees = 0
nx = 0
ny = 0

//draw_set_color(c_dkgray)
//draw_set_alpha(0.25)
if (res > radius*2){
  res = radius*2;
  show_debug_message("Error: resolution is larger then the circle")
}

while (radius_i > 0)
{
  //pi method
  degrees_i = (res/((radius_i*2)*pi))*360
  degrees_i =  360/round(360/degrees_i)
  
  while (degrees < 360)
  {
    rads = degtorad(degrees)
    xx = cos(rads) * radius_i;
    yy = sin(rads) * radius_i ;
    
    if !tile_point_precise(cx+xx,cy+yy,TileLayerBottom,){
      nx += xx
      ny += yy
    }
    
    degrees += degrees_i
  }
  degrees = 0
  radius_i -= res
  if (!prec) radius_i = 0;
}

if (nx == 0 && ny == 0) return (-1);
return point_direction(0,0,nx,ny);

Offline

Board footer

Powered by FluxBB