forum.boolean.name

forum.boolean.name (http://forum.boolean.name/index.php)
-   2D-программирование (http://forum.boolean.name/forumdisplay.php?f=13)
-   -   простой ray casting 2d array hit (http://forum.boolean.name/showthread.php?t=19205)

polopok 31.05.2014 13:44

простой ray casting 2d array hit
 
Думаю и этот код будет полезен ...

Код в Offtop :
Код:

ttt = CreateTimer(60)
;SeedRnd(MilliSecs())
Const numT=10 , sizeT = 20
Dim AA(numT*numT,numT*numT)

Graphics 640,480
SetBuffer BackBuffer()


x2#=130 :y2#=130
x1 =x2 : y1=y2

For b =0 To numT
        For a =0 To numT
        AA(a,b) = Rnd (1 )
               
        Next
Next
While Not KeyHit(1)
Cls ; Сначала очищаем экран
x2 =MouseX() : y2=MouseY()
CamFOV#= (180+ATan2(x1-x2,y1-y2))
If MouseHit(1) Then x1 =MouseX() : y1=MouseY()

 
WaitTimer(ttt)
For angle#= 0 To 360 Step 2
 x3# = 40+200*Sin#(angle)
  y3# = 150+200*Cos#(angle)
 line2(40,150,x3,y3,25,25,125)
Next
For angle#= 30 To -30 Step -0.09
 x2# = x1+200*Sin#(CamFOV-angle)
  y2# = y1+200*Cos#(CamFOV-angle)

 line2(x1,y1,x2,y2,255,25,25)


Next

For b =0 To numT
        For a =0 To numT
                If AA(a,b) = 1 Then Rect a*sizeT ,b*sizeT ,sizeT  ,sizeT  ,0
                If AA(a,b) = 2 Then Rect a*sizeT ,b*sizeT ,sizeT  ,sizeT  ,1
                If AA(a,b) = 2 Then AA(a,b) = 1
        Next
Next

Line x1,y1,x2,y2
Line x1,y1,x1+200*Sin(CamFOV-30),y1+200*Cos(CamFOV-30)
Line x1,y1,x1+200*Sin(CamFOV),y1+200*Cos(CamFOV)
Flip ; Меняем буфер
Wend
FreeTimer(tttt)
End



Function line2(x1#,y1#,x2#,y2#,red=-1,green=-1,blue=-1)
        Local StopLine = 0
    If red>0 And green=-1
          rgb=red
    Else If red=-1
        rgb = ColorBlue() Or ( ColorGreen() Shl 8) Or ( ColorRed() Shl 16)
    Else
          rgb=blue Or (green Shl 8) Or (red Shl 16)
    EndIf

    xd#=x2-x1
    yd#=y2-y1
    If Abs(xd)>Abs(yd) steps=Abs(xd) Else steps=Abs(yd)
    x2=xd/Float(steps)
    y2=yd/Float(steps)

 ;  For Stepr=steps To 1 Step -1
        While Not (x1=x2 And y1=y2) Or ( (StopLine = 1)) Or  (Not ( x1 <=( numT*sizeT+sizeT) And y1 <=(numT*sizeT+sizeT) And x1>-2 And y1>-2))
        WritePixel x1,y1,rgb
        x =  Floor(x1/sizeT) : y= Floor(y1/sizeT)
        If  ( x  <=numT And y    <=numT  And x  >=0 And y  >=0)
                If AA(x,y) =1 Or AA(x,y) =2 Then
                AA(x,y) =2
                StopLine = 1
                Exit
                EndIf
        EndIf
      x1=x1+x2
      y1=y1+y2
  ;  Next
Wend

End Function


Другой вариант :
Код:

;
ttt = CreateTimer(120)
;SeedRnd(MilliSecs())
Const numT=10 , sizeT = 20
Dim AA(numT*numT,numT*numT)

Graphics 800,600,32,2
SetBuffer BackBuffer()


x2#=130 :y2#=130
x1# =x2 : y1#=y2

For b =0 To numT
        For a =0 To numT
        AA(a,b) = Rnd (1 )
               
        Next
Next
While Not KeyHit(1)
Cls
x2 =MouseX() : y2=MouseY()
If MouseDown(1) Then x1 =MouseX() : y1=MouseY()


WaitTimer(ttt)

RayCast2d(x1,y1,x2,y2)

For b =0 To numT
        For a =0 To numT
                If AA(a,b) = 1 Then Rect a*sizeT ,b*sizeT ,sizeT  ,sizeT  ,0
                If AA(a,b) = 2 Then Rect a*sizeT ,b*sizeT ,sizeT  ,sizeT  ,1
                If AA(a,b) = 2 Then AA(a,b) = 1
        Next
Next

Flip
Wend
FreeTimer(tttt)
End

Function RayCast2d(x1#,y1#,x2,y2)
        Local count,StopLine,angle#
        dx# = x1-x2
        dy#= y1-y2
        a# = 180+ATan2(dy,dx) ;

For angle#= 30 To -30 Step -0.5
        vx# = Cos(a+angle)
        vy#= Sin(a+angle)       
        x0#= x1
        y0#=y1
        count=0 : StopLine =0
        While (count<100) Or (StopLine = 1 )
        WritePixel x0,y0,$00ffff
                x =  Floor(x0/sizeT) : y= Floor(y0/sizeT)
                If  ( x  <=numT And y    <=numT  And x  >=0 And y  >=0)
                        If AA(x,y) =1 Or AA(x,y) =2 Then
                        AA(x,y) =2
                        StopLine = 1
                        Exit
                        EndIf
        EndIf
                x0# = (x0#+vx)
                y0# =(y0#+vy)
                count=count+1
        Wend
Next
End Function


LLI.T.A.L.K.E.R. 31.05.2014 18:27

Ответ: простой ray casting 2d array hit
 
Приложу картинки:
1 пример: синие лучи - обзор 360*, красные лучи - направляющий обзор, белые кубики - попадающие в препятствие перед лучами.


2 пример: лучи - с ограниченной дистанцией дальности обзора

polopok 02.06.2014 21:10

Ответ: простой ray casting 2d array hit
 
Ну типо камера обзора 2д


Код:

Const RotateSpeed# = 5 , MoveSpeed# = 1
Global angleViewX# , angleViewY#

ttt = CreateTimer(120)
;SeedRnd(MilliSecs())
Const numT=10 , sizeT = 20
Dim AA(numT*numT,numT*numT)

Graphics 800,600,32,2
SetBuffer BackBuffer()


camPosX#=300
camPosY#=200
angleView#= 180

For b =0 To numT
        For a =0 To numT
        AA(a,b) = Rnd (1 )
               
        Next
Next
While Not KeyHit(1)
Cls
;x2 =MouseX() : y2=MouseY()

If KeyDown(205) Then angleView#  = angleView# +RotateSpeed  ; RIGHT
If KeyDown(203) Then angleView#  = angleView# -RotateSpeed  ; LEFT
If KeyDown(200) Then camPosX#  = camPosX# +MoveSpeed*angleViewX :  camPosY#  = camPosY# +MoveSpeed*angleViewY  ; DOWN
If KeyDown(208) Then camPosY#  = camPosY# +MoveSpeed* -angleViewY  :  camPosX#  = camPosX# +MoveSpeed* -angleViewX  ; UP

WaitTimer(ttt)

View2D(camPosX#,camPosY#,angleView#,offset=4)

For b =0 To numT
        For a =0 To numT
                If AA(a,b) = 1 Then Rect a*sizeT ,b*sizeT ,sizeT  ,sizeT  ,0
                If AA(a,b) = 2 Then Rect a*sizeT ,b*sizeT ,sizeT  ,sizeT  ,1
                If AA(a,b) = 2 Then AA(a,b) = 1
        Next
Next

text 500,50,"Управляем стрелками клавитуры "

Flip
Wend
FreeTimer(tttt)
End


Function View2D#(camPosX#,camPosY#,angleView#,direction = 100)
        IangleView =angleView  Mod 360
        newDirection# =  direction *0.6
        angleViewX# =Cos(angleView )
        angleViewY#= Sin(angleView )
               
        For CV# = 30 To -30 Step -1
        camDirX# =camPosX
        camDirY# =camPosY       
                vd        =0
                While vd < (direction)
                                angleViewX1# =Cos(angleView-CV )
                                angleViewY1#= Sin(angleView-CV )
                               
                                x =  Floor(camDirX/sizeT) : y= Floor(camDirY/sizeT)
                                If  ( x  <=numT And y    <=numT  And x  >=0 And y  >=0)
                                        If AA(x,y) =1 Or AA(x,y) =2 Then
                                        AA(x,y) =2
                                        StopLine = 1
                                        Exit
                                        EndIf
                                EndIf       
                               
                                WritePixel camDirX ,camDirY,$666600
                                camDirX# =camDirX+offset*angleViewX1
                                camDirY# =camDirY+offset*angleViewY1       
                        vd = vd +offset                       
                Wend
        Next 
        Line camPosX,camPosY,camPosX+direction*Cos(angleView ),camPosY+direction*Sin(angleView )
        Line camPosX,camPosY,camPosX+direction*Cos(angleView-30 ),camPosY+direction*Sin(angleView-30 )
        Line camPosX,camPosY,camPosX+direction*Cos(angleView- -30 ),camPosY+direction*Sin(angleView- -30 )
End Function


LLI.T.A.L.K.E.R. 02.06.2014 21:28

Ответ: простой ray casting 2d array hit
 
линии направления не отображаются

попробовал так Line 0,0,camPosX+direction*Cos(angleView ),camPosY+direction*Sin(angleView )
и точка направлена в точку позиции камеры (а не куда должна глядеть камера)

надо вычисления концов линий починить

(я делал на Delphi подобное, но сейчас могу заняться поправкой)

в общем приписал
direction=100
Line camPosX,camPosY,camPosX+direction*Cos(angleView ),camPosY+direction*Sin(angleView )
и норм

для чего тогда newDirection ? и тут же View2D(offset) и View2D(direction)

polopok 02.06.2014 21:59

Ответ: простой ray casting 2d array hit
 
newDirection просто не удалил из кода ,а offset - это смещение шага луча

moka 02.06.2014 23:01

Ответ: простой ray casting 2d array hit
 
Делал давно, используя тригонометрию а не raycast. Тут 800+ отрезков, никаких оптимизаций.
http://moka.co/shadows/

polopok 02.06.2014 23:07

Ответ: простой ray casting 2d array hit
 
что -то вроде пересечения отрезка с отрезком или нормаи? Или проекцией на вектор?

moka 02.06.2014 23:52

Ответ: простой ray casting 2d array hit
 
Находим отрезки в радиусе, кастуем два отрезка к концам кастера, продолжаем два отрезка до квадрата который описывает радиус источника света, и добовляем вершин чтобы прилегал массив вершин к прямоугольнику. Для оптимизации можно объединять стрипы от каждого кастера, и проверять если кастер вообще попал в видимость.
Также мягкие тени не сложно сделать с таким подходом.

LLI.T.A.L.K.E.R. 03.06.2014 11:03

Ответ: простой ray casting 2d array hit
 
Цитата:

Сообщение от polopok (Сообщение 281904)
newDirection просто не удалил из кода ,а offset - это смещение шага луча

просто хочу сказать-показать, что не отображается желаемое

polopok 03.06.2014 21:22

Ответ: простой ray casting 2d array hit
 
Цитата:

Сообщение от moka (Сообщение 281914)
Находим отрезки в радиусе, кастуем два отрезка к концам кастера, продолжаем два отрезка до квадрата который описывает радиус источника света, и добовляем вершин чтобы прилегал массив вершин к прямоугольнику. Для оптимизации можно объединять стрипы от каждого кастера, и проверять если кастер вообще попал в видимость.
Также мягкие тени не сложно сделать с таким подходом.

Нашёл пример 2d light & shadow

moka 03.06.2014 23:03

Ответ: простой ray casting 2d array hit
 
Цитата:

Сообщение от polopok (Сообщение 281987)
Нашёл пример 2d light & shadow

Очень похожий подход, эту демку видел тоже, но она поновее будет. Отличие в том что тут нужно отсортировать все вершины по градусу к источнику и бить их поочередно. Как бы тут есть экономия за счет проверки если не попал по отрезку, но и в моем подходе это реализуемо.

Оба подхода очень быстрые и качественные результаты производят.


Часовой пояс GMT +4, время: 19:03.

vBulletin® Version 3.6.5.
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Перевод: zCarot