its not agk but you can convert
'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
single reflection in agk
rem
rem AGK Application 2.0.21
rem MR
SetDisplayAspect( 4.0/3.0 )
type TVector
x as float
y as float
z as float
endtype
do
Print("Reflection")
//--------------------
//Norface Normal
n as TVector
n.x=-1
n.y=0
n.z=0
//n.x=0
//n.y=-1
//--------------------
//Line Start
p1 as TVector
p1.x=50
p1.y=50
p1.z=0
//Line End
p2 as TVector
p2.x=GetPointerX()
p2.y=GetPointerY()
p2.z=50
//Delta
d as TVector
d.x=p2.x-p1.x
d.y=p2.y-p1.y
d.z=p2.z-p1.z
l#=sqrt(d.x*d.x + d.y*d.y + d.z*d.z) //length
//Direction
dir as TVector
dir.x=d.x/l#
dir.y=d.y/l#
dir.z=d.z/l#
DrawLine(p1.x , p1.y , p2.x , p2.y , 255,255,0)
//Reflect Direction
o as TVector
op# =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)
//Start from End to New Point
p1.x=p2.x+o.x*100.0
p1.y=p2.y+o.y*100.0
p1.z=p2.z+o.z*100.0
//Reflected Line
DrawLine(p1.x , p1.y , p2.x , p2.y , 255,0,0)
//Normal
DrawLine(p2.x , p2.y , p2.x + n.x*10.0 , p2.y + n.y*10.0 , 192,192,192)
Sync()
loop
AGK (Steam) V2.0.21 : Windows 10 Pro 64 Bit : AMD (16.6) Radeon R7 265 : Mac mini OS Sierra (10.12)