Blitz zeichnen

Für allgemeine Fragen zur Programmierung mit PureBasic.
Benutzeravatar
Scarabol
Beiträge: 1427
Registriert: 30.11.2005 21:00

Blitz zeichnen

Beitrag von Scarabol »

Hallo Leute,

wie kann ich einen Blitz zwischen zwei Punkten zeichnen?
Klinkt erstmal einfach ist es aber aus meiner Sicht nicht, ich bekomm es zwar mit

Code: Alles auswählen

for x = 1 to 100
  plot(x, y, #red)
  y-1+random(2
next
hin das der Blitz an einer bestimmten Stelle startet aber ich weiß nicht wie ich den Zielpunkt genau bestimmen kann. So "tanzt" der Blitz jetzt nach 100 Pixeln immer auf und ab.

Dann hab ich diesen Quellcode ausgegraben und verändert:

Code: Alles auswählen

Global MaxHeight = 100.0

#PIXELS = 1000
Global Dim ALine.f(#PIXELS)
Global mv.f, d.l, max.l

Procedure Split(low.l, high.l)
   Protected m.l
   
   m = (high + low) / 2
   d = high - low
   If d <= 1
      ProcedureReturn 0
   EndIf
   
   mv = (ALine(high) + ALine(low)) / 2.0
   
   ALine(m) = mv - (Random(10000) / 10000.0 - 0.5) * MaxHeight * d / (#PIXELS)
   
   
   Split(m, high)
   Split(low, m)
   
EndProcedure

width = 600
height = 300

PosY = 150

CreateImage(0, width, height)

OpenWindow(0, 200, 200, width, height, "Drawing", #PB_Window_SystemMenu|#PB_Window_ScreenCentered)
CreateGadgetList(WindowID(0))
   ImageGadget(1, 0, 0, width, height, ImageID(0))

SetGadgetState(1, ImageID(0))

Repeat
  
  StartDrawing(ImageOutput(0))
    Box(0,0, width,height, 0) ; Sprite löschen
    
    FrontColor(#White)
    Split(0, #PIXELS)
    For z = 1 To #PIXELS
      LineXY((z-1)*width/#PIXELS, ALine(z-1)+PosY, z*width/#PIXELS, ALine(z)+PosY)
    Next
    
  StopDrawing()
  
  SetGadgetState(1, ImageID(0))
  Delay(10)
Until WindowEvent() = #PB_Event_CloseWindow
Hier trifft der Blitz zwar immer genau einen Punkt, aber ich weiß nicht wie ich diesen Punkt jetzt verändern kann, sodass der Blitz z. B. diagonal verläuft.

Gruß
Scarabol
Abgeschlossen Projekte:
Schreibmaschine, Bildschirmlupe, Wings3DtoOgreMeshConverter
Watch: PureArea

PB-V: 4
WinXP
Benutzeravatar
NicTheQuick
Ein Admin
Beiträge: 8807
Registriert: 29.08.2004 20:20
Computerausstattung: Ryzen 7 5800X, 64 GB DDR4-3200
Ubuntu 24.04.2 LTS
GeForce RTX 3080 Ti
Wohnort: Saarbrücken

Beitrag von NicTheQuick »

Ich hab den Code mal etwas für dich abgeändert.

Ich hoffe du blickst dann noch durch. ;)

Code: Alles auswählen

Global MaxHeight = 200.0

#PIXELS = 100
Global Dim ALine.f(#PIXELS)
Global mv.f, d.l, max.l

Procedure Split(low.l, high.l)
  Protected m.l
  
  m = (high + low) / 2
  d = high - low
  If d <= 1
    ProcedureReturn 0
  EndIf
  
  mv = (ALine(high) + ALine(low)) / 2.0
  
  ALine(m) = mv - (Random(10000) / 10000.0 - 0.5) * MaxHeight * d / (#PIXELS)
  
  
  Split(m, high)
  Split(low, m)
  
EndProcedure

Procedure.f ATan2(x.f, y.f)
  If x => 0
    If y >= 0
      ProcedureReturn ATan(y / x)
    Else
      ProcedureReturn ATan(y / x) + 6.283185307179586477
    EndIf
  Else
    ProcedureReturn ATan(y / x) + 3.141592653589793238
  EndIf
EndProcedure

Procedure DrawFlash(x1.l, y1.l, x2.l, y2.l)
  Protected a.f, l.l, xm.l = x2 - x1, ym.l = y2 - y1
  Protected xf1.f, yf1.f, xf2.f, yf2.f, z.l, px1.f, py1.f, px2.f, py2.f
  
  Split(0, #PIXELS)
  l = Sqr(xm * xm + ym * ym)
  a = ATan2(xm, ym)
  
  xf1 = Cos(a)
  yf1 = Sin(a)
  
  xf2 = Cos(a + 1.570796326794896619)
  yf2 = Sin(a + 1.570796326794896619)
  
  For z = 0 To #PIXELS - 1
    px1 = z * l / #PIXELS
    py1 = ALine(z)
    px2 = (z + 1) * l / #PIXELS
    py2 = ALine(z + 1)
    LineXY(x1 + px1 * xf1 + py1 * xf2, y1 + px1 * yf1 + py1 * yf2, x1 + px2 * xf1 + py2 * xf2, y1 + px2 * yf1 + py2 * yf2)
  Next
  
EndProcedure

Width = 600
Height = 300

CreateImage(0, Width, Height)

OpenWindow(0, 200, 200, Width, Height, "Drawing", #PB_Window_SystemMenu|#PB_Window_ScreenCentered)
CreateGadgetList(WindowID(0))
ImageGadget(1, 0, 0, Width, Height, ImageID(0))

SetGadgetState(1, ImageID(0))

Repeat
  StartDrawing(ImageOutput(0))
  Box(0,0, Width,Height, 0) ; Sprite löschen
  
  FrontColor(#White)
  DrawFlash(300, 150, WindowMouseX(0), WindowMouseY(0))
  
  StopDrawing()
  
  SetGadgetState(1, ImageID(0))
  Delay(10)
Until WindowEvent() = #PB_Event_CloseWindow 
wasser
Beiträge: 125
Registriert: 27.11.2006 21:16

Beitrag von wasser »

warum so umständlich, nimmst ein sprite, kannste auch zoomen und drehen und farbe verändern.

wie in der wirklichen natur.
Benutzeravatar
bobobo
jaAdmin
Beiträge: 3873
Registriert: 13.09.2004 17:48
Kontaktdaten:

Beitrag von bobobo »

In der wirklichen Natur sind Blitze Sprites ??? :)

Ich glaube nicht, dass es jemals einen Blitz gegeben hat der aussieht wie
ein anderer.

Ein Sprite reicht da nicht. Da muss eher ein ganzer Sack voll her sonst
wird' s ganz schnell ganz unnatürlich.

Aber es spricht nichts dagegen obige Malroutine letztlich auf ein Sprite
anzuwenden, für spätere Wiederauflage im weiteren Programmverlauf.

____________
Musste antworten : Bei Blitzen werd ich elektrisch :)
Kaeru Gaman
Beiträge: 17389
Registriert: 10.11.2004 03:22

Beitrag von Kaeru Gaman »

@NTQ

sauber :allright:

..evtl. wärs noch ne sache, die amplitute relativ zum abstand ein wenig anzupassen....


aber das sind ja jetzt blitze gewesen, wie sie im labor auftreten, mit zwei klar definierten polen.
(war ja Scarabols fragestellung, is ja ok)

mich würde jetzt interessieren, mal rumzuprobieren natürliche blitze zu zeichnen,
und zwar die typische form wie sie bei einem wolken-erde blitz auftritt.
Der Narr denkt er sei ein weiser Mann.
Der Weise weiß, dass er ein Narr ist.
Benutzeravatar
bobobo
jaAdmin
Beiträge: 3873
Registriert: 13.09.2004 17:48
Kontaktdaten:

Beitrag von bobobo »

Das macht man am Besten durch eine möglichst genaue Abbildung der
natürlichen Gegenheiten.
So ein Blitz sucht ja immer nur den nächstliegenden größten
Potentialunterscheid. Sollte eigentich kein Riesending sein.
‮pb aktuel 6.2 windoof aktuell und sowas von 10
Ich hab Tinnitus im Auge. Ich seh nur Pfeifen.
Benutzeravatar
Scarabol
Beiträge: 1427
Registriert: 30.11.2005 21:00

Beitrag von Scarabol »

Könnte man vielleicht noch ne Option einbauen, die es erlaubt die Amplitude einzustellen?
Abgeschlossen Projekte:
Schreibmaschine, Bildschirmlupe, Wings3DtoOgreMeshConverter
Watch: PureArea

PB-V: 4
WinXP
Kaeru Gaman
Beiträge: 17389
Registriert: 10.11.2004 03:22

Beitrag von Kaeru Gaman »

das geht über die manipulation der Global MaxHeight

ich hab mal die hauptschleife angepasst für variable amplitude:

Code: Alles auswählen

Repeat 
  MX = WindowMouseX(0)
  MY = WindowMouseY(0)
  dx = 300 - MX
  dy = 150 - MY
  leng = Sqr(dx*dx+dy*dy)
  MaxHeight = leng * 3 / 4

  StartDrawing(ImageOutput(0)) 
  Box(0,0, Width,Height, 0) ; Sprite löschen 
  
  FrontColor(#White)
  DrawFlash(300, 150, MX, MY) 
  
  StopDrawing() 
  
  SetGadgetState(1, ImageID(0)) 
  Delay(10) 
Until WindowEvent() = #PB_Event_CloseWindow 
Der Narr denkt er sei ein weiser Mann.
Der Weise weiß, dass er ein Narr ist.
Benutzeravatar
dige
Beiträge: 1236
Registriert: 08.09.2004 08:53

Beitrag von dige »

Coole Wirkung!
"Papa, ich laufe schneller - dann ist es nicht so weit."
Benutzeravatar
NicTheQuick
Ein Admin
Beiträge: 8807
Registriert: 29.08.2004 20:20
Computerausstattung: Ryzen 7 5800X, 64 GB DDR4-3200
Ubuntu 24.04.2 LTS
GeForce RTX 3080 Ti
Wohnort: Saarbrücken

Beitrag von NicTheQuick »

Wenn man einen etwas bläulichen Blitz haben will, empfehle ich folgenden
RGB-Wert als Parameter in LineXY einzugeben:
RGB(255 - Random(127), 255 - Random(127), 255)
Antworten