Game development specific discussions.
Boromir
Posts: 451
Joined: Apr 30, 2015 19:28
Location: Texas,U.S., Earth,Solar System
Contact:

### Re: Isometric shadow casting light.

@dodicat
Really nice!
I'll need to learn more math to understand all of what you did. :)

@Leopardpm
I saw that the angle routine was returning values 0-90. 90*4=360. 4 was the number of bad angles. This gave me a lead on the problem.
Upon removing the abs() from x and y differences my angle calculating routine returned 0-360 degrees
Now there was a glitch on only one angle, when it went from 180 to -180

I fixed it by checking if there were both negative and positive angles on the same frame. If so then remove 360 degrees from the positive slopes.

Code: Select all

`dim as integer k,k1,k2,k3,k4if slope1>0 then k+=1:k1=1if slope2>0 then k+=1:k2=1if slope3>0 then k+=1:k3=1if slope4>0 then k+=1:k4=1if k>0 and k<4 and plight.x<(box1.p2.x+box1.p3.x)/2 then    if k1=1 then slope1-=360    if k2=1 then slope2-=360    if k3=1 then slope3-=360    if k4=1 then slope4-=360end if`

Sorry, if this is gibberish. I'm not so good at explaining myself.
Last edited by Boromir on Mar 31, 2017 23:57, edited 2 times in total.
leopardpm
Posts: 1795
Joined: Feb 28, 2009 20:58

### Re: Isometric shadow casting light.

nope - not gibberish - explained very well - thank you! I will look into your code and see how to optimize it, I REALLY like how simple it is and that our idea actually worked!
Boromir
Posts: 451
Joined: Apr 30, 2015 19:28
Location: Texas,U.S., Earth,Solar System
Contact:

### Re: Isometric shadow casting light.

I'm still having a bit of an issue with when the light gets too close to the object the shadow gets short.

Performance test:
I get about 16 fps on my 1.8 ghz Pentium M cpu(not as fast as I had hoped for)

Bigger Light Image

Code: Select all

`'2d Quad-Shadow caster'by Ezekiel Gutierrez and Leopardpm''requires light.bmpx 800x400 for the glow'const scrw=1280const scrh=1024const pi = 4 * atn(1)dim shared as double DtoR = pi / 180   ' degrees * DtoR = radianstype point2d    x as integer    y as integerend typetype box    p1 as point2d    p2 as point2d    p3 as point2d    p4 as point2d    declare sub draw(img as any ptr)end typepublic function getslope(p1 as point2d, _                  p2 as point2d,byref dist as integer) as integer        dim as integer xdif,ydif        xdif = p2.x - p1.x        ydif = p2.y - p1.y        dist=SQR(xdif*xdif + ydif*ydif)        return atan2(ydif, xdif)*(180 / pi)end functionpublic sub makepoint(angle as integer,dist as integer, _              p1 as point2d, _              byref p2 as point2d)    p2.x=p1.x-(cos(angle*DtoR)*(200))    p2.y=p1.y-(sin(angle*DtoR)*(200))end subdeclare sub shadowcast(box1 as box,plight as point2d,img as any ptr,col as integer)screenres scrw,scrh,32dim as box boxes(10)dim as point2d plightdim as integer slope1,slope2,slope3,slope4for i as integer=0 to 10boxes(i).p1.x=100+(i*80) 'boxboxes(i).p1.y=90 '    co-ordinate 1boxes(i).p2.x=80+(i*80)'boxboxes(i).p2.y=100'    co-ordinate 2boxes(i).p3.x=120+(i*80)'boxboxes(i).p3.y=100'    co-ordinate 3boxes(i).p4.x=100+(i*80)'boxboxes(i).p4.y=110'    co-ordinate 4next i'create light glow from 32 bit bitmapdim as any ptr lightlight=imagecreate(800,400)bload "light.bmpx",light'====================================color rgb(255,255,255),rgb(0,0,0)dim as any ptr imgimg=imagecreate(scrw,scrh,rgba(0,0,0,0))dim as integer fps,framesdim as double prevtimeprevtime=timerdogetmouse plight.x,plight.y'put light.x and y at mousescreenlockclsline img,(0,0)-(scrw,scrh),rgba(0,0,0,0),bf'fill image with nothingnessput img,(plight.x-400,plight.y-200),light,alpha'   put light into itfor i as integer=0 to 10shadowcast(boxes(i),plight,img,i)'cast shadownext ifor i as integer=0 to 10boxes(i).draw(img)next iput (0,0),img,alpha'draw resultprint "fps "+str(fps)screenunlocksleep 1frames+=1if timer-1>prevtime then fps=frames:frames=0:prevtime=timerloop until multikey(1)sub box.draw(img as any ptr)    'line img,(p1.x,p1.y)-(p2.x,p2.y),rgb(0,0,0)    'line img,(p2.x,p2.y)-(p4.x,p4.y),rgb(0,0,0)    'line img,(p3.x,p3.y)-(p4.x,p4.y),rgb(0,0,0)    'line img,(p3.x,p3.y)-(p1.x,p1.y),rgb(0,0,0)    line img,(p1.x,p1.y-20)-(p2.x,p2.y-20),rgb(255,0,0)    line img,(p2.x,p2.y-20)-(p2.x,p2.y),rgb(255,0,0)    line img,(p2.x,p2.y)-(p4.x,p4.y),rgb(255,0,0)    line img,(p3.x,p3.y)-(p4.x,p4.y),rgb(255,0,0)    line img,(p3.x,p3.y)-(p3.x,p3.y-20),rgb(255,0,0)    line img,(p3.x,p3.y-20)-(p1.x,p1.y-20),rgb(255,0,0)    line img,(p4.x,p4.y)-(p4.x,p4.y-20),rgb(255,0,0)    line img,(p2.x,p2.y-20)-(p4.x,p4.y-20),rgb(255,0,0)    line img,(p3.x,p3.y-20)-(p4.x,p4.y-20),rgb(255,0,0)    paint img,(p1.x+1,p1.y+3),rgb(50,0,0),rgb(255,0,0)    paint img,(p1.x-1,p1.y+3),rgb(100,0,0),rgb(255,0,0)    paint img,(p1.x,p1.y-1),rgb(255,0,0),rgb(255,0,0)end subsub shadowcast(box1 as box,plight as point2d,img as any ptr,col as integer)dim as point2d shad1,shad2dim as integer slope1,slope2,slope3,slope4dim as point2d ch1,ch2dim as integer testval=-200,dist'calculate differences for each pointwith box1slope1=getslope(.p2,plight,dist)'+180slope2=getslope(.p4,plight,dist)'+180slope3=getslope(.p1,plight,dist)'+180slope4=getslope(.p3,plight,dist)'+180dim as integer k,k1,k2,k3,k4if slope1>0 then k+=1:k1=1if slope2>0 then k+=1:k2=1if slope3>0 then k+=1:k3=1if slope4>0 then k+=1:k4=1if k>0 andalso k<4 andalso plight.x<(box1.p2.x+box1.p3.x)/2 then    if k1=1 then slope1-=360    if k2=1 then slope2-=360    if k3=1 then slope3-=360    if k4=1 then slope4-=360end if'===================================================if slope1>testval then testval=slope1:ch1.x=.p2.x:ch1.y=.p2.y      ':chx2=x:chy2=y2if slope2>testval then testval=slope2:ch1.x=.p4.x:ch1.y=.p4.y     ':chx2=x:chy2=yif slope3>testval then testval=slope3:ch1.x=.p1.x:ch1.y=.p1.y       ':chx2=x2:chy2=y2if slope4>testval then testval=slope4:ch1.x=.p3.x:ch1.y=.p3.y      ':chx2=x2:chy2=y'testval=-1if slope1<testval then testval=slope1:ch2.x=.p2.x:ch2.y=.p2.yif slope2<testval then testval=slope2:ch2.x=.p4.x:ch2.y=.p4.yif slope3<testval then testval=slope3:ch2.x=.p1.x:ch2.y=.p1.yif slope4<testval then testval=slope4:ch2.x=.p3.x:ch2.y=.p3.y'===================================================end with'use selected pointsdim as integer ss=getslope(ch1,plight,dist)'get slope difference for one edge of the shadowmakepoint(s,dist,ch1,shad1)'create first points=getslope(ch2,plight,dist)'get slope difference for the other edgemakepoint(s,dist,ch2,shad2)'create second point    dim as point2d p1=shad1,p2=ch1,p3=ch2,p4=shad2'draw shadow outlineline img,(p1.x,p1.y)-(p2.x  ,p2.y  ),rgba(col,0,0,0)line img,(p2.x  ,p2.y  )-(p3.x  ,p3.y  ),rgba(col,0,0,0)line img,(p4.x,p4.y)-(p3.x  ,p3.y  ),rgba(col,0,0,0)line img,(p1.x,p1.y)-(p4.x,p4.y),rgba(col,0,0,0)'fill shadow outlinepaint img,((p1.x+p2.x+p3.x+p4.x)/4, _           (p1.y+p2.y+p3.y+p4.y)/4),rgba(col,0,0,0),rgba(col,0,0,0)'draw boxend sub`
Last edited by Boromir on Apr 01, 2017 3:31, edited 2 times in total.
Boromir
Posts: 451
Joined: Apr 30, 2015 19:28
Location: Texas,U.S., Earth,Solar System
Contact:

### Re: Isometric shadow casting light.

Code: Select all

`public sub makepoint(angle as integer,dist as integer, _              p1 as point2d, _              byref p2 as point2d)    p2.x=p1.x-(cos(angle*DtoR)*(200))    p2.y=p1.y-(sin(angle*DtoR)*(200))end sub`

This needs to calculate a value in place of the 200 depending on the value of dist(distance between light and shadow casting box point)
leopardpm
Posts: 1795
Joined: Feb 28, 2009 20:58

### Re: Isometric shadow casting light.

Boromir wrote:

Code: Select all

`public sub makepoint(angle as integer,dist as integer, _              p1 as point2d, _              byref p2 as point2d)    p2.x=p1.x-(cos(angle*DtoR)*(200))    p2.y=p1.y-(sin(angle*DtoR)*(200))end sub`

This needs to calculate a value in place of the 200 depending on the value of dist(distance between light and shadow casting box point)

why? what points are p1 and p2?
leopardpm
Posts: 1795
Joined: Feb 28, 2009 20:58

### Re: Isometric shadow casting light.

there seems to be something wrong with the points picked for the shadow polygon, doesn't matter how close or far, it shows up depending upon the angle of the light to the object...
Boromir
Posts: 451
Joined: Apr 30, 2015 19:28
Location: Texas,U.S., Earth,Solar System
Contact:

### Re: Isometric shadow casting light.

leopardpm wrote:
Boromir wrote:

Code: Select all

`public sub makepoint(angle as integer,dist as integer, _              p1 as point2d, _              byref p2 as point2d)    p2.x=p1.x-(cos(angle*DtoR)*(200))    p2.y=p1.y-(sin(angle*DtoR)*(200))end sub`

This needs to calculate a value in place of the 200 depending on the value of dist(distance between light and shadow casting box point)

why? what points are p1 and p2?

P1 is the point selected to cast a shadow.
p2 is the point that is created by this sub. Currently 200 defines the distance between p1 and p2
Boromir
Posts: 451
Joined: Apr 30, 2015 19:28
Location: Texas,U.S., Earth,Solar System
Contact:

### Re: Isometric shadow casting light.

leopardpm wrote:there seems to be something wrong with the points picked for the shadow polygon, doesn't matter how close or far, it shows up depending upon the angle of the light to the object...

Can you get me a screenshot?
Btw, the red thing is supposed to look like an isometric cube.
Last edited by Boromir on Apr 01, 2017 3:35, edited 1 time in total.
leopardpm
Posts: 1795
Joined: Feb 28, 2009 20:58

### Re: Isometric shadow casting light. notice the left and right shadow polygons not calculated correctly?
leopardpm
Posts: 1795
Joined: Feb 28, 2009 20:58

### Re: Isometric shadow casting light.

Boromir wrote:The red thing is supposed to look like an isometric cube.
oh, in that case they are doing it correctly, not hexagon shapes on the ground, but rather rhombuses (squished squares, diamonds)
Boromir
Posts: 451
Joined: Apr 30, 2015 19:28
Location: Texas,U.S., Earth,Solar System
Contact:

### Re: Isometric shadow casting light.

Modified to be more obvious.

Code: Select all

`'2d Quad-Shadow caster'by Ezekiel Gutierrez and Leopardpm''requires light.bmpx 800x400 for the glow'const scrw=1280const scrh=1024const pi = 4 * atn(1)dim shared as double DtoR = pi / 180   ' degrees * DtoR = radianstype point2d    x as integer    y as integerend typetype box    p1 as point2d    p2 as point2d    p3 as point2d    p4 as point2d    declare sub draw(img as any ptr)end typepublic function getslope(p1 as point2d, _                  p2 as point2d,byref dist as integer) as integer        dim as integer xdif,ydif        xdif = p2.x - p1.x        ydif = p2.y - p1.y        dist=SQR(xdif*xdif + ydif*ydif)        return atan2(ydif, xdif)*(180 / pi)end functionpublic sub makepoint(angle as integer,dist as integer, _              p1 as point2d, _              byref p2 as point2d)    p2.x=p1.x-(cos(angle*DtoR)*(200))    p2.y=p1.y-(sin(angle*DtoR)*(200))end subdeclare sub shadowcast(box1 as box,plight as point2d,img as any ptr,col as integer)screenres scrw,scrh,32dim as box boxes(10)dim as point2d plightdim as integer slope1,slope2,slope3,slope4for i as integer=0 to 10boxes(i).p1.x=100+(i*80) 'boxboxes(i).p1.y=90 '    co-ordinate 1boxes(i).p2.x=80+(i*80)'boxboxes(i).p2.y=100'    co-ordinate 2boxes(i).p3.x=120+(i*80)'boxboxes(i).p3.y=100'    co-ordinate 3boxes(i).p4.x=100+(i*80)'boxboxes(i).p4.y=110'    co-ordinate 4next i'create light glow from 32 bit bitmapdim as any ptr lightlight=imagecreate(800,400)bload "light.bmpx",light'====================================color rgb(255,255,255),rgb(0,0,0)dim as any ptr imgimg=imagecreate(scrw,scrh,rgba(0,0,0,0))dim as integer fps,framesdim as double prevtimeprevtime=timerdogetmouse plight.x,plight.y'put light.x and y at mousescreenlockclsline img,(0,0)-(scrw,scrh),rgba(0,0,0,0),bf'fill image with nothingnessput img,(plight.x-400,plight.y-200),light,alpha'   put light into itfor i as integer=0 to 10shadowcast(boxes(i),plight,img,i)'cast shadownext ifor i as integer=0 to 10boxes(i).draw(img)next iput (0,0),img,alpha'draw resultprint "fps "+str(fps)screenunlocksleep 1frames+=1if timer-1>prevtime then fps=frames:frames=0:prevtime=timerloop until multikey(1)sub box.draw(img as any ptr)    'line img,(p1.x,p1.y)-(p2.x,p2.y),rgb(0,0,0)    'line img,(p2.x,p2.y)-(p4.x,p4.y),rgb(0,0,0)    'line img,(p3.x,p3.y)-(p4.x,p4.y),rgb(0,0,0)    'line img,(p3.x,p3.y)-(p1.x,p1.y),rgb(0,0,0)    line img,(p1.x,p1.y-20)-(p2.x,p2.y-20),rgb(255,0,0)    line img,(p2.x,p2.y-20)-(p2.x,p2.y),rgb(255,0,0)    line img,(p2.x,p2.y)-(p4.x,p4.y),rgb(255,0,0)    line img,(p3.x,p3.y)-(p4.x,p4.y),rgb(255,0,0)    line img,(p3.x,p3.y)-(p3.x,p3.y-20),rgb(255,0,0)    line img,(p3.x,p3.y-20)-(p1.x,p1.y-20),rgb(255,0,0)    line img,(p4.x,p4.y)-(p4.x,p4.y-20),rgb(255,0,0)    line img,(p2.x,p2.y-20)-(p4.x,p4.y-20),rgb(255,0,0)    line img,(p3.x,p3.y-20)-(p4.x,p4.y-20),rgb(255,0,0)    paint img,(p1.x+1,p1.y+3),rgb(50,0,0),rgb(255,0,0)    paint img,(p1.x-1,p1.y+3),rgb(100,0,0),rgb(255,0,0)    paint img,(p1.x,p1.y-1),rgb(255,0,0),rgb(255,0,0)end subsub shadowcast(box1 as box,plight as point2d,img as any ptr,col as integer)dim as point2d shad1,shad2dim as integer slope1,slope2,slope3,slope4dim as point2d ch1,ch2dim as integer testval=-200,dist'calculate differences for each pointwith box1slope1=getslope(.p2,plight,dist)'+180slope2=getslope(.p4,plight,dist)'+180slope3=getslope(.p1,plight,dist)'+180slope4=getslope(.p3,plight,dist)'+180dim as integer k,k1,k2,k3,k4if slope1>0 then k+=1:k1=1if slope2>0 then k+=1:k2=1if slope3>0 then k+=1:k3=1if slope4>0 then k+=1:k4=1if k>0 andalso k<4 andalso plight.x<(box1.p2.x+box1.p3.x)/2 then    if k1=1 then slope1-=360    if k2=1 then slope2-=360    if k3=1 then slope3-=360    if k4=1 then slope4-=360end if'===================================================if slope1>testval then testval=slope1:ch1.x=.p2.x:ch1.y=.p2.y      ':chx2=x:chy2=y2if slope2>testval then testval=slope2:ch1.x=.p4.x:ch1.y=.p4.y     ':chx2=x:chy2=yif slope3>testval then testval=slope3:ch1.x=.p1.x:ch1.y=.p1.y       ':chx2=x2:chy2=y2if slope4>testval then testval=slope4:ch1.x=.p3.x:ch1.y=.p3.y      ':chx2=x2:chy2=y'testval=-1if slope1<testval then testval=slope1:ch2.x=.p2.x:ch2.y=.p2.yif slope2<testval then testval=slope2:ch2.x=.p4.x:ch2.y=.p4.yif slope3<testval then testval=slope3:ch2.x=.p1.x:ch2.y=.p1.yif slope4<testval then testval=slope4:ch2.x=.p3.x:ch2.y=.p3.y'===================================================end with'use selected pointsdim as integer ss=getslope(ch1,plight,dist)'get slope difference for one edge of the shadowmakepoint(s,dist,ch1,shad1)'create first points=getslope(ch2,plight,dist)'get slope difference for the other edgemakepoint(s,dist,ch2,shad2)'create second point    dim as point2d p1=shad1,p2=ch1,p3=ch2,p4=shad2'draw shadow outlineline img,(p1.x,p1.y)-(p2.x  ,p2.y  ),rgba(col,0,0,0)line img,(p2.x  ,p2.y  )-(p3.x  ,p3.y  ),rgba(col,0,0,0)line img,(p4.x,p4.y)-(p3.x  ,p3.y  ),rgba(col,0,0,0)line img,(p1.x,p1.y)-(p4.x,p4.y),rgba(col,0,0,0)'fill shadow outlinepaint img,((p1.x+p2.x+p3.x+p4.x)/4, _           (p1.y+p2.y+p3.y+p4.y)/4),rgba(col,0,0,0),rgba(col,0,0,0)'draw boxend sub`
leopardpm
Posts: 1795
Joined: Feb 28, 2009 20:58

### Re: Isometric shadow casting light.

then I cannot replicate the issue you are having, it appears to work fine both far and close up... only when the light is actually on a line between points on the diamond is there an issue, and that is easy enough to test for. Do you have a screenshot of what you are talking about?
leopardpm
Posts: 1795
Joined: Feb 28, 2009 20:58

### Re: Isometric shadow casting light.

Boromir wrote:P1 is the point selected to cast a shadow.
p2 is the point that is created by this sub. Currently 200 defines the distance between p1 and p2
oh, so you are trying to see how far to draw the shadow? How about to the edge of the light image? that seems to make sense.... but I need to look closer at your code to understand, this solution may be way off...lol
Boromir
Posts: 451
Joined: Apr 30, 2015 19:28
Location: Texas,U.S., Earth,Solar System
Contact:

### Re: Isometric shadow casting light. Boromir
Posts: 451
Joined: Apr 30, 2015 19:28
Location: Texas,U.S., Earth,Solar System
Contact:

### Re: Isometric shadow casting light.

leopardpm wrote:oh, so you are trying to see how far to draw the shadow? How about to the edge of the light image? that seems to make sense.... but I need to look closer at your code to understand, this solution may be way off...lol

Exactly. The hard part is calculating how much to extend to reach the edge of the light image.