Isometric shadow casting light.

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.

Postby Boromir » Mar 31, 2017 19:20

@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,k4
if slope1>0 then k+=1:k1=1
if slope2>0 then k+=1:k2=1
if slope3>0 then k+=1:k3=1
if slope4>0 then k+=1:k4=1
if 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-=360
end 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.

Postby leopardpm » Mar 31, 2017 19:27

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.

Postby Boromir » Mar 31, 2017 19:33

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:
11 shadow casting boxes
I get about 16 fps on my 1.8 ghz Pentium M cpu(not as fast as I had hoped for)

Bigger Light Image
https://drive.google.com/file/d/0BxwvH1 ... sp=sharing


Code: Select all

'2d Quad-Shadow caster
'by Ezekiel Gutierrez and Leopardpm
'
'requires light.bmpx 800x400 for the glow
'
const scrw=1280
const scrh=1024
const pi = 4 * atn(1)
dim shared as double DtoR = pi / 180   ' degrees * DtoR = radians

type point2d
    x as integer
    y as integer
end type
type box
    p1 as point2d
    p2 as point2d
    p3 as point2d
    p4 as point2d
    declare sub draw(img as any ptr)
end type

public 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 function

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

declare sub shadowcast(box1 as box,plight as point2d,img as any ptr,col as integer)

screenres scrw,scrh,32
dim as box boxes(10)

dim as point2d plight
dim as integer slope1,slope2,slope3,slope4
for i as integer=0 to 10
boxes(i).p1.x=100+(i*80) 'box
boxes(i).p1.y=90 '    co-ordinate 1
boxes(i).p2.x=80+(i*80)'box
boxes(i).p2.y=100'    co-ordinate 2
boxes(i).p3.x=120+(i*80)'box
boxes(i).p3.y=100'    co-ordinate 3
boxes(i).p4.x=100+(i*80)'box
boxes(i).p4.y=110'    co-ordinate 4
next i
'create light glow from 32 bit bitmap
dim as any ptr light
light=imagecreate(800,400)
bload "light.bmpx",light
'====================================
color rgb(255,255,255),rgb(0,0,0)
dim as any ptr img
img=imagecreate(scrw,scrh,rgba(0,0,0,0))

dim as integer fps,frames
dim as double prevtime
prevtime=timer
do
getmouse plight.x,plight.y'put light.x and y at mouse

screenlock
cls
line img,(0,0)-(scrw,scrh),rgba(0,0,0,0),bf'fill image with nothingness
put img,(plight.x-400,plight.y-200),light,alpha'   put light into it
for i as integer=0 to 10
shadowcast(boxes(i),plight,img,i)'cast shadow
next i
for i as integer=0 to 10
boxes(i).draw(img)
next i
put (0,0),img,alpha'draw result
print "fps "+str(fps)
screenunlock

sleep 1
frames+=1
if timer-1>prevtime then fps=frames:frames=0:prevtime=timer
loop 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 sub

sub shadowcast(box1 as box,plight as point2d,img as any ptr,col as integer)
dim as point2d shad1,shad2
dim as integer slope1,slope2,slope3,slope4

dim as point2d ch1,ch2
dim as integer testval=-200,dist
'calculate differences for each point

with box1
slope1=getslope(.p2,plight,dist)'+180
slope2=getslope(.p4,plight,dist)'+180
slope3=getslope(.p1,plight,dist)'+180
slope4=getslope(.p3,plight,dist)'+180
dim as integer k,k1,k2,k3,k4
if slope1>0 then k+=1:k1=1
if slope2>0 then k+=1:k2=1
if slope3>0 then k+=1:k3=1
if slope4>0 then k+=1:k4=1
if 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-=360
end if
'===================================================
if slope1>testval then testval=slope1:ch1.x=.p2.x:ch1.y=.p2.y      ':chx2=x:chy2=y2
if slope2>testval then testval=slope2:ch1.x=.p4.x:ch1.y=.p4.y     ':chx2=x:chy2=y
if slope3>testval then testval=slope3:ch1.x=.p1.x:ch1.y=.p1.y       ':chx2=x2:chy2=y2
if slope4>testval then testval=slope4:ch1.x=.p3.x:ch1.y=.p3.y      ':chx2=x2:chy2=y
'testval=-1
if slope1<testval then testval=slope1:ch2.x=.p2.x:ch2.y=.p2.y
if slope2<testval then testval=slope2:ch2.x=.p4.x:ch2.y=.p4.y
if slope3<testval then testval=slope3:ch2.x=.p1.x:ch2.y=.p1.y
if slope4<testval then testval=slope4:ch2.x=.p3.x:ch2.y=.p3.y
'===================================================
end with
'use selected points
dim as integer s
s=getslope(ch1,plight,dist)'get slope difference for one edge of the shadow
makepoint(s,dist,ch1,shad1)'create first point
s=getslope(ch2,plight,dist)'get slope difference for the other edge
makepoint(s,dist,ch2,shad2)'create second point
    dim as point2d p1=shad1,p2=ch1,p3=ch2,p4=shad2
'draw shadow outline
line 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 outline
paint 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 box
end 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.

Postby Boromir » Mar 31, 2017 23:55

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.

Postby leopardpm » Apr 01, 2017 2:37

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.

Postby leopardpm » Apr 01, 2017 2:43

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.

Postby Boromir » Apr 01, 2017 3:15

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.
Image
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.

Postby Boromir » Apr 01, 2017 3:18

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.

Postby leopardpm » Apr 01, 2017 3:24

Image
notice the left and right shadow polygons not calculated correctly?
leopardpm
Posts: 1795
Joined: Feb 28, 2009 20:58

Re: Isometric shadow casting light.

Postby leopardpm » Apr 01, 2017 3:26

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.

Postby Boromir » Apr 01, 2017 3:32

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=1280
const scrh=1024
const pi = 4 * atn(1)
dim shared as double DtoR = pi / 180   ' degrees * DtoR = radians

type point2d
    x as integer
    y as integer
end type
type box
    p1 as point2d
    p2 as point2d
    p3 as point2d
    p4 as point2d
    declare sub draw(img as any ptr)
end type

public 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 function

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

declare sub shadowcast(box1 as box,plight as point2d,img as any ptr,col as integer)

screenres scrw,scrh,32
dim as box boxes(10)

dim as point2d plight
dim as integer slope1,slope2,slope3,slope4
for i as integer=0 to 10
boxes(i).p1.x=100+(i*80) 'box
boxes(i).p1.y=90 '    co-ordinate 1
boxes(i).p2.x=80+(i*80)'box
boxes(i).p2.y=100'    co-ordinate 2
boxes(i).p3.x=120+(i*80)'box
boxes(i).p3.y=100'    co-ordinate 3
boxes(i).p4.x=100+(i*80)'box
boxes(i).p4.y=110'    co-ordinate 4
next i
'create light glow from 32 bit bitmap
dim as any ptr light
light=imagecreate(800,400)
bload "light.bmpx",light
'====================================
color rgb(255,255,255),rgb(0,0,0)
dim as any ptr img
img=imagecreate(scrw,scrh,rgba(0,0,0,0))

dim as integer fps,frames
dim as double prevtime
prevtime=timer
do
getmouse plight.x,plight.y'put light.x and y at mouse

screenlock
cls
line img,(0,0)-(scrw,scrh),rgba(0,0,0,0),bf'fill image with nothingness
put img,(plight.x-400,plight.y-200),light,alpha'   put light into it
for i as integer=0 to 10
shadowcast(boxes(i),plight,img,i)'cast shadow
next i
for i as integer=0 to 10
boxes(i).draw(img)
next i
put (0,0),img,alpha'draw result
print "fps "+str(fps)
screenunlock

sleep 1
frames+=1
if timer-1>prevtime then fps=frames:frames=0:prevtime=timer
loop 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 sub

sub shadowcast(box1 as box,plight as point2d,img as any ptr,col as integer)
dim as point2d shad1,shad2
dim as integer slope1,slope2,slope3,slope4

dim as point2d ch1,ch2
dim as integer testval=-200,dist
'calculate differences for each point

with box1
slope1=getslope(.p2,plight,dist)'+180
slope2=getslope(.p4,plight,dist)'+180
slope3=getslope(.p1,plight,dist)'+180
slope4=getslope(.p3,plight,dist)'+180
dim as integer k,k1,k2,k3,k4
if slope1>0 then k+=1:k1=1
if slope2>0 then k+=1:k2=1
if slope3>0 then k+=1:k3=1
if slope4>0 then k+=1:k4=1
if 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-=360
end if
'===================================================
if slope1>testval then testval=slope1:ch1.x=.p2.x:ch1.y=.p2.y      ':chx2=x:chy2=y2
if slope2>testval then testval=slope2:ch1.x=.p4.x:ch1.y=.p4.y     ':chx2=x:chy2=y
if slope3>testval then testval=slope3:ch1.x=.p1.x:ch1.y=.p1.y       ':chx2=x2:chy2=y2
if slope4>testval then testval=slope4:ch1.x=.p3.x:ch1.y=.p3.y      ':chx2=x2:chy2=y
'testval=-1
if slope1<testval then testval=slope1:ch2.x=.p2.x:ch2.y=.p2.y
if slope2<testval then testval=slope2:ch2.x=.p4.x:ch2.y=.p4.y
if slope3<testval then testval=slope3:ch2.x=.p1.x:ch2.y=.p1.y
if slope4<testval then testval=slope4:ch2.x=.p3.x:ch2.y=.p3.y
'===================================================
end with
'use selected points
dim as integer s
s=getslope(ch1,plight,dist)'get slope difference for one edge of the shadow
makepoint(s,dist,ch1,shad1)'create first point
s=getslope(ch2,plight,dist)'get slope difference for the other edge
makepoint(s,dist,ch2,shad2)'create second point
    dim as point2d p1=shad1,p2=ch1,p3=ch2,p4=shad2
'draw shadow outline
line 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 outline
paint 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 box
end sub
leopardpm
Posts: 1795
Joined: Feb 28, 2009 20:58

Re: Isometric shadow casting light.

Postby leopardpm » Apr 01, 2017 3:37

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.

Postby leopardpm » Apr 01, 2017 3:42

Boromir wrote:P1 is the point selected to cast a shadow.
p2 is the point that is created by this sub.
Image
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.

Postby Boromir » Apr 01, 2017 3:42

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

Re: Isometric shadow casting light.

Postby Boromir » Apr 01, 2017 3:44

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.

Return to “Game Dev”

Who is online

Users browsing this forum: No registered users and 1 guest