Seite 1 von 1

Blitz zeichnen

Verfasst: 23.01.2007 15:40
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

Verfasst: 23.01.2007 18:12
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 

Verfasst: 24.01.2007 10:04
von wasser
warum so umständlich, nimmst ein sprite, kannste auch zoomen und drehen und farbe verändern.

wie in der wirklichen natur.

Verfasst: 24.01.2007 11:45
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 :)

Verfasst: 24.01.2007 11:51
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.

Verfasst: 24.01.2007 12:00
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.

Verfasst: 24.01.2007 15:40
von Scarabol
Könnte man vielleicht noch ne Option einbauen, die es erlaubt die Amplitude einzustellen?

Verfasst: 24.01.2007 16:07
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 

Verfasst: 25.01.2007 10:19
von dige
Coole Wirkung!

Verfasst: 25.01.2007 10:37
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)