Seite 1 von 2

Wie Game of Life optimieren?

Verfasst: 07.01.2008 20:42
von Gubbie247
Hallo.
Ich hab heute mal wieder ein Game of Life geschrieben, das aber sehr langsam läuft. Hat jemand Vorschläge, da zu optimieren?

Code: Alles auswählen

InitSprite()
InitKeyboard()
InitMouse()

#bb=1280
#bh=800
breite.w=10
w=#bb/breite
h=#bh/breite
array=0
Dim f(w,h,1)
;Dim f2(w,h)
OpenScreen(#bb,#bh,16,"")
For y = 0 To h
  For x =0 To w
    f(x,y,array)=0;Random(1) 
  Next
Next
;- bild
CreateSprite(0,breite,breite,0)
StartDrawing(SpriteOutput(0))
Box(0,0,breite,breite,RGB(13, 27, 24))
StopDrawing()
#maus=1
CreateSprite(#maus,11,16) 
StartDrawing(SpriteOutput(#maus)) 
FrontColor(RGB(20,0,0)) 
BackColor(RGB(0,0,0)) 
LineXY(0,0,0,15) 
LineXY(1,15,5,11) 
LineXY(5,11,11,11) 
LineXY(11,11,0,0) 
FillArea(2,5,RGB(20,0,0),RGB(20,0,0)) 
TransparentSpriteColor(#maus,RGB(0,0,0)) 
StopDrawing() 

Procedure bound(i.w,a.w,b.w)
    If i<a
      i+b
    EndIf
    If i>b
      i-b
    EndIf
    ProcedureReturn i
EndProcedure
Repeat
  
  ExamineKeyboard()
  maus = MouseButton(1)
  ExamineMouse()
  ClearScreen(RGB(255,255,255))
  For y = 0 To h
    For x =0 To w
      If f(x,y,array)
        DisplaySprite(0,x*breite,y*breite)
      EndIf
      If g
      livingaround=0
      livingaround+f(bound(x-1,0,w),bound(y-1,0,h),array)
      livingaround+f(bound(x,0,w),bound(y-1,0,h),array)
      livingaround+f(bound(x+1,0,w),bound(y-1,0,h),array)
      livingaround+f(bound(x-1,0,w),bound(y,0,h),array)
      livingaround+f(bound(x+1,0,w),bound(y,0,h),array)
      livingaround+f(bound(x-1,0,w),bound(y+1,0,h),array)
      livingaround+f(bound(x,0,w),bound(y+1,0,h),array)
      livingaround+f(bound(x+1,0,w),bound(y+1,0,h),array)
      
      If (livingaround=2  And f(x,y,array)=1) Or livingaround=3
        f(x,y,1-array)=1
      Else
        f(x,y,1-array)=0   
      EndIf
    EndIf
    Next
  Next
  If g
    array=1-array
  EndIf
  DisplayTransparentSprite(#maus,MouseX(),MouseY())

 
If KeyboardReleased(57)
  g=1-g
EndIf
If MouseButton(1) 
  If KeyboardPushed(#PB_Key_N)
    f(MouseX()/breite,MouseY()/breite, array)=0
  Else
    f(MouseX()/breite,MouseY()/breite, array)=1
  EndIf
EndIf
If KeyboardPushed(#PB_Key_B)
  For i = 0 To w*h/100
    f(Random(w),Random(h),array)=1
  Next
EndIf
  FlipBuffers()
Until KeyboardPushed(1)

Verfasst: 07.01.2008 20:48
von Andreas_S

Code: Alles auswählen

Repeat
 
  ExamineKeyboard()
  maus = MouseButton(1)
  ExamineMouse()
  ClearScreen(RGB(255,255,255))
  For y = 0 To h
    For x =0 To w
      If f(x,y,array)
        DisplaySprite(0,x*breite,y*breite)
      EndIf
      If g
      livingaround=0
      livingaround+f(bound(x-1,0,w),bound(y-1,0,h),array)
      livingaround+f(bound(x,0,w),bound(y-1,0,h),array)
      livingaround+f(bound(x+1,0,w),bound(y-1,0,h),array)
      livingaround+f(bound(x-1,0,w),bound(y,0,h),array)
      livingaround+f(bound(x+1,0,w),bound(y,0,h),array)
      livingaround+f(bound(x-1,0,w),bound(y+1,0,h),array)
      livingaround+f(bound(x,0,w),bound(y+1,0,h),array)
      livingaround+f(bound(x+1,0,w),bound(y+1,0,h),array)
     
      If (livingaround=2  And f(x,y,array)=1) Or livingaround=3
        f(x,y,1-array)=1
      Else
        f(x,y,1-array)=0   
      EndIf
    EndIf
    Next
  Next
  If g
    array=1-array
  EndIf
  DisplayTransparentSprite(#maus,MouseX(),MouseY())

 
If KeyboardReleased(57)
  g=1-g
EndIf
If MouseButton(1)
  If KeyboardPushed(#PB_Key_N)
    f(MouseX()/breite,MouseY()/breite, array)=0
  Else
    f(MouseX()/breite,MouseY()/breite, array)=1
  EndIf
EndIf
If KeyboardPushed(#PB_Key_B)
  For i = 0 To w*h/100
    f(Random(w),Random(h),array)=1
  Next
EndIf
  FlipBuffers()
Until KeyboardPushed(1) 

in der hauptschleife eine 2-dimensionale For ?!
ein wunder das das läuft :lol:

Verfasst: 07.01.2008 20:51
von Gubbie247
Andreas_S hat geschrieben:

in der hauptschleife eine 2-dimensionale For ?!
ein wunder das das läuft :lol:
warum? durch die zellen muss man doch so oder so durch?

Verfasst: 07.01.2008 20:59
von Andreas_S
puh...

der code hat einen relativ argen syntax und mache variablen haben auch keinen aussagekräftigen namen...

vil. mach ich mir die mühe und geh das mal durch...


Grüße Andreas

Verfasst: 07.01.2008 21:09
von Gubbie247
nochmal kommentiert:

Code: Alles auswählen

InitSprite()
InitKeyboard()
InitMouse()

#bb=1280
#bh=800
breite.w=10 ;breite der zellen
w=#bb/breite ;breite des felde
h=#bh/breite ;hoehe des feldes
array=0 ;welches feld wird verwendet? 1 oder 0
Dim f(w,h,1);das feld
OpenScreen(#bb,#bh,16,"")
For y = 0 To h
  For x =0 To w
    f(x,y,array)=0;Random(1) 
  Next
Next
;- bild
CreateSprite(0,breite,breite,0)
StartDrawing(SpriteOutput(0))
Box(0,0,breite,breite,RGB(13, 27, 24))
StopDrawing()
#maus=1 ; das mausbild
CreateSprite(#maus,11,16) 
StartDrawing(SpriteOutput(#maus)) 
FrontColor(RGB(20,0,0)) 
BackColor(RGB(0,0,0)) 
LineXY(0,0,0,15) 
LineXY(1,15,5,11) 
LineXY(5,11,11,11) 
LineXY(11,11,0,0) 
FillArea(2,5,RGB(20,0,0),RGB(20,0,0)) 
TransparentSpriteColor(#maus,RGB(0,0,0)) 
StopDrawing() 

Procedure bound(i.w,a.w,b.w) ; begrenzung des feldes/ein rand kommt am anderen raus
    If i<a
      i+b
    EndIf
    If i>b
      i-b
    EndIf
    ProcedureReturn i
EndProcedure
Repeat
  
  ExamineKeyboard()
  maus = MouseButton(1)
  ExamineMouse()
  ClearScreen(RGB(255,255,255))
  For y = 0 To h
    For x =0 To w
      If f(x,y,array) ; zelle anzeigen
        DisplaySprite(0,x*breite,y*breite)
      EndIf
      If g ; wenn gelebt wird
      livingaround=0
      livingaround+f(bound(x-1,0,w),bound(y-1,0,h),array)
      livingaround+f(bound(x,0,w),bound(y-1,0,h),array)
      livingaround+f(bound(x+1,0,w),bound(y-1,0,h),array)
      livingaround+f(bound(x-1,0,w),bound(y,0,h),array)
      livingaround+f(bound(x+1,0,w),bound(y,0,h),array)
      livingaround+f(bound(x-1,0,w),bound(y+1,0,h),array)
      livingaround+f(bound(x,0,w),bound(y+1,0,h),array)
      livingaround+f(bound(x+1,0,w),bound(y+1,0,h),array)
      
      If (livingaround=2  And f(x,y,array)=1) Or livingaround=3 ;regeln werden angewendet
        f(x,y,1-array)=1
      Else
        f(x,y,1-array)=0   
      EndIf
    EndIf
    Next
  Next
  If g ;wenn gelebt wird, wird das array jedes mal gewechselt
    array=1-array
  EndIf
  DisplayTransparentSprite(#maus,MouseX(),MouseY())

 
If KeyboardReleased(57)
  g=1-g
EndIf
If MouseButton(1) ;zellen setzen
  If KeyboardPushed(#PB_Key_N) 
    f(MouseX()/breite,MouseY()/breite, array)=0
  Else
    f(MouseX()/breite,MouseY()/breite, array)=1
  EndIf
EndIf
If KeyboardPushed(#PB_Key_B) ;zufällig zellen verteilen
  For i = 0 To w*h/100
    f(Random(w),Random(h),array)=1
  Next
EndIf
  FlipBuffers()
Until KeyboardPushed(1)

Verfasst: 07.01.2008 21:23
von STARGÅTE
es läuft so langsam weil du jedesmal die kleines Quadraten zeichnen lässt.

Besser wäre es hier, das du dir ein leeres Screengroßes Sprites erstellst, und darauf zeichnest, und dies dann anzeigst.

Dann wird immer nur ein Sprite angezeigt und veränderungen an dem Bild werden auf dem Sprite Durchgeführt. Denn diese muss du ja nicht immer machen, sondern nur dann wenn sich wirklich was ändert

Verfasst: 07.01.2008 22:16
von PureLust
STARGÅTE hat geschrieben:es läuft so langsam weil du jedesmal die kleines Quadraten zeichnen lässt.
Naja .... soooo langsam wird's duch die Quadrate auch wieder nicht (auch wenn Sprites den Aufbau natürlich wesentlich schneller machen würden).

Die Hauptbremse ist jedoch die Limitierung auf rund 60-FPS durch FlipBuffers().
Mach aus dem "FlipBuffers()" einfach ein "FlipBuffers(0)" und es sollte (zumindest auf einigermassen modernen PCs) erheblich flüssiger ablaufen.

Greetz, PL.

Verfasst: 07.01.2008 22:25
von NicTheQuick
Ich hab das ganze mal etwas abgeändert und die 'bound()'-Procedure
rausgeworfen. Das war nämlich die eigentliche Geschwindigkeitsbremse.

Außerdem habe ich alle Variablen als Long deklariert, was nochmal einen
Geschwindigkeitsvorteil mit sich bringt.

Unter PB Linux läuft es jetzt einwandfrei und recht schnell.

Code: Alles auswählen

InitSprite()
InitKeyboard()
InitMouse()

Global bb.l, bh.l, w.l, h.l, breite.l, array.l
bb = 800
bh = 600
breite.l = 10
w = bb / breite - 1
h = bh / breite - 1
array = 0
Dim f(w, h, 1)
If Not OpenWindow(0, 0, 0, bb, bh, "Test") : End : EndIf
If Not OpenWindowedScreen(WindowID(0), 0, 0, bb, bh, 0, 0, 0) : End : EndIf
If #PB_Compiler_OS = #PB_OS_Linux
  HideWindow(0, 1)
EndIf

;- bild
If CreateSprite(0, breite, breite, 0)
  StartDrawing(SpriteOutput(0))
    Box(0, 0, breite, breite, RGB(13, 27, 24))
  StopDrawing()
EndIf

#maus = 1
If CreateSprite(#maus, 11, 16)
  StartDrawing(SpriteOutput(#maus))
    FrontColor(RGB(20, 0, 0))
    BackColor(RGB(0, 0, 0))
    LineXY(0, 0, 0, 15)
    LineXY(1, 15, 5, 11)
    LineXY(5, 11, 11, 11)
    LineXY(11, 11, 0, 0)
    FillArea(2, 5, RGB(20, 0, 0), RGB(20, 0, 0))
    TransparentSpriteColor(#maus, RGB(0, 0, 0))
  StopDrawing()
EndIf

Repeat
  ClearScreen(RGB(255, 255, 255))
  
  ExamineKeyboard()
  ExamineMouse()
  
  For y = 0 To h
    ym = y - 1
    yp = y + 1
    If ym < 0 : ym = h : EndIf
    If yp > h : yp = 0 : EndIf
    For x = 0 To w
      xm = x - 1
      xp = x + 1
      If xm < 0 : xm = w : EndIf
      If xp > w : xp = 0 : EndIf
      If f(x, y, array)
        DisplaySprite(0, x * breite, y * breite)
      EndIf
      If g
        livingaround = f(xm, ym, array)
        livingaround + f( x, ym, array)
        livingaround + f(xp, ym, array)
        livingaround + f(xm,  y, array)
        livingaround + f(xp,  y, array)
        livingaround + f(xm, yp, array)
        livingaround + f( x, yp, array)
        livingaround + f(xp, yp, array)
       
        If livingaround = 3 Or (livingaround = 2 And f(x, y, array))
          f(x, y, array ! 1) = 1
        Else
          f(x, y, array ! 1) = 0   
        EndIf
      EndIf
    Next
  Next
  If g
    array ! 1
  EndIf
  DisplayTransparentSprite(#maus, MouseX(), MouseY())
  
  If KeyboardReleased(#PB_Key_R) ;RUN
    g ! 1
  EndIf
  
  If MouseButton(1)
    If KeyboardPushed(#PB_Key_N) ;NEGATE DRAWING
      f(MouseX() / breite, MouseY() / breite, array) = 0
    Else
      f(MouseX() / breite, MouseY() / breite, array) = 1
    EndIf
  EndIf
  If KeyboardPushed(#PB_Key_S) ;SHUFFLE
    For i = 0 To w * h / 100
      f(Random(w), Random(h), array)=1
    Next
  EndIf
  FlipBuffers(0)
Until KeyboardPushed(#PB_Key_Escape) Or WindowEvent() = #PB_Event_CloseWindow
///Edit:
@Gubbie247:
Gewöhn dir bitte an die vordefinierten Konstanten zu benutzen. Ich habe nämlich nach dem ersten Start dein Programm nicht mehr aus bekommen
außer mit 'kill'.
'KeyboardPushed(1)' funktioniert vielleicht unter Windows, aber nicht unter
Linux, da ist '#PB_Key_Escape' nämlich 27.

Hier findest du übrigens noch ein paar kürzere Codes:
PureContest - #1: PureGolf
Die Codes funktionieren aber nur unter Windows.

Verfasst: 07.01.2008 22:34
von STARGÅTE
will ja nicht meckern, aber ich sehe keine geschwindigkeits Steigerung, sobalt wieder ca 90% schwarze Quadrate sind begint es langsammer zu werden.

EDIT: die Simulation ist flüssiger ! aber nicht der StartScreen


Ich werden heute nacht mal das mit dem ScreenSprite probieren

Verfasst: 07.01.2008 22:51
von Gubbie247
vielen dank jungs, ihr seid echt die besten. Wirklich fein, wie großzügig man hier mit Code ist.

:allright:

Jedoch wär ich manchmal auch dankbar nur Denkanstösse zu erhalten, denn das macht für mich den Spass aus beim Programmieren, Sachen selber auszuknobeln. Vielleicht wie 'guck mal die bound()-Prozedur, die ist wirklich lahm'.

Noch mal vielen Dank, keep up the good fight.