Log In  


hey guys, can you please explain the hit function in my code. I used a tutorial for it but i want to understand it.

x = 63
y = 35
dx = 0
dy = 0
grid_x = 0
grid_y = 0
map_tile = 0
flag_tile = 0
function _update()
dx = 0
dy = 0
grid_x = flr(x/8)
grid_y = flr(y/8)
flag_tile = fget(mget(grid_x,grid_y))
if btn(⬅️) then dx = -1 end
if btn(➡️) then dx = 1 end
if btn(⬆️) then dy = -1 end
if btn(⬇️) then dy = 1 end
if hit(x+dx,y,7,7) then
dx = 0
end
if hit(x,y+dy,7,7) then
dy = 0
end
x += dx
y += dy
end
function _draw()
cls()
map(0,0,0,0,16,16)
spr(2,x,y)
end
function hit(x,y,w,h)
collide = false
for i=x,x+w,w do
if fget(mget(i/8,y/8))>0 or
fget(mget(i/8,(y+h)/8))>0 then
collide = true
end
end
return collide
end



1

It's an interesting implementation, hit() takes a rectangle at upper left corner x,y with width w and height h, it loops through each x-coord from x to x+w and checks if the pixel at that x coord and the y coord (top) of the rectangle, or the pixel at that x coord and the y coord +h (which is actually one pixel below the bottom edge of the rect and thus likely why 7 is being passed in instead of 8) hits a tile with any flags set (not just a specific flag but any).

So, it's really only checking the top and bottom edges, and each and every pixel of those edges. Which will work as long as the rect is no taller than a map tile (8px) since the vertical edges aren't checked, but it's excessive for the horizontal edges as only 1 check is needed per 8px as well. It would be more efficient (for rects of 8px or less in width and height) to check the four corners only.

Also, bear in mind that as x+dx and y+dy are passed into the function, this will stop an object from completing a move into a solid tile but may do so at a few pixels away if the object is moving faster than 1px per frame on a given axis.


Hi @kozm0naut, I checked the code to see if I could understand it and help as well. Like you said, the collision function checks for any tile flag, even if the flag is set to 0. This is interesting because the code seems to check for a flag value greater than 0. Do you happen to know if this is just a quirk of Pico or Lua?

	for i=x,x+w,w do 
		if fget(mget(i/8,y/8))>0 or
		fget(mget(i/8,(y+h)/8))>0 then
		collide = true
		end
	end

1

Hi @8bit_gnosis, this is actually because a call to fget() without the third parameter specified returns a number representing a (binary) bitfield of all the flags for that tile, e.g. 1 for flag 1, 2 for flag 2, 4 for flag 3, 8 for flag 4, and e.g. 1+2+4+8 (15) for flags 1,2,3,4 together. This might be slightly off as I think flag numbers actually start from 0 but can't check right now. So, a call to fget() without the third parameter would only be equal to 0 if none of the flags are set whatsoever.


Ahh, that makes sense. Thanks!



[Please log in to post a comment]