you can do this also with a line-line intersect/reflect function.
here is some code i had made.
it used a list of walls.
not agk basic
'Reflection / 2D Raytracing
'M.Rauch 15.08.2013
'(Monkey Pro 73b)
Strict
Import mojo
Class Vector
Field x:Float
Field y:Float
Field z:Float
Function Create:Vector(x:Float,y:Float,z:Float)
Local v:Vector=New Vector
v.x=x
v.y=y
v.z=z
Return v
End
Method Length:Float()
Return Sqrt(x*x + y*y + z*z)
End
Method Length1:Vector()
Local v:Vector = Vector.Create(x,y,z)
Local l:Float=v.Length()
If l>0
v.x=v.x / l
v.y=v.y / l
v.z=v.z / l
Endif
Return v
End
Function Sub:Vector(a:Vector , b:Vector)
'Delta
Local v:Vector=New Vector
v.x = a.x - b.x
v.y = a.y - b.y
v.z = a.z - b.z
Return v
End
Method Sub:Vector(b:Vector)
'Delta
Local v:Vector=New Vector
v.x = x - b.x
v.y = y - b.y
v.z = z - b.z
Return v
End
Method Add:Vector(b:Vector)
'Plus
Local v:Vector=New Vector
v.x = x + b.x
v.y = y + b.y
v.z = z + b.z
Return v
End
Method Mul:Vector(b:Vector)
'*
Local v:Vector=New Vector
v.x = x * b.x
v.y = y * b.y
v.z = z * b.z
Return v
End
Function Middle:Vector(a:Vector , b:Vector)
'Mitte
Local m:Vector=New Vector
m.x = (a.x + b.x) / 2.0
m.y = (a.y + b.y) / 2.0
m.z = (a.z + b.z) / 2.0
Return m
End
Method Draw:Void()
DrawOval(x-4,y-4,8,8)
End
End
Class MyApp Extends App
Field walllist:List<Line> = New List<Line>
Field once:Bool=true
Method OnCreate:Int()
Print "Device Screen Size "+DeviceWidth() + " x " + DeviceHeight()
'wenn das bei HTML5 fehlt kein Bild nur weiß
SetUpdateRate 30 'Render & Update identisch
MakeWalls()
Return 1
End
Method MakeWalls:void()
Local wall:Line
wall=New Line
wall.a=Vector.Create(10,DeviceHeight()-10,0)
wall.b=Vector.Create(10,10,0)
walllist.AddLast(wall)
wall=New Line
wall.a=Vector.Create(10,10,0)
wall.b=Vector.Create(DeviceWidth()-10,10,0)
walllist.AddLast(wall)
wall=New Line
wall.a=Vector.Create(DeviceWidth()-10,10,0)
wall.b=Vector.Create(DeviceWidth()-10,DeviceHeight()-10,0)
walllist.AddLast(wall)
wall=New Line
wall.a=Vector.Create(DeviceWidth()-10,DeviceHeight()-10,0)
wall.b=Vector.Create(10,DeviceHeight()-10,0)
walllist.AddLast(wall)
const s:Float=10.0
For Local w:Float=0 To 360.0-s Step s
Local p1:Vector=Vector.Create(100.0+Sin(w )*40,100.0+Cos(w )*40,0)
Local p2:Vector=Vector.Create(100.0+Sin(w+s)*40,100.0+Cos(w+s)*40,0)
wall=Line.Create(p1,p2)
walllist.AddLast(wall)
Next
For Local w:Float=0 To 360.0-s Step s
Local p1:Vector=Vector.Create(100.0+Sin(w )*40,300.0+Cos(w )*40,0)
Local p2:Vector=Vector.Create(100.0+Sin(w+s)*40,300.0+Cos(w+s)*40,0)
wall=Line.Create(p1,p2)
walllist.AddLast(wall)
Next
End
Method RenderWalls:void()
'-------------------- paint walls
SetColor 128,128,128
For Local wall:Line=Eachin walllist
wall.DrawNormal(5.0)
Next
SetColor 255,255,255
For Local wall:Line=Eachin walllist
wall.Draw()
Next
End
Method OnUpdate:Int()
Return 1
End
Method OnRender:Int()
PushMatrix
If once
'once=False
Cls 0,0,0
RenderWalls()
Endif
'-------------------- start ray
Local ray:Line=New Line
ray.a=Vector.Create(DeviceWidth()/2,DeviceHeight()/2,0)
ray.b=Vector.Create(TouchX(),TouchY(),0).Sub(ray.a).Length1().Mul(Vector.Create(1000.0,1000.0,1000.0)).Add(ray.a)
'-------------------- ray trace / Raytracing
Ray.Trace(ray,walllist,10) 'with trace depth limit
PopMatrix
Return 1
End
End
Class Ray
Function Trace:Void(ray:Line,lines:List<Line>,depth:int)
depth=depth-1
If depth=0 Then Return
Local l:Float=1000000.0
Local newray:Line=null
For Local wall:Line=Eachin lines
Local hit:Vector = LineLine.Intersection(ray,wall)
If hit
'SetColor 255,0,0
'hit.Draw()
'surface Normal
Local n:Vector=wall.Normal()
'Direction
Local dir:Vector=ray.Direction()
'Reflect Direction
Local o:Vector=New Vector
Local op:Float =2.0 * (dir.x*n.x + dir.y*n.y + dir.z*n.z)
o.x=dir.x - (op * n.x)
o.y=dir.y - (op * n.y)
o.z=dir.z - (op * n.z)
If hit.Sub(ray.a).Length() <l Then 'find the nearest
l=hit.Sub(ray.a).Length()
ray.b=hit 'shorten the ray
'Reflected Line
'Start from End To New Point
newray=New Line
newray.a=Vector.Create(hit.x+n.x*0.5,hit.y+n.y*0.5,hit.z+n.z*0.5) 'else we hit direct the same wall, we start a little bit up ( sonst trift man die gleiche Mauer wieder)
newray.b=Vector.Create(hit.x+o.x*10000.0,hit.y+o.y*10000.0,hit.z+o.z*10000.0) 'länge 10000 weiter
Endif
Endif
Next
SetColor 255,255,0
ray.Draw()
'do the same again
If newray<>Null
newray.a.Draw()
Ray.Trace(newray,lines,depth)
Endif
End
End
Class Line
Field a:Vector
Field b:Vector
Function Create:Line(a:Vector,b:Vector)
Local l:Line= New Line
l.a=a
l.b=b
Return l
end
Method Draw:Void()
DrawLine(a.x , a.y , b.x , b.y )
End
Method DrawNormal:Void(l:Float)
Local m:Vector=Vector.Middle(a,b)
Local n:Vector=Normal()
DrawLine(m.x , m.y , m.x + n.x*l , m.y + n.y*l )
End
Method Normal:Vector()
'Normale der Linie!
'define dx=x2-x1 And dy=y2-y1
'the normals are (-dy, dx) And (dy, -dx)
Local d:Vector=b.Sub(a).Length1()
Return Vector.Create(-d.y,d.x,0)
End
Method Direction:Vector()
Return b.Sub(a).Length1()
End
Method Length:Float()
'Länge Linie
Return b.Sub(a).Length()
End
End
Class LineLine
Function Intersection:Vector(line1:Line,line2:Line)
Local p:Vector=Null
Local x1:Float=line1.a.x
Local y1:Float=line1.a.y
Local x2:Float=line1.b.x
Local y2:Float=line1.b.y
Local x3:Float=line2.a.x
Local y3:Float=line2.a.y
Local x4:Float=line2.b.x
Local y4:Float=line2.b.y
Local bx:Float = x2 - x1
Local by:Float = y2 - y1
Local dx:Float = x4 - x3
Local dy:Float = y4 - y3
Local b_dot_d_perp:Float = bx * dy - by * dx
If b_dot_d_perp = 0.0 Then Return Null
Local cx:Float = x3 - x1
Local cy:Float = y3 - y1
Local t:Float = (cx * dy - cy * dx) / b_dot_d_perp
If (t < 0.0) Or (t > 1.0) Then Return Null
Local u:Float = (cx * by - cy * bx) / b_dot_d_perp
If (u < 0.0) Or (u > 1.0) Then Return Null
p=Vector.Create(x1+t*bx, y1+t*by,0)
Return p
End
End
Function Main:Int()
Local myApp:MyApp = New MyApp
Return 1
End
AGK 108 B19 : Windows 8.1 Pro 64 Bit : AMD Radeon HD 6670