how to check for intersection
4 replies



04.01.15 11:12:15 pm
Example:
I have two points:
one set at (1,5) and another at (10,13)
How can i detect if a tile is between them.
Here is a photo explaining exactly what i want

I want this red tile to fail the check, but the blue tile returns true.
I have two points:
one set at (1,5) and another at (10,13)
How can i detect if a tile is between them.
Here is a photo explaining exactly what i want

I want this red tile to fail the check, but the blue tile returns true.
Well, isn't it the case that you find angle your line is drawn with and then loop every spot of your line to check if there's anything in intersection. I say one pixel cause it's the most reliable way, you could do it every say 3-4 pixels to make it less laggy. Another way would be to take the CORNERS of your tile and check if some are below your line and some are above (or on the left or right). As far as I know, if you're using just a few tiles, the second method is better for me.
I'm assuming you don't care about pixel-perfect detection and you just want a straight line from the center of square A to the center of B.
I have done a similar algorithm for other purposes in Java but not in Lua, so this one isn't tested.
Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
local dx = B.x - A.x
local dy = B.y - A.y
-- we will use the following function for the line:
-- C(t) = (A.x + t*dx, A.y + t*dy) with 0<=t<=1
-- ofc, t can take an infinite number of values
-- and we can't evaluate them all
-- hopefully, this is enough, and maybe not too much
local maxd = math.abs(dx)+math.abs(dy)
-- we divide t in maxd pieces
for t = 0, maxd do
local tx = math.floor(A.x + t/maxd * dx)
local ty = math.floor(A.y + t/maxd * dy)
if tile(tx,ty) meets condition then
-- do sth
end
end
local dy = B.y - A.y
-- we will use the following function for the line:
-- C(t) = (A.x + t*dx, A.y + t*dy) with 0<=t<=1
-- ofc, t can take an infinite number of values
-- and we can't evaluate them all
-- hopefully, this is enough, and maybe not too much
local maxd = math.abs(dx)+math.abs(dy)
-- we divide t in maxd pieces
for t = 0, maxd do
local tx = math.floor(A.x + t/maxd * dx)
local ty = math.floor(A.y + t/maxd * dy)
if tile(tx,ty) meets condition then
-- do sth
end
end
I have done a similar algorithm for other purposes in Java but not in Lua, so this one isn't tested.
edited 5×, last 05.01.15 11:26:27 am
Here's a Lua implementation of the Bresenham algorithm which is probably what you're looking for:
https://github.com/kikito/bresenham.lua
It has a callback function which is called for each pixel (in case of CS2D you can simply handle tiles as if they were pixels) so you can do individual checks for each tile.
https://github.com/kikito/bresenham.lua
It has a callback function which is called for each pixel (in case of CS2D you can simply handle tiles as if they were pixels) so you can do individual checks for each tile.
@
DC:
Thank you, this package is very neat and useful.
@
Flacko: Thanks for helping me too...
I know it is giant and stupid, but it works for me...

Thank you, this package is very neat and useful.
@

I know it is giant and stupid, but it works for me...
Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
function stab_p(uid)
local x,y,rot = player(uid,"x"),player(uid,"y"),player(uid,"rot")
local new_rot=rot
if new_rot<-90 then new_rot=new_rot+360 end
local angle=math.rad(math.abs(new_rot +90))-math.pi
local x1=x+math.cos(angle)*52
local y1=y+math.sin(angle)*52
local x2=x+math.cos(angle)*106
local y2=y+math.sin(angle)*106
local player_targeted={}
local tx,ty,dx,dy=pixel_totile(x),pixel_totile(y),pixel_totile(x2),pixel_totile(y2)
local tile_check = bresenham.los(tx,ty,dx,dy,function(x,y)
--effect("flare",tile_topixel(x),tile_topixel(y),20,20,0,0,0)
if not tile(x,y,"walkable") then
return false
end
for index,tid in ipairs(player(0,"table")) do
if player(tid,"tilex")==x and player(tid,"tiley")==y and tid~=uid then
table.insert(player_targeted,tid)
end
end
--[[
local ti=image("gfx/block.png",0,0,1)
imagepos(ti,tile_topixel(x),tile_topixel(y),0)
timerex(1000,freeimage,1,ti)
--]]
return true
end)
if not tile_check then return false end
---------------------------------------------------------
local sword=image("gfx/classmod/adaga.png",0,0,1)
imagepos(sword,x1,y1,rot)
setpos(uid,x2,y2)
--parse('setpos '..uid..' '..x2..' '..y2)
tween_alpha(sword,1000,0)
timerex(1000,freeimage,1,sword)
for index,tid in ipairs(player_targeted) do
bleed_p(tid,30)
class.bleeding[tid][1]=5
class.bleeding[tid][2]=uid
class.refresh_status(tid)
end
--]]
class.cooldown[uid]=os.time()+3
end
local x,y,rot = player(uid,"x"),player(uid,"y"),player(uid,"rot")
local new_rot=rot
if new_rot<-90 then new_rot=new_rot+360 end
local angle=math.rad(math.abs(new_rot +90))-math.pi
local x1=x+math.cos(angle)*52
local y1=y+math.sin(angle)*52
local x2=x+math.cos(angle)*106
local y2=y+math.sin(angle)*106
local player_targeted={}
local tx,ty,dx,dy=pixel_totile(x),pixel_totile(y),pixel_totile(x2),pixel_totile(y2)
local tile_check = bresenham.los(tx,ty,dx,dy,function(x,y)
--effect("flare",tile_topixel(x),tile_topixel(y),20,20,0,0,0)
if not tile(x,y,"walkable") then
return false
end
for index,tid in ipairs(player(0,"table")) do
if player(tid,"tilex")==x and player(tid,"tiley")==y and tid~=uid then
table.insert(player_targeted,tid)
end
end
--[[
local ti=image("gfx/block.png",0,0,1)
imagepos(ti,tile_topixel(x),tile_topixel(y),0)
timerex(1000,freeimage,1,ti)
--]]
return true
end)
if not tile_check then return false end
---------------------------------------------------------
local sword=image("gfx/classmod/adaga.png",0,0,1)
imagepos(sword,x1,y1,rot)
setpos(uid,x2,y2)
--parse('setpos '..uid..' '..x2..' '..y2)
tween_alpha(sword,1000,0)
timerex(1000,freeimage,1,sword)
for index,tid in ipairs(player_targeted) do
bleed_p(tid,30)
class.bleeding[tid][1]=5
class.bleeding[tid][2]=uid
class.refresh_status(tid)
end
--]]
class.cooldown[uid]=os.time()+3
end



