PureBasic

Forums PureBasic
Nous sommes le Lun 09/Déc/2019 12:16

Heures au format UTC + 1 heure




Poster un nouveau sujet Répondre au sujet  [ 16 messages ]  Aller à la page 1, 2  Suivante
Auteur Message
 Sujet du message: Eclairage dynamique 2D
MessagePosté: Ven 02/Juin/2017 0:42 
Hors ligne
Avatar de l’utilisateur

Inscription: Jeu 14/Oct/2004 19:48
Messages: 1121
Il y a 2 bugs que je ne sais pas régler élégamment. Je pense que c'est un problème de virgule flottant avec l'angle et le trie.
Il se fait tard je verrais ça demain. Si vous trouvez avant, dites moi. :D

Espace pour voir le dessous de l'affaire...
Image

Code:
DisableDebugger
If InitSprite() = 0 Or InitKeyboard() = 0 Or InitMouse() = 0:MessageRequester("Error", "Can't open the sprite system", 0):End:EndIf
If OpenWindow(0, 0, 0,800, 600,"lighting", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)=0:MessageRequester("Error", "Can't open windowed screen!", 0):EndIf
If OpenWindowedScreen(WindowID(0), 0, 0, 800, 600, 0, 0, 0)=0:MessageRequester("Error", "Can't open windowed screen!", 0):EndIf   
Structure seg
  x1.d
  y1.d
  x2.d
  y2.d
EndStructure
Structure retour
  x.d
  y.d
  param.d
EndStructure
Structure xy
  x.d
  y.d
EndStructure
Structure ray
  a.xy
  b.xy
EndStructure
Global NewList pt.xy()
Global NewList Seg.seg()
Global NewMap dot.xy()
Global NewList angle.d()
NewList ligne.xy()
modedebug.i=0
f.d=0.00001
Ray.ray
Segment.ray
Procedure Intersection(*ray.ray,*seg.seg,*retour.retour)
   r_dx.d = *ray\b\x-*ray\a\x
   r_dy.d = *ray\b\y-*ray\a\y
   s_dx.d = *seg\x2-*seg\x1
   s_dy.d = *seg\y2-*seg\y1
   r_mag.d = Sqr(r_dx*r_dx+r_dy*r_dy);
   s_mag.d = Sqr(s_dx*s_dx+s_dy*s_dy);
   If r_dx/r_mag=s_dx/s_mag And r_dy/r_mag=s_dy/s_mag:ProcedureReturn 0:EndIf
   T2.d = (r_dx*(*seg\y1-*ray\a\y) + r_dy*(*ray\a\x-*seg\x1))/(s_dx*r_dy - s_dy*r_dx);
   T1.d = (*seg\x1+s_dx*T2-*ray\a\x)/r_dx;
   If T1<0:ProcedureReturn 0:EndIf
   If T2<0 Or T2>1:ProcedureReturn 0:EndIf;
   *retour\x=*ray\a\x+r_dx*T1
   *retour\y=*ray\a\y+r_dy*T1
   *retour\param=T1
   ProcedureReturn *retour
EndProcedure

Procedure AddSegment(x1.d,y1.d,x2.d,y2.d)
  AddElement(seg()):seg()\x1=x1:seg()\y1=y1:seg()\x2=x2:seg()\y2=y2
  dot(Str(x1)+"\"+Str(y1))\x=x1:dot(Str(x1)+"\"+Str(y1))\y=y1
  dot(Str(x2)+"\"+Str(y2))\x=x2:dot(Str(x2)+"\"+Str(y2))\y=y2
EndProcedure

Procedure ProcessAllSegments()
  ; Get all unique points
  ForEach dot()
    AddElement(pt())
    pt()\x=dot()\x
    pt()\y=dot()\y
  Next
EndProcedure

CreateImage(0,800,600,32,RGB(0,0,0))
CreateSprite(0,800,600)
;external box// Fenêtre englobante
Addsegment(-1,-1,800,-1)
addsegment(800,-1,800,600)
Addsegment(800,600,-1,600)
Addsegment(-1,600,-1,-1)
;random squares// carrés aléatoires
For i=1 To 30
  size.d=Random(50,10)
  rx.d=Random(750,50)
  ry.d=Random(550,50)
  Addsegment(rx,ry,rx+size,ry)
  Addsegment(rx+size,ry,rx+size,ry+size)
  Addsegment(rx+size,ry+size,rx,ry+size)
  Addsegment(rx,ry+size,rx,ry)
Next i

For an=0 To 360 Step 36
  AddSegment(200+20*Cos(Radian(an)),200+20*Sin(Radian(an)),200+20*Cos(Radian(an+36)),200+20*Sin(Radian(an+36)))
Next an

ProcessAllSegments()

MouseLocate(10,10)

Repeat
  Repeat:Until WindowEvent()=0
  Delay(3):FlipBuffers():ExamineKeyboard():ExamineMouse():If KeyboardReleased(#PB_Key_Space):modedebug=~modedebug:EndIf
  x.d=MouseX():y.d=MouseY()
  ClearList(ligne())
  ClearList(angle())
 
    ; Get all angles
  ForEach pt()
    dx.d=pt()\x-x:dy.d=pt()\y-y
    angle.d=ATan2(dx,dy)   
    AddElement(angle()):angle()=angle-f
    AddElement(angle()):angle()=angle
    AddElement(angle()):angle()=angle+f
  Next
  SortList(angle(),#PB_Sort_Ascending)
 
  ForEach angle()
    ray\a\x=x:ray\a\y=y
    ray\b\x=Cos(angle())+x:ray\b\y=Sin(angle())+y
    Retour.retour
    closest.retour
    closest\param=10000
    ForEach seg()
      If Intersection(@ray,@seg(),@retour)=0:Continue:EndIf
      If retour\param<closest\param
        closest\param=retour\param
        closest\x=retour\x
        closest\y=retour\y
      EndIf
    Next
    If closest\param=10000:Continue:EndIf
    AddElement(ligne())
    ligne()\x=closest\x:ligne()\y=closest\y
  Next
  ;Display everything // Affichage
  StartDrawing(ImageOutput(0))
  DrawingMode(#PB_2DDrawing_Gradient)
  BackColor($FFFFFF)
  FrontColor($000000)
  CircularGradient(x,y,450)
  Circle(x,y,800)
  StopDrawing()
  FirstElement(ligne())
  prevx.d=ligne()\x
  prevy.d=ligne()\y   
  StartDrawing(SpriteOutput(0))
  Box(0,0,800,600,RGB(1,1,1))
  ForEach ligne()
    If modedebug:LineXY(x,y,ligne()\x,ligne()\y,RGB(0,255,0)):EndIf
    If modedebug=0:LineXY(prevx,prevy,ligne()\x,ligne()\y,#Black):EndIf
    prevx=ligne()\x:prevy=ligne()\y
    If modedebug:Circle(ligne()\x,ligne()\y,2,RGB(0,255,0)):EndIf
  Next
  FirstElement(ligne())
  If modedebug=0
    LineXY(prevx,prevy,ligne()\x,ligne()\y,#Black)
    FillArea(x,y,#Black,#Black)
  EndIf
  ;display squares // affiche les segments des carrés
  ForEach seg()
    LineXY(seg()\x1,seg()\y1,seg()\x2,seg()\y2,RGB(255,0,0))
  Next
  ;display mouse // affiche la souris
  Circle(MouseX(),MouseY(),5,RGB(255,0,0))
  DrawText(0,0,"Press [SPACE]")
  StopDrawing()
 
  ;display gradient light // affiche le dégradé d'éclairage
  StartDrawing(ScreenOutput())
  DrawImage(ImageID(0),0,0)
  StopDrawing()
  ;display mask sprite // Affiche le sprite de masque
  DisplayTransparentSprite(0,0,0)
Until KeyboardPushed(#PB_Key_Escape)

_________________
Il y a deux méthodes pour écrire des programmes sans erreurs. Mais il n’y a que la troisième qui marche.
Version de PB : 5.45LTS - 32 bits


Dernière édition par Fig le Ven 02/Juin/2017 19:45, édité 10 fois.

Haut
 Profil  
Répondre en citant le message  
 Sujet du message: Re: Eclairage dynamique 2D
MessagePosté: Ven 02/Juin/2017 8:27 
Hors ligne
Avatar de l’utilisateur

Inscription: Jeu 14/Oct/2004 19:48
Messages: 1121
J'ai rajouté un éclairage plus réaliste...

_________________
Il y a deux méthodes pour écrire des programmes sans erreurs. Mais il n’y a que la troisième qui marche.
Version de PB : 5.45LTS - 32 bits


Haut
 Profil  
Répondre en citant le message  
 Sujet du message: Re: Eclairage dynamique 2D
MessagePosté: Ven 02/Juin/2017 9:33 
Hors ligne
Avatar de l’utilisateur

Inscription: Jeu 25/Juin/2015 16:18
Messages: 270
joli code
le bug est visible lorsque la source lumineuse est dans l'alignement vertical ou horizontal de l'un des sommets des carrés
(losque la fonction intersection retourne 0 (det=0), je pense)


Haut
 Profil  
Répondre en citant le message  
 Sujet du message: Re: Eclairage dynamique 2D
MessagePosté: Ven 02/Juin/2017 10:07 
Hors ligne
Avatar de l’utilisateur

Inscription: Dim 22/Aoû/2010 15:24
Messages: 6860
Localisation: IDF (Yvelines)
Le bug je ne sais trop quoi dire. Par contre j'aime beaucoup.

_________________

➽ Config PureBasic : i3, RAM 4Go, NVidia (1024 Mo), Windows 10 - PB 5.70 LTS
➽ Je papote aussi sur http://purebasic.chat

➽ Sites personnels http://falsam.com & EasySprite.js

➽ Je ne réponds pas aux MP techniques


Haut
 Profil  
Répondre en citant le message  
 Sujet du message: Re: Eclairage dynamique 2D
MessagePosté: Ven 02/Juin/2017 11:04 
Hors ligne
Avatar de l’utilisateur

Inscription: Dim 13/Déc/2015 11:05
Messages: 649
Localisation: Allez, cherche...
Trés intéressant ce code, merci Fig :)

_________________
"Le bug se situe entre la chaise et le clavier"
Votre expert national en bogage et segfaults.

CPU : AMD A8 Quad core - RAM 8Gb - HDD 2To
  • Windows 10 x64 - PB 5.61 x64
  • Linux Ubuntu 16.04 LTS x64 (dual boot) - PB pas encore réinstallé


Haut
 Profil  
Répondre en citant le message  
 Sujet du message: Re: Eclairage dynamique 2D
MessagePosté: Ven 02/Juin/2017 13:51 
Hors ligne

Inscription: Mer 04/Nov/2015 17:39
Messages: 1025
Jolie ce code :)

_________________
Processeur: Intel Core I7-4790 - 4 Cœurs - 8 Thread: 3.60 Ghz.
Ram: 32 GB.
Disque: C: SDD 250 GB, D: 3 TB.
Vidéo: NVIDIA GeForce GTX 960: 2 GB DDR5.
Écran: Asus VX248 24 Pouces: 1920 x 1080.
Système: Windows 7 64 Bits.

PureBasic: 5.60 x64 Bits.


Haut
 Profil  
Répondre en citant le message  
 Sujet du message: Re: Eclairage dynamique 2D
MessagePosté: Ven 02/Juin/2017 15:20 
Hors ligne

Inscription: Mer 21/Jan/2004 17:48
Messages: 5162
ça me semble bien plus rapide que mon truc :

http://www.purebasic.fr/french/viewtopic.php?f=8&t=14566&p=165362&hilit=purepunch#p165362

_________________
http://purebasic.developpez.com/
Je ne réponds à aucune question technique en PV, utilisez le forum, il est fait pour ça, et la réponse peut profiter à tous.


Haut
 Profil  
Répondre en citant le message  
 Sujet du message: Re: Eclairage dynamique 2D
MessagePosté: Ven 02/Juin/2017 15:26 
Hors ligne
Avatar de l’utilisateur

Inscription: Jeu 14/Oct/2004 19:48
Messages: 1121
Le tien ne bug pas en tout cas. Tu as la version non compressée pour voir ?

_________________
Il y a deux méthodes pour écrire des programmes sans erreurs. Mais il n’y a que la troisième qui marche.
Version de PB : 5.45LTS - 32 bits


Haut
 Profil  
Répondre en citant le message  
 Sujet du message: Re: Eclairage dynamique 2D
MessagePosté: Ven 02/Juin/2017 15:42 
Hors ligne
Avatar de l’utilisateur

Inscription: Dim 13/Déc/2015 11:05
Messages: 649
Localisation: Allez, cherche...
J'ai tenté de comprendre comment tout cela marchait et de voir pourquoi ca buggait et je ne suis arrivé qu'a des noeuds dans mon ensemble neuronal inefficace :mrgreen:

Je te conseille la troisiéme méthode. :P

_________________
"Le bug se situe entre la chaise et le clavier"
Votre expert national en bogage et segfaults.

CPU : AMD A8 Quad core - RAM 8Gb - HDD 2To
  • Windows 10 x64 - PB 5.61 x64
  • Linux Ubuntu 16.04 LTS x64 (dual boot) - PB pas encore réinstallé


Haut
 Profil  
Répondre en citant le message  
 Sujet du message: Re: Eclairage dynamique 2D
MessagePosté: Ven 02/Juin/2017 15:47 
Hors ligne
Avatar de l’utilisateur

Inscription: Jeu 14/Oct/2004 19:48
Messages: 1121
http://ncase.me/sight-and-light/
Avec ce lien ça peut aider la compréhension...
Mais ça n'aidera pas à comprendre où je me suis foutu dedans.

Bon j'ai chopé le code JS du gentil monsieur du tuto, je vais regarder... :mrgreen:

_________________
Il y a deux méthodes pour écrire des programmes sans erreurs. Mais il n’y a que la troisième qui marche.
Version de PB : 5.45LTS - 32 bits


Haut
 Profil  
Répondre en citant le message  
 Sujet du message: Re: Eclairage dynamique 2D
MessagePosté: Ven 02/Juin/2017 18:03 
Hors ligne
Avatar de l’utilisateur

Inscription: Jeu 14/Oct/2004 19:48
Messages: 1121
J'ai repris mon code en me conformant au code en Javascript.

_________________
Il y a deux méthodes pour écrire des programmes sans erreurs. Mais il n’y a que la troisième qui marche.
Version de PB : 5.45LTS - 32 bits


Dernière édition par Fig le Mar 13/Juin/2017 0:04, édité 1 fois.

Haut
 Profil  
Répondre en citant le message  
 Sujet du message: Re: Eclairage dynamique 2D
MessagePosté: Ven 02/Juin/2017 18:20 
Hors ligne
Avatar de l’utilisateur

Inscription: Dim 13/Déc/2015 11:05
Messages: 649
Localisation: Allez, cherche...
J'ai remarqué que lorsque la source est dans l'alignement d'un segment, les deux rayons assignés aux deux extrémités de ce segments disparaissent, et ne sont même plus dessinés... Comme si les deux points étaient alors ignorés 8O :?

En tout cas, merci pour le lien, j'ai pu comprendre le fonctionnement du truc :) C'est trés intéressant

_________________
"Le bug se situe entre la chaise et le clavier"
Votre expert national en bogage et segfaults.

CPU : AMD A8 Quad core - RAM 8Gb - HDD 2To
  • Windows 10 x64 - PB 5.61 x64
  • Linux Ubuntu 16.04 LTS x64 (dual boot) - PB pas encore réinstallé


Haut
 Profil  
Répondre en citant le message  
 Sujet du message: Re: Eclairage dynamique 2D
MessagePosté: Ven 02/Juin/2017 18:45 
Hors ligne

Inscription: Mer 21/Jan/2004 17:48
Messages: 5162
Fig a écrit:
http://ncase.me/sight-and-light/
Avec ce lien ça peut aider la compréhension...
Mais ça n'aidera pas à comprendre où je me suis foutu dedans.

Bon j'ai chopé le code JS du gentil monsieur du tuto, je vais regarder... :mrgreen:


Ah super, c'est exactement ce tuto que j'avais utilisé, et j'ai oublié de copier l'adresse dans mon code, merci de l'avoir collée ici :)

Je m'étais basé sur le code java je crois pour faire mon truc. Mais je ne trouve pas le code que j'avais utilisé pour créer le purepunch, j'ai quand même retrouvé ce brouillon


Code:
;-TEST
#Epsilon = 0.0001

Structure Vector2
  x.d
  y.d
EndStructure

Structure Segment
  p1.Vector2
  p2.Vector2
EndStructure

Structure Triangle
  No.i
  p1.Vector2
  p2.Vector2
  p3.Vector2
EndStructure

Structure intersection
  ok.i
  x.d
  y.d
  param.d
  angle.d
EndStructure 

Declare Init()
Declare CreateLevel()
Declare Main()
Declare getIntersection(*Intersect.intersection, *ray.Segment,*segment.Segment)
Declare getSightPolygon(sightX.f,sightY.f)
Declare draw()
Declare DrawPolygon()

Global NewList ListSegments.Segment()
Global NewList ListUniquePoints.Vector2()
Global NewList ListUniqueAngles.d()
Global NewList ListIntersect.intersection()


Init()
CreateLevel()
getSightPolygon(0,0)
Main()

Procedure Init()
  InitSprite()
  InitMouse()
  InitKeyboard()
  OpenWindow(0, 0, 0, 640, 360, "Lumière")
  OpenWindowedScreen(WindowID(0), 0, 0, 640, 360)
EndProcedure

Procedure Main()
  Repeat
    Repeat
      Event = WindowEvent()
    Until Event = 0 Or event = #PB_Event_CloseWindow
    ClearScreen(RGB(210, 210, 210))
    ExamineMouse()
    ExamineKeyboard()
    Draw()
   
    FlipBuffers()
   
  Until KeyboardPushed(#PB_Key_Escape) Or event = #PB_Event_CloseWindow
EndProcedure

Procedure CreateLevel()
 
  With ListSegments()
   
    ; Border
    AddElement(ListSegments())
    \p1\x =   0 : \p1\y =   0 : \p2\x = 639 : \p2\y =   0
    AddElement(ListSegments())
    \p1\x = 639 : \p1\y =   0 : \p2\x = 639 : \p2\y = 359
    AddElement(ListSegments())
    \p1\x = 639 : \p1\y = 359 : \p2\x =   0 : \p2\y = 359
    AddElement(ListSegments())
    \p1\x =   0 : \p1\y = 359 : \p2\x =   0 : \p2\y =   0
   
    ; Polygon #1
    AddElement(ListSegments())
    \p1\x = 100 : \p1\y = 150 : \p2\x = 120 : \p2\y =  50
    AddElement(ListSegments())
    \p1\x = 120 : \p1\y =  50 : \p2\x = 200 : \p2\y =  80
    AddElement(ListSegments())
    \p1\x = 200 : \p1\y =  80 : \p2\x = 140 : \p2\y = 210
    AddElement(ListSegments())
    \p1\x = 140 : \p1\y = 210 : \p2\x = 100 : \p2\y = 150
   
    ; Polygon #2
    AddElement(ListSegments())
    \p1\x = 100 : \p1\y = 200 : \p2\x = 120 : \p2\y = 250
    AddElement(ListSegments())
    \p1\x = 120 : \p1\y = 250 : \p2\x =  60 : \p2\y = 300
    AddElement(ListSegments())
    \p1\x =  60 : \p1\y = 300 : \p2\x = 100 : \p2\y = 200   
   
   
    ; Polygon #3
    AddElement(ListSegments())
    \p1\x = 200 : \p1\y = 260 : \p2\x = 220 : \p2\y = 150
    AddElement(ListSegments())
    \p1\x = 220 : \p1\y = 150 : \p2\x = 300 : \p2\y = 200
    AddElement(ListSegments())
    \p1\x = 300 : \p1\y = 200 : \p2\x = 350 : \p2\y = 320
    AddElement(ListSegments())
    \p1\x = 350 : \p1\y = 320 : \p2\x = 200 : \p2\y = 260   
   
    ; Polygon #4
    AddElement(ListSegments())
    \p1\x = 340 : \p1\y =  60 : \p2\x = 360 : \p2\y =  40
    AddElement(ListSegments())
    \p1\x = 360 : \p1\y =  40 : \p2\x = 370 : \p2\y =  70
    AddElement(ListSegments())
    \p1\x = 370 : \p1\y =  70 : \p2\x = 340 : \p2\y =  60     
   
    ; Polygon #5
    AddElement(ListSegments())
    \p1\x = 450 : \p1\y = 190 : \p2\x = 560 : \p2\y = 170
    AddElement(ListSegments())
    \p1\x = 560 : \p1\y = 170 : \p2\x = 540 : \p2\y = 270
    AddElement(ListSegments())
    \p1\x = 540 : \p1\y = 270 : \p2\x = 430 : \p2\y = 290
    AddElement(ListSegments())
    \p1\x = 430 : \p1\y = 290 : \p2\x = 450 : \p2\y = 190     
   
   
    ; Polygon #6
    AddElement(ListSegments())
    \p1\x = 400 : \p1\y =  95 : \p2\x = 580 : \p2\y =  50
    AddElement(ListSegments())
    \p1\x = 580 : \p1\y =  50 : \p2\x = 480 : \p2\y = 150
    AddElement(ListSegments())
    \p1\x = 480 : \p1\y = 150 : \p2\x = 400 : \p2\y =  95     
   
  EndWith
EndProcedure

Procedure getIntersection(*Intersect.intersection, *ray.Segment,*segment.Segment)
 
  ; RAY in parametric: Point + Direction*T1
  r_px.d = *ray\p1\x
  r_py.d = *ray\p1\y
  r_dx.d = *ray\p2\x-*ray\p1\x
  r_dy.d = *ray\p2\y-*ray\p1\y
 
  ; SEGMENT in parametric: Point + Direction*T2
  s_px.d = *segment\p1\x
  s_py.d = *segment\p1\y
  s_dx.d = *segment\p2\x-*segment\p1\x
  s_dy.d = *segment\p2\y-*segment\p1\y
 
  ; Are they parallel? If so, no intersect
  r_mag.d = Sqr(r_dx*r_dx+r_dy*r_dy)
  s_mag.d = Sqr(s_dx*s_dx+s_dy*s_dy)
 
  If (r_dx/r_mag=s_dx/s_mag And r_dy/r_mag=s_dy/s_mag) ; Directions are the same
    ProcedureReturn #False
  EndIf
 
  ; SOLVE For T1 & T2
  T2.d = (r_dx*(s_py-r_py) + r_dy*(r_px-s_px))/(s_dx*r_dy - s_dy*r_dx)
  T1.d = (s_px+s_dx*T2-r_px)/r_dx
 
  ; Must be within parametic whatevers For RAY/SEGMENT
  If T1<0
    ProcedureReturn #False
  EndIf
  If T2<0 Or T2>1
    ProcedureReturn #False
  EndIf 
 
  ; Return the POINT OF INTERSECTION
  *Intersect\x = r_px+r_dx*T1
  *Intersect\y = r_py+r_dy*T1
  *Intersect\param = T1
  ProcedureReturn #True
EndProcedure

Procedure getSightPolygon(sightX.f,sightY.f)
 
  ; Get all unique points
  ClearList(ListUniquePoints())
  ForEach ListSegments()
    AddElement(ListUniquePoints())
    ListUniquePoints()\x = ListSegments()\p1\x
    ListUniquePoints()\y = ListSegments()\p1\y
    AddElement(ListUniquePoints())
    ListUniquePoints()\x = ListSegments()\p2\x
    ListUniquePoints()\y = ListSegments()\p2\y
  Next
 
  ForEach ListUniquePoints()
    ValueX.f = ListUniquePoints()\x
    ValueY.f = ListUniquePoints()\y
    PushListPosition(ListUniquePoints())
    While NextElement(ListUniquePoints())
      If ListUniquePoints()\x = ValueX And  ListUniquePoints()\y = ValueY
        DeleteElement(ListUniquePoints())
      EndIf
    Wend
    PopListPosition(ListUniquePoints())
  Next
 
  ; Get all angles
  ClearList(ListUniqueAngles())
 
  ForEach ListUniquePoints()
    angle.f = ATan2(ListUniquePoints()\x-sightX, ListUniquePoints()\y-sightY)
    ;uniquePoint.angle = angle;
    AddElement(ListUniqueAngles())
    ListUniqueAngles() = angle-0.00001
    AddElement(ListUniqueAngles())
    ListUniqueAngles() = angle
    AddElement(ListUniqueAngles())
    ListUniqueAngles() = angle+0.00001
  Next 
 
  ; RAYS IN ALL DIRECTIONS
  ClearList(ListIntersect())
  ForEach ListUniqueAngles()
    angle.f = ListUniqueAngles()
   
    ; Calculate dx & dy from angle
    dx.d = Cos(angle)
    dy.d = Sin(angle)
   
    ; Ray from center of screen To mouse
    ray.Segment
    ray\p1\x = sightX : ray\p1\y = sightY
    ray\p2\x = sightX+dx : ray\p2\y = sightY+dy
   
   
    ; Find CLOSEST intersection
    Protected.intersection closestIntersect, intersect
    closestIntersect\ok = #False
    ForEach ListSegments()
      Info = getIntersection(@intersect, @ray, @ListSegments())
      If Info = 0
        Continue
      EndIf 
      If (closestIntersect\ok=#False Or intersect\param<closestIntersect\param)
        closestIntersect=intersect
        closestIntersect\ok = #True
      EndIf
    Next
   
    ; Intersect angle
    If (closestIntersect\ok=#False)
      Continue
    EndIf
   
    closestIntersect\angle = angle
   
    ; Add To List of intersects
    AddElement(ListIntersect())
    ListIntersect() = closestIntersect
   
  Next
 
  ; Sort intersects by angle
  SortStructuredList(ListIntersect(),  #PB_Sort_Ascending, OffsetOf(intersection\angle), TypeOf(intersection\angle))
 
EndProcedure

Procedure draw()
 
  StartDrawing(ScreenOutput())
 
  With ListSegments()
    ForEach ListSegments()
      LineXY(\p1\x, \p1\y, \p2\x, \p2\y, RGB(5, 5, 5))
    Next
  EndWith
 
  getSightPolygon(MouseX(), MouseY())
   
  ok = 0
  x.d = 0
  y.d = 0
  x0.d = 0
  y0.d = 0
   
  ForEach ListIntersect()
    If ok = 0
      x0 = ListIntersect()\x
      y0 = ListIntersect()\y   
    Else
           
      LineXY(x, y, ListIntersect()\x, ListIntersect()\y, RGB(255, 0, 0))
     
    EndIf 
    ;LineXY(MouseX(), MouseY(), ListIntersect()\x, ListIntersect()\y, RGB(255, 0, 0))
    x = ListIntersect()\x
    y = ListIntersect()\y   
    ok = 1
  Next
  LineXY(x0, y0, ListIntersect()\x, ListIntersect()\y, RGB(255, 0, 0))
  FillArea(MouseX(), MouseY(), -1, RGB(255,0,0))
  Circle(MouseX(), MouseY(), 4, RGB(255, 255, 0))
  StopDrawing()
EndProcedure

_________________
http://purebasic.developpez.com/
Je ne réponds à aucune question technique en PV, utilisez le forum, il est fait pour ça, et la réponse peut profiter à tous.


Haut
 Profil  
Répondre en citant le message  
 Sujet du message: Re: Eclairage dynamique 2D
MessagePosté: Ven 02/Juin/2017 19:00 
Hors ligne
Avatar de l’utilisateur

Inscription: Jeu 14/Oct/2004 19:48
Messages: 1121
J'ai trouvé mon erreur, j'utilisais Atan en la corrigeant (mal) au lieu de Atan2...
Merci d'avoir regardé, Comtois.

A part cette erreur, j'étais arrivé assez proche du code en JS... C'est satisfaisant. (je ne l'avais pas consulté mais m'étais basé sur les explications seulement)

_________________
Il y a deux méthodes pour écrire des programmes sans erreurs. Mais il n’y a que la troisième qui marche.
Version de PB : 5.45LTS - 32 bits


Haut
 Profil  
Répondre en citant le message  
 Sujet du message: Re: Eclairage dynamique 2D
MessagePosté: Dim 11/Juin/2017 8:38 
Hors ligne
Avatar de l’utilisateur

Inscription: Jeu 14/Oct/2004 19:48
Messages: 1121
GPI a été plus loin sur le forum anglais, je poste son code ci-dessous car il servira de référence pour ceux qui s'en serviraient pour des jeux...
GPI a écrit:
nice code.

i have add some extensions to your code:
* add a FillPolygon-Routine (when two rays are to near, fillarea will not work correct)
* I filter the segs-list. I only calculate ray-segments-collisions, when a collision is possible (this speed up the code, i can handle here over 400 boxes with nearly the same speed)
* when 3 collions are detected on one segment, the middle one is eliminated
* i add the possibility for a "light-mask"

edit: Remove DisableDebugger - this will crash the code...

Code:
EnableExplicit

;Original Polygon-Routine from
;http://www.purebasic.fr/english/viewtopic.php?f=12&t=42870&start=0
Structure pippoint
  x.i
  y.i
EndStructure

Procedure FilledPolygon(List points.pippoint(),color,midx=0,midy=0,spr=#PB_Any)
  Protected miny,maxy,cy,oddnodes
  Protected x.d,y.d,x1.d,y1.d,x2.d,y2.d
  Protected iNodes.i, i.i
 
  If spr<>#PB_Any
    Protected startx,offx,starty
    Protected SprWidth=SpriteWidth(spr)
    Protected SprHeight=SpriteHeight(spr)
    Protected sprxmid=SprWidth/2
    Protected sprymid=SprHeight/2
    Protected width,width2
   
  EndIf
 
  ;NewList nodes.i()
  Dim nodes.i( ListSize(points()) )
 
  ;Find least and most y values to restrict area to transverse when filling..
  ResetList(points())
  If NextElement(points())
    miny=points()\y;OutputHeight()-1
    maxy=points()\y
    While NextElement(points())
      If points()\y<miny:miny=points()\y:EndIf
      If points()\y>maxy:maxy=points()\y:EndIf
    Wend
  EndIf
 
 
  For cy=miny To maxy
    y=cy
    oddnodes=#False
    ;ClearList(nodes())
    ;LastElement(points())
    iNodes=-1
    x1=points()\x
    y1=points()\y
    ForEach points()
      x2=points()\x
      y2=points()\y
      If ((y2<Y) And y1>=Y) Or (y1<Y And y2>=Y)
        iNodes+1
        ;AddElement(nodes())
        nodes(iNodes)=(x2+(Y-y2) / (y1-y2) * (x1-x2))
      EndIf
      x1=x2
      y1=y2
    Next
    If iNodes>-1
      nodes(iNodes+1)=nodes(iNodes)
      SortArray(nodes(),#PB_Sort_Ascending,0,iNodes)
      For i=0 To iNodes Step 2
       
        If spr<>#PB_Any
          startx=sprxmid+ nodes(i)-midx
          width=nodes(i+1)-nodes(i)+1
          offx=0
          If startx<0
            offx=-startx
            width-offx
            startx=0
          EndIf
         
          starty=sprymid+y-midy
          If starty>=0 And starty<SprWidth And startx<SprWidth And width>0
            If offx>0
              ClipSprite(spr,1,1,1,1)
              ZoomSprite(spr,offx+1,1)             
              DisplayTransparentSprite(spr,nodes(i),y)
              ZoomSprite(spr,#PB_Default,#PB_Default)
              ClipSprite(spr,#PB_Default,#PB_Default,#PB_Default,#PB_Default) 
             
            EndIf
            If startx+width>SprWidth
              width2=startx+width-SprWidth
              ClipSprite(spr,1,1,1,1)
              ZoomSprite(spr,width2,1)
              DisplayTransparentSprite(spr,nodes(i)+offx+width-width2,y)
              ZoomSprite(spr,#PB_Default,#PB_Default)
              ClipSprite(spr,#PB_Default,#PB_Default,#PB_Default,#PB_Default) 
            EndIf 
           
            ClipSprite(spr,
                       startx,
                       starty,
                       width,
                       1)
            DisplayTransparentSprite(spr,nodes(i)+offx,y)
            ClipSprite(spr,#PB_Default,#PB_Default,#PB_Default,#PB_Default) 
           
          Else
            ClipSprite(spr,1,1,1,1)
            ZoomSprite(spr,nodes(i+1)-nodes(i)+1,1)
            DisplayTransparentSprite(spr,nodes(i),y)
            ZoomSprite(spr,#PB_Default,#PB_Default)
            ClipSprite(spr,#PB_Default,#PB_Default,#PB_Default,#PB_Default) 
           
          EndIf
        Else
          LineXY(nodes(i),Y,nodes(i+1),y,color)
        EndIf
      Next
    EndIf
  Next
EndProcedure

If InitSprite() = 0 Or InitKeyboard() = 0 Or InitMouse() = 0:MessageRequester("Error", "Can't open the sprite system", 0):End:EndIf
If OpenWindow(0, 0, 0,800, 600,"lighting", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)=0:MessageRequester("Error", "Can't open windowed screen!", 0):EndIf
If OpenWindowedScreen(WindowID(0), 0, 0, 800, 600, 0, 0, 0,#PB_Screen_NoSynchronization)=0:MessageRequester("Error", "Can't open windowed screen!", 0):EndIf 

Structure seg
  *pt1.pt
  *pt2.pt
  DoDelete.d
EndStructure
Structure xy
  x.d
  y.d
EndStructure
Structure ray
  a.xy
  b.xy
EndStructure
Structure pt
  x.d
  y.d
  angle.d
  *seg.seg
  *startseg.seg
  *endseg.seg
EndStructure

Global NewList pt.pt()
Global NewList Seg.seg()
NewList *segs.seg()
NewList ligne.pippoint()

#MaxDistance=10000.0

Procedure.d Intersection(*ray.ray,*seg.seg)
  Protected r_dx.d,r_dy.d,s_dx.d,s_dy.d
  Protected t2.d,t1.d
  Protected r_mag.d,s_mag.d
 
  r_dx.d = *ray\b\x-*ray\a\x
  r_dy.d = *ray\b\y-*ray\a\y
  s_dx.d = *seg\pt2\x-*seg\pt1\x
  s_dy.d = *seg\pt2\y-*seg\pt1\y
  T2.d = (r_dx*(*seg\pt1\y-*ray\a\y) + r_dy*(*ray\a\x-*seg\pt1\x))/(s_dx*r_dy - s_dy*r_dx);
  If T2<0 Or T2>1:ProcedureReturn #MaxDistance:EndIf                                      ;
 
  T1.d = (*seg\pt1\x+s_dx*T2-*ray\a\x)/r_dx;
  If T1<0 Or IsInfinity(t1):ProcedureReturn #MaxDistance:EndIf
 
  ProcedureReturn t1
EndProcedure

Procedure AddSegment(x1,y1,x2,y2)
  AddElement(seg()):;seg()\x1=x1:seg()\y1=y1:seg()\x2=x2:seg()\y2=y2
 
  AddElement(pt())
  pt()\x=x1:pt()\y=y1
  pt()\seg=@seg()
  seg()\pt1=@pt()
 
  AddElement(pt())
  pt()\x=x2:pt()\y=y2
  pt()\seg=@seg()
  seg()\pt2=@pt()
 
EndProcedure

Define i,ii, size, rx,ry,oldmili
Define x.d,y.d
Define an
Define *oldseg,segcount,*curseg,closest.d,retour.d
Define oldAngle.d,angle.d
Define modedebug.i=0
Define f.d=0.0001
Define Ray.ray
Define Segment.ray
Define LightMaskFlicker,LightMaskFlickerTimer
Define LightMaskFlickerDX.d,LightMaskFlickerDy.d

CreateImage(0,800,600,32)
CreateSprite(0,800,600)
CreateSprite(1,450,450,#PB_Sprite_AlphaBlending)
CreateSprite(2,450,450,#PB_Sprite_AlphaBlending)


;-Draw Lightning-Mask 1
StartDrawing(ImageOutput(0))
DrawingMode(#PB_2DDrawing_Gradient|#PB_2DDrawing_AllChannels)
BackColor(RGBA(0,0,0,0));mid
GradientColor(0.4,RGBA(0,0,0,50))
GradientColor(0.6,RGBA(0,0,0,200))
FrontColor(RGBA(0,0,0,255))
CircularGradient(225,225,200)
Box(0,0,800,600)
StopDrawing()

StartDrawing(SpriteOutput(1))
DrawingMode(#PB_2DDrawing_AllChannels)
DrawImage(ImageID(0),0,0)
StopDrawing()

;-Draw Lightning-Mask 1
StartDrawing(ImageOutput(0))
DrawingMode(#PB_2DDrawing_Gradient|#PB_2DDrawing_AllChannels)
BackColor(RGBA(0,0,0,0));mid
GradientColor(0.4,RGBA(0,0,0,60))
GradientColor(0.6,RGBA(0,0,0,210))
FrontColor(RGBA(0,0,0,255))
CircularGradient(225,225,201)
Box(0,0,800,600)
StopDrawing()

StartDrawing(SpriteOutput(2))
DrawingMode(#PB_2DDrawing_AllChannels)
DrawImage(ImageID(0),0,0)
StopDrawing()


;-Draw Background Image
StartDrawing(ImageOutput(0))
DrawingMode(#PB_2DDrawing_Gradient)
BackColor($000088)
GradientColor(0.4, $008888)
GradientColor(0.6, $888800)
FrontColor($880000)

CircularGradient(400,300,450)
Box(0,0,800,600)

DrawingMode(#PB_2DDrawing_Default)
StopDrawing()

;-Create "Shadow-Level"
;external box// Fenêtre englobante
Addsegment(-1,-1,800,-1)
addsegment(800,-1,800,600)
Addsegment(800,600,-1,600)
Addsegment(-1,600,-1,-1)
;random squares// carrés aléatoires
CompilerIf #False
  For i=1 To 400
    size=Random(50,10)
    rx=Random(750,50)
    ry=Random(550,50)
    Addsegment(rx,ry,rx+size,ry)
    Addsegment(rx+size,ry,rx+size,ry+size)
    Addsegment(rx+size,ry+size,rx,ry+size)
    Addsegment(rx,ry+size,rx,ry)
  Next i
CompilerElse
  For i=1 To 400
    size=Random(50,10)
    rx=Random(750,50)
    ry=Random(550,50)
    Addsegment(rx,ry,rx+Random(50,0)-25,ry+Random(50,0)-25)
  Next i
CompilerEndIf

;One Circle
For an=0 To 359 Step 36
  AddSegment(200+20*Cos(Radian(an)),200+20*Sin(Radian(an)),200+20*Cos(Radian(an+36)),200+20*Sin(Radian(an+36)))
Next an


MouseLocate(230,202)

Repeat
  Repeat:Until WindowEvent()=0:Delay(1)
  FlipBuffers():ExamineKeyboard():ExamineMouse():
  x.d=MouseX():y.d=MouseY()
  oldmili=ElapsedMilliseconds()
 
  If KeyboardReleased(#PB_Key_Space):modedebug=~modedebug:EndIf
  If KeyboardPushed(#PB_Key_Left)
    x-1
    MouseLocate(x,y)
  EndIf
  If KeyboardPushed(#PB_Key_Right)
    x+1
    MouseLocate(x,y)
  EndIf
  If KeyboardPushed(#PB_Key_Up  )
    y-1
    MouseLocate(x,y)
  EndIf
  If KeyboardPushed(#PB_Key_Down)
    y+1
    MouseLocate(x,y)
  EndIf
 
  If ElapsedMilliseconds()>LightMaskFlickerTimer
    LightMaskFlickerTimer=ElapsedMilliseconds()+4000/30
    LightMaskFlicker!1
    LightMaskFlickerDX=(Random(2,0)-1)/5
    LightMaskFlickerDy=(Random(2,0)-1)/5
  EndIf
  x+LightMaskFlickerDX
  y+LightMaskFlickerDy
 
  ClearList(ligne())
 
  ; Get all angles
  ForEach pt()
    angle.d=ATan2(pt()\x-x,pt()\y-y)
    pt()\angle.d=angle
  Next
  SortStructuredList(pt(),#PB_Sort_Ascending,OffsetOf(pt\angle),#PB_Double)
 
  ; seg-angle-sort and find activ segments
  ClearList (*segs())
  Define a1.d,a2.d
  ForEach seg()   
    seg()\DoDelete=#False
   
    a1=seg()\pt1\angle
    a2=seg()\pt2\angle
   
    If (a2<a1 And a1-a2<#PI) Or (a2>a1 And a2-a1>#PI)
      seg()\pt2\startseg=@seg()
      seg()\pt2\endseg=0
      seg()\pt1\startseg=0
      seg()\pt1\endseg=@seg()
    Else
      seg()\pt2\startseg=0
      seg()\pt2\endseg=@seg()
      seg()\pt1\startseg=@seg()
      seg()\pt1\endseg=0
    EndIf   
    If a1-a2>#PI Or a2-a1>#PI
      AddElement(*segs())
      *segs()=@seg()
    EndIf
  Next
 
  ;Calculate rays
  *oldseg=0:segcount=0
 
  FirstElement(pt())
  Define DoLoop=#True
  Define ptAngle.d
 
  ;Segment-Managment
  While DoLoop
    ptAngle=pt()\angle
    Repeat
      ;add new segments
      If pt()\startseg
        AddElement(*segs())
        *segs()=pt()\startseg
      EndIf
      ;mark segments to die
      If pt()\endseg
        pt()\endseg\DoDelete=#True
      EndIf
     
      If NextElement(pt())
        If pt()\angle>ptAngle+f
          Break
        EndIf       
      Else
        DoLoop=#False
        Break
      EndIf     
    ForEver
   
    ;Calculate 2 Rays
    For ii=-1 To 1 Step 2
      angle.d=ptangle+f*ii
      ray\a\x=x:ray\a\y=y
      ray\b\x=Cos(angle)+x:ray\b\y=Sin(angle)+y
     
      closest=#MaxDistance
     
      ForEach *segs()
        retour=Intersection(@ray,*segs())
        If retour=#MaxDistance:Continue:EndIf
        If retour<closest
          closest=retour
          *curseg=*segs()
        EndIf
       
      Next
     
      If closest=#MaxDistance:Continue:EndIf
     
      rx=x+(ray\b\x-x) * closest
      ry=y+(ray\b\y-y) * closest
      If *oldseg=0 Or ligne()\x<>rx Or ligne()\y<>ry
        If *oldseg<>*curseg
          AddElement(ligne())
          *oldseg=*curseg
          segcount=0
        Else
          If segcount=0
            AddElement(ligne())
          EndIf 
          segcount+1
        EndIf
       
        ligne()\x=rx
        ligne()\y=ry
      EndIf
    Next
   
    ;Remove unneeded segments
    ForEach *segs()
      If *segs()\DoDelete
        *segs()\DoDelete=#False
        DeleteElement(*segs())
      EndIf
    Next
   
  Wend
 
 
  ;Drawing Background
 
  StartDrawing(ScreenOutput())
  DrawImage(ImageID(0),0,0)
  ForEach seg()
    LineXY(seg()\pt1\x,seg()\pt1\y,seg()\pt2\x,seg()\pt2\y,RGB(255,0,0))
  Next
  StopDrawing()
 
  ;Draw light-mask
  If modedebug=0
   
    FilledPolygon(ligne(),#Black,Int(x),Int(y),1+LightMaskFlicker)
  EndIf
 
  ;calculate shadow-mask
  StartDrawing(SpriteOutput(0))
  If modedebug=0
    Box(0,0,800,600,RGB(1,1,1))
    FilledPolygon(ligne(),#Black)
  Else
    Box(0,0,800,600,RGB(0,0,0))
    ForEach ligne()
      LineXY(x,y,ligne()\x,ligne()\y,RGB(0,255,0))
      Circle(ligne()\x,ligne()\y,2,RGB(0,255,0))
    Next
  EndIf
  StopDrawing()
 
  ;draw shadow-mask
  DisplayTransparentSprite(0,0,0)
 
  ;draw HUD
  StartDrawing(ScreenOutput())
  Circle(MouseX(),MouseY(),5,RGB(255,0,0))
  DrawText(0,0,"Press [SPACE] "+Right("0000"+Str(ElapsedMilliseconds()-oldmili),4)+"s polygon:"+ListSize(ligne())+" "+x+" "+y)
 
  StopDrawing()
 
 
Until KeyboardPushed(#PB_Key_Escape)

_________________
Il y a deux méthodes pour écrire des programmes sans erreurs. Mais il n’y a que la troisième qui marche.
Version de PB : 5.45LTS - 32 bits


Haut
 Profil  
Répondre en citant le message  
Afficher les messages postés depuis:  Trier par  
Poster un nouveau sujet Répondre au sujet  [ 16 messages ]  Aller à la page 1, 2  Suivante

Heures au format UTC + 1 heure


Qui est en ligne

Utilisateurs parcourant ce forum: Aucun utilisateur enregistré et 1 invité


Vous ne pouvez pas poster de nouveaux sujets
Vous ne pouvez pas répondre aux sujets
Vous ne pouvez pas éditer vos messages
Vous ne pouvez pas supprimer vos messages

Rechercher:
Aller à:  

 


Powered by phpBB © 2008 phpBB Group | Traduction par: phpBB-fr.com
subSilver+ theme by Canver Software, sponsor Sanal Modifiye