Heavily commented so hopefully everyone can understand how it works.
Hold the left mouse button to draw a "mirror", or reflective surface, then release button to place it. The laser will reflect off the surface and continue on until it's strength (or depth/length) has died off.
One thing the demo does not take into consideration is a mirror's position in relation to another. Meaning that if you position mirror 1 then decide to place a 2nd mirror closer to the emitter thus cutting off mirror 1 from being hit, the 2nd mirror actually gets ignored. The laser scans for mirrors in the order that you place them, not as they appear physically on screen.
To correct this, you would need to check collision with all mirrors every time you reflect from one.
Version 1
REM ====================================
REM Project: 2D Mirror Reflection
REM Created: Saturday, January 19, 2013
REM Author: Phaelax
REM ====================================
type mirror
ax as float
ay as float
bx as float
by as float
endtype
dim mirrors() as mirror
rem Laser emitter position
emitterX = 630
emitterY = 200
rem Laser's direction (a normalized value)
emitterDx = -1
emitterDy = 0
rem Laser's depth, or strength.
rem How far the laser travels before ending
laserDepth# = 2000
sync on
DO
cls
rem controls to create/place new mirrors
if mouseclick() = 1 and mFlag = 0
mFlag = 1
tx = mousex()
ty = mousey()
endif
if mouseclick() = 0
if mFlag = 1
addMirror(tx, ty, mousex(), mousey())
endif
mFlag = 0
endif
rem draw new mirror being created
if mFlag = 1
ink rgb(255,255,255),0
mx = mousex()
my = mousey()
line tx, ty, mx, my
rem show the mirror's normal
midX = tx + (mx - tx)*0.5
midY = ty + (my - ty)*0.5
nx# = my - ty
ny# = -(mx-tx)
d# = sqrt(nx#*nx# + ny#*ny#)
nx# = nx# / d#
ny# = ny# / d#
line midX, midY, midX+nx#*20, midY+ny#*20
endif
rem fire da laser!
ink rgb(255,0,0),0
circle emitterX, emitterY, 5
rem loop through all mirror and check for collision
originX = emitterX
originY = emitterY
dx# = emitterDx
dy# = emitterDy
depth# = laserDepth#
for i = 0 to array count(mirrors())
rem Target destination of laser.
destX = originX + dx# * depth#
destY = originY + dy# * depth#
rem Do some line intersection.
n# = ((mirrors(i).bx - mirrors(i).ax) * (originY - mirrors(i).ay)) - ((mirrors(i).by - mirrors(i).ay) * (originX - mirrors(i).ax))
d# = ((mirrors(i).by - mirrors(i).ay) * (destX - originX)) - ((mirrors(i).bx - mirrors(i).ax) * (destY - originY))
t# = n# / d#
rem The same check as above, except swapping the lines to get
rem the intersection time along the mirror instead of the laser.
rem This is so we don't pick up intersections outside of the segments'
rem lengths. The base equations work on infinite lines.
n# = ((destX - originX) * (mirrors(i).ay - originY)) - ((destY - originY) * (mirrors(i).ax - originX))
d# = ((destY - originY) * (mirrors(i).bx - mirrors(i).ax)) - ((destX - originX) * (mirrors(i).by - mirrors(i).ay))
u# = n# / d#
rem Check range; laser is a line segment, not an infinite line.
if t# >= 0 and t# <= 1 and u# >= 0 and u# <= 1
rem Find point of intersection of laser and mirror.
destX = originX + (destX - originX)*t#
destY = originY + (destY - originY)*t#
rem Draw laser from current position to point of relfection.
line originX, originY, destX, destY
rem Now that we know the laser has hit the mirror,
rem calculate the reflected direction vector.
rem Mirror's normal vector (normalized)
mx = mirrors(i).by - mirrors(i).ay
my = -(mirrors(i).bx - mirrors(i).ax)
d# = sqrt(mx*mx + my*my)
nMx# = mx / d#
nMy# = my / d#
rem Laser's direction vector (normalized).
x = destX - originX
y = destY - originY
d# = sqrt(x*x + y*y)
nIx# = x / d#
nIy# = y / d#
rem Dot product of the two normals.
dot# = nMx#*nIx# + nMy#*nIy#
rem New reflected direction vector.
rem Reflection Equation: R = I - 2N*(N dot I)
rem The vector is already normalized because we
rem used normalized values in the equation.
dx# = nIx# - ((2*nMx#) * dot#)
dy# = nIy# - ((2*nMy#) * dot#)
rem Calculate remaining laser strength.
depth# = depth# - depth#*t#
rem Update origin and destination coordinates.
originX = destX
originY = destY
destX = originX + dx#*depth#
destY = originY + dy#*depth#
endif
next i
rem Finish off the laser. Project what's remaining.
destX = originX + dx#*depth#
destY = originY + dy#*depth#
line originX, originY, destX, destY
rem draw mirrors
ink rgb(160,160,160),0
for i = 0 to array count(mirrors())
line mirrors(i).ax, mirrors(i).ay, mirrors(i).bx, mirrors(i).by
next i
sync
LOOP
rem add a new mirror to the array
function addMirror(ax, ay, bx, by)
add to queue mirrors()
mirrors().ax = ax
mirrors().ay = ay
mirrors().bx = bx
mirrors().by = by
endfunction
"You're not going crazy. You're going sane in a crazy world!" ~Tick