Trying to figure out platformer collisions

The code below is from the Platformer Basics example by Gilles. In the first part where do the - 10+100/20 come from? I believe the 100 is because of the screen height. But the rest I don't even have a guess. Similarly lower down there is hero_x = 160+left*20+30 where do those numbers come from? I tried to figure it out most of yesterday and even though I could get things to work. I couldn't figure out why they work. I will line comment below anywhere I am seeing this set of numbers. It is clear that they are all related. So if you can tell me what they are in a couple of instances I can figure out the rest. Thank you very much in advance!

physics = function()
  vy -= 0.2 // gravity

  local bottom = floor((hero_y+vy-10+100)/20) // Where do the numbers in this formula and the ones below come from?
  local left = floor((hero_x+vx-10+160)/20)
  local x = floor((hero_x+160)/20)
  local y = floor((hero_y+100)/20)

  if vy<0 and maps["map1"].get(x,bottom) then
    hero_y = -100+bottom*20+30 // Where do the numbers in this formula and the ones below come from?
    vy = 0
    landed = 1
  elsif vy>0 and maps["map1"].get(x,bottom+1) then
    vy = 0
    landed = 0
  if vx<0 and maps["map1"].get(left,y) then
    vx = 0
    hero_x = -160+left*20+30 // Where do the numbers in this formula and the ones below come from?
  elsif vx>0 and maps["map1"].get(left+1,y) then
    vx = 0
    hero_x = -160+left*20+10 // Where do the numbers in this formula and the ones below come from?
  hero_x += vx
  hero_y += vy

I believe I have found an answer. The above code is similar to some code by MrLman:

// discover the name of the sprite portion at an (x, y) position in the world
// NOTE: the draw width/height is not the width of the map, but how width/high
// you draw it in the game
checkCollision = function(x, y, map_name, map_draw_width, map_draw_height)
  local grid_x = floor((x + map_draw_width / 2) / (map_draw_width / maps[map_name].width))
  local grid_y = floor((y + map_draw_height / 2) / (map_draw_height / maps[map_name].height))
  return maps[map_name].get(grid_x, grid_y)

Since this was a function there were names instead of numbers. I can now move forward. In case some one looks at this later for a solution the tricky bit with the above code is that the map_draw_width and map_draw_height will be equal to the number of tiles you have multiplied by the tile size for each direction. For instance a map that is 10x10 tiles with tiles that are 16x16 would have a map_draw_width and map_draw_height of 160x160. Cheers and thanks!

Actually, not necessarily. This code will still calculate collisions correctly with any draw dimensions. I'll break it down into steps:

checkCollision = function(x, y, map_name, map_draw_width, map_draw_height)
  // what we want to do is convert a screen position to a map position. The map's positions are centred at the bottom left
  // while the drawn map on screen is centred. This means we need to convert a position
  // in the map  to a value that is between 0->map_draw_width instead of -map_draw_width/2 to map_draw_width/2, like so:
  translated_x = x + map_draw_width / 2
  translated_y = y + map_draw_height / 2
  // then we need to convert it to map coordinates, which is between 0->the dimensions of the map in tiles
  // to do this, we first convert our value between 0->map_draw_width to a 0->1 value, like so
  small_x = translated_x / map_draw_width
  small_y = translated_y / map_draw_height
  // then, we convert it from a float value between 0->1 to an integer value between 0->dimensions of the map in tiles
  // We can do this like so:
  grid_x = small_x * maps[map_name].width // <- width of map in cells
  grid_y = small_y * maps[map_name].height // <- height of map in cells
  grid_x = floor(grid_x) // <- convert float to integer value
  grid_y = floor(grid_y)
  return maps[map_name].get(grid_x, grid_y)

Condensed, that gives the above function from MrLman's library. The map's draw dimensions are thoroughly taken into account so that it will calculate collision correctly with any given draw dimension.

Hopefully this helps :)

Post a reply



Validate your e-mail address to participate in the community