Wie Game of Life optimieren?

Anfängerfragen zum Programmieren mit PureBasic.
Gubbie247
Beiträge: 32
Registriert: 10.10.2004 13:23

Wie Game of Life optimieren?

Beitrag 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)
Andreas_S
Beiträge: 787
Registriert: 14.04.2007 16:48
Wohnort: Wien Umgebung
Kontaktdaten:

Beitrag 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:
Gubbie247
Beiträge: 32
Registriert: 10.10.2004 13:23

Beitrag 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?
Andreas_S
Beiträge: 787
Registriert: 14.04.2007 16:48
Wohnort: Wien Umgebung
Kontaktdaten:

Beitrag 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
Gubbie247
Beiträge: 32
Registriert: 10.10.2004 13:23

Beitrag 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)
Benutzeravatar
STARGÅTE
Kommando SG1
Beiträge: 7031
Registriert: 01.11.2005 13:34
Wohnort: Glienicke
Kontaktdaten:

Beitrag 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
PB 6.01 ― Win 10, 21H2 ― Ryzen 9 3900X, 32 GB ― NVIDIA GeForce RTX 3080 ― Vivaldi 6.0 ― www.unionbytes.de
Aktuelles Projekt: Lizard - Skriptsprache für symbolische Berechnungen und mehr
Benutzeravatar
PureLust
Beiträge: 1145
Registriert: 21.07.2005 00:02
Computerausstattung: Hab aktuell im Grunde nur noch 'nen Lenovo Yoga 2 Pro im Einsatz.
Wohnort: am schönen Niederrhein

Beitrag 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.
[Dynamic-Dialogs] - komplexe dynamische GUIs einfach erstellen
[DeFlicker] - Fenster flimmerfrei resizen
[WinFX] - Window Effekte (inkl. 'durchklickbares' Window)
Benutzeravatar
NicTheQuick
Ein Admin
Beiträge: 8809
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 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.
Benutzeravatar
STARGÅTE
Kommando SG1
Beiträge: 7031
Registriert: 01.11.2005 13:34
Wohnort: Glienicke
Kontaktdaten:

Beitrag 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
PB 6.01 ― Win 10, 21H2 ― Ryzen 9 3900X, 32 GB ― NVIDIA GeForce RTX 3080 ― Vivaldi 6.0 ― www.unionbytes.de
Aktuelles Projekt: Lizard - Skriptsprache für symbolische Berechnungen und mehr
Gubbie247
Beiträge: 32
Registriert: 10.10.2004 13:23

Beitrag 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.
Antworten