Kollisionen verursachen Performanceeinsturz

Übersicht BlitzMax, BlitzMax NG Allgemein

Neue Antwort erstellen

 

Turion87

Betreff: Kollisionen verursachen Performanceeinsturz

BeitragMo, Jul 25, 2011 0:30
Antworten mit Zitat
Benutzer-Profile anzeigen
Hallöchen zusammen,

ich habe nach langer Zeit in vb.net und c# nun auch den Weg in die Spieleprogrammierung gefunden und mich mit einem Tutorial in die wichtigsten Befehle in Blitzmax eingearbeitet. (das war gestern)
Jetzt sollte es mit Learning by Doing weitergehen.

Ich möchte gerne ein Spiel gestalten, in dem es darum geht, aufgebaute Dominosteine umkippen zu lassen.

Also habe ich mir mit Paint eine png "gemalt" in der eine Fallanimation enthalten ist. (test.png)
dann habe ich einen Type "Stone" geschrieben und mir mit entsprechender Methode einige Steine "bauen" lassen.
Durch eine Kollisionsabfrage wars dann auch möglich, die Steine fallen zu lassen. Cool Cool .. ABER: sobald mehrere Steinreihen parallel kippen sollen, kommt es zu Performanceeinbrüchen.

Ich weiß, dass die Lösung mit 5 png's nicht die Beste ist. Vorher hatte ich es auch mit "LoadAnimImage" auf die test.png bezogen. Resultat war dasselbe Sad

Hier ist mal der Quellcode:
Achso und wegen der lustigen for-Schleifen zum Erstellen der Steine bitte auch keine Kommentare Very Happy die sind nur aus Testzwecken so geschrieben ^^

Kurz was zum Code:
Field Direction is dazu da, anzugeben in welche Richtung der Stein kippt. l-links r-rechts - = noch nicht gefallen x-bereitsgefallen
Code: [AUSKLAPPEN]


'-----------------SETUP GAME CONDITIONS--------------------
Global StoneList:TList=CreateList()
Global ScreenW=1024
Global ScreenH=768
Global TDelay= 1
Global Img1:TImage=LoadImage("1.png")
Global Img2:TImage=LoadImage("2.png")
Global Img3:TImage=LoadImage("3.png")
Global Img4:TImage=LoadImage("4.png")
Global Img5:TImage=LoadImage("5.png")

Graphics ScreenW,ScreenH,0
Abstand = 20

Start:TStone = New TStone.Create(Img1,20,50)
Start2:TStone = New TStone.Create(Img1,20,80)
Start3:TStone = New TStone.Create(Img1,20,110)
Start4:TStone = New TStone.Create(Img1,20,140)
Start5:TStone = New TStone.Create(Img1,20,170)
Start6:TStone = New TStone.Create(Img1,20,200)
Start7:TStone = New TStone.Create(Img1,20,230)
Start8:TStone = New TStone.Create(Img1,20,260)
Start9:TStone = New TStone.Create(Img1,20,290)
Start10:TStone = New TStone.Create(Img1,20,320)
Start11:TStone = New TStone.Create(Img1,20,350)
Start12:TStone = New TStone.Create(Img1,20,380)


For s = 2 To 10
   TStone.Create(Img1,s*Abstand,50)
Next

For s = 2 To 20
   TStone.Create(Img1,s*Abstand,80)
Next

For s = 2 To 30
   TStone.Create(Img1,s*Abstand,110)
Next

For s = 2 To 40
   TStone.Create(Img1,s*Abstand,140)
Next

For s = 2 To 50
For s2 = 1 To 10
TStone.Create(Img1,s*Abstand,140+s2*30)
Next

Next

 ' ---------------------MAIN LOOP-------------------------
Repeat
         Cls
         For o:TGameObject=EachIn StoneList
               o.DrawSelf()
               o.UpdateState()
         Next
      If KeyDown(KEY_SPACE) Then Start.Direction = "r"
      If KeyDown(KEY_SPACE) Then Start2.Direction = "r"
      If KeyDown(KEY_SPACE) Then Start3.Direction = "r"
      If KeyDown(KEY_SPACE) Then Start4.Direction = "r"
      If KeyDown(KEY_SPACE) Then Start5.Direction = "r"
      If KeyDown(KEY_SPACE) Then Start6.Direction = "r"
      If KeyDown(KEY_SPACE) Then Start7.Direction = "r"
      If KeyDown(KEY_SPACE) Then Start8.Direction = "r"
      If KeyDown(KEY_SPACE) Then Start9.Direction = "r"
      If KeyDown(KEY_SPACE) Then Start10.Direction = "r"
      If KeyDown(KEY_SPACE) Then Start11.Direction = "r"
      If KeyDown(KEY_SPACE) Then Start12.Direction = "r"
         Flip
Until KeyDown(KEY_ESCAPE) Or AppTerminate()
End


Type TStone Extends TGameObject
   Field DelayTime:Int = TDelay
   Field Direction:String = "-"
   Function Create:TStone(Image:TImage,xstart:Int,ystart:Int)
      Local Stone:TStone=New TStone
      CreateObject(Stone,Image,xstart,ystart)
      ListAddLast StoneList, Stone
      Return Stone
   End Function
   
   Method UpdateState()
         If KeyDown(KEY_RIGHT)
         X :+4
      EndIf
      CheckCollision()
      DelayTime :-1
      If DelayTime<=0 Then
         If Direction = "r" Or Direction = "l" Then
            If Frame < 4 Then
               'Frame=-1
            DrawText Frame, X+10,Y-10
            DelayTime = TDelay
            Frame:+1
            Select Frame
               Case 1
                  Image = Img2
               Case 2
                  Image = Img3
               Case 3
                  Image = Img4
               Case 4
                  Image = Img5
                  Direction = "x"
            End Select
            Else
            DrawText Frame, X+10,Y-10
            Direction = "x"
            EndIf            
         EndIf
      EndIf
      
   End Method
   
  Method CheckCollision()
      For Local g:TStone=EachIn StoneList
        If g.Direction <> "x" Then

      If g<>Self Then
         If g.Direction <> "-" Then
               If ImagesCollide(Self.Image,X,Y,0,g.Image,g.X,g.Y,0)
                  'ListRemove(GameObjectList,g)
             Self.Direction = "r"
               EndIf
         EndIf
      EndIf
        EndIf
    Next
      ResetCollisions()
    End Method
End Type   


Type TGameObject
   Field X:Int = 320
   Field Y:Int = 420
   Field Speed:Int=3
   Field Image:TImage
   Field Frame:Int=0
   Field XScale:Float=1.0
   Field YScale:Float=1.0
   Field Explosion:Int=0
   
   Method DrawSelf()
      SetColor 255,255,255
      SetScale XScale,YScale
      DrawImage Image,X,Y,0
   End Method   
   
   Method UpdateState() Abstract
End Type

Function CreateObject(Obj:TGameObject, Image:TImage,xstart:Int,ystart:Int,scale:Float=1.0)
   Obj.X=xstart
   Obj.Y=ystart
   Obj.XScale=scale
   Obj.YScale=Scale
   Obj.Image=Image
   If Obj.Image=Null
      Print "Not able to load image file. Program aborting"
      End
   EndIf
End Function




Hier ist auch nochmal der Code zum Download, damit ihr sehen könnt, was da nich so läuft: http://www.file-upload.net/dow...o.zip.html

Xeres

Moderator

BeitragMo, Jul 25, 2011 0:59
Antworten mit Zitat
Benutzer-Profile anzeigen
Das liegt vermutlich an ImagesCollide. Pixelgenaue Kollisionsabfragen dauern. Mach erst eine schnelle Rechteck Kollision, und erst wenn die eintrifft wenn nötig etwas exakteres.
Setz' noch an den Anfang des Codes SuperStrict -> erzwingt Deklaration der Variablen, was Fehler vermeidet und verbessert etwas die Performance.
Win10 Prof.(x64)/Ubuntu 16.04|CPU 4x3Ghz (Intel i5-4590S)|RAM 8 GB|GeForce GTX 960
Wie man Fragen richtig stellt || "Es geht nicht" || Video-Tutorial: Sinus & Cosinus
T
HERE IS NO FAIR. THERE IS NO JUSTICE. THERE IS JUST ME. (Death, Discworld)
 

Turion87

BeitragMo, Jul 25, 2011 1:30
Antworten mit Zitat
Benutzer-Profile anzeigen
Danke für die schnelle Antwort.

eine Rechteckkollision..
D.h. aus Stein 1, der nach rechts fällt nehm ich den am weitesten rechten Pixel und generiere daraus ein Rechteck und prüfe das mit den Steinen in meiner Stonelist?

Wenn das Ergebnis positiv ist, dann mach ich eine Pixelgenaue Prüfung?

Meinste das bringt was?
Im Prinzip werden pro Reihe, in der Steine fallen - 5 Prüfungen gemacht. Frame 0 auf 1 1 auf 2 2 auf 3 3 auf 4 und 4 selbst (erst wenn die 4 geprüft wird, wird Direction auf "x" gesetzt und fällt dann nicht mehr.

Mir ist grad ne Idee gekommen, dass ich die 5 Prüfungen auf eine reduzieren könnte, indem ich die Steine mit einem Tag versehe, der kennzeichnet, ob der geprüfte Stein bereits einen anderen angestoßen hat.
Wenn dem so ist, dann braucht der nicht mehr geprüft werden, denn entweder ist der gerade beim Fallen (Frame 1-4) oder er liegt dann um (Frame 4)
Naja werde ich wohl morgen mal testen.

Kannst ja noch kurz schreiben, wie eine Rechteckprüfung/Kollision gemacht wird, wurde bestimmt schon im Forum hier behandelt.

Danke schonmal Smile

Xeres

Moderator

BeitragMo, Jul 25, 2011 2:00
Antworten mit Zitat
Benutzer-Profile anzeigen
Jedes Bild ist ein Rechteck. Wenn zwei Bilder nicht überlappen, kann es auch keine Kollision geben. Mit bekannten Positionen sowie Breite & Höhe sollte das kein Problem sein.
Wenn du von vorn herein noch Steine ausschließen kannst, ist natürlich auch gut.
"Direction" würde ich noch als Integer deklarieren. Stringvergleiche dauern länger, was sich u.U. auch summieren kann - mit Konstanten hältst du den Code trotzdem lesbar.
Funktionen kannst du übrigens auch in den Type Stecken; TypeName.Funktion(...)
Oh, und...
Code: [AUSKLAPPEN]
If KeyDown(KEY_SPACE) Then
   Start.Direction = "r"
   Start2.Direction = "r"
   Start3.Direction = "r"
   '[...]
EndIf

...wäre hübscher. Mit Keyhit funktionierst deshalb nicht (in deiner Version), wie du vielleicht fest gestellt hast, da der Buffer beim ersten Keyhit gelöscht wird und bei den nachfolgenden nicht mehr True zurück gibt.

Nicht vergessen im Forum zu suchen, viele Fragen werden schon mal aufgekommen sein. Ansonsten: Weitermachen & Viel Erfolg.
Win10 Prof.(x64)/Ubuntu 16.04|CPU 4x3Ghz (Intel i5-4590S)|RAM 8 GB|GeForce GTX 960
Wie man Fragen richtig stellt || "Es geht nicht" || Video-Tutorial: Sinus & Cosinus
T
HERE IS NO FAIR. THERE IS NO JUSTICE. THERE IS JUST ME. (Death, Discworld)

M0rgenstern

BeitragMo, Jul 25, 2011 9:20
Antworten mit Zitat
Benutzer-Profile anzeigen
Du könntest, bevor du auf eine Rechteckkollision prüfst, erstmal noch prüfen wie weit zwei Steine voneinander entfernt sind. Das dürfte noch ein wenig schneller sein als die Rechteckkollisionsprüfung. Dann kannst du sagen: Erst wenn zwei Steine eine Entfernung < x haben können sie überhaupt kollidieren und erst dann prüfe ich das auch.

Btw. Gehört das nicht ins Beginners?

Lg, M0rgenstern
 

Turion87

BeitragMo, Jul 25, 2011 9:52
Antworten mit Zitat
Benutzer-Profile anzeigen
eigentlich ist das ja auch nur ne gaaanz simple testversion.
die eigentliche version soll dann nachher ein "raster" oder ein 2d feld im hintergrund haben, wo ich dann eine Zelle sogroß mache, wie eine png, also 32 x 32 und dann könnte ich mir das kollidieren auch sparen, weil wenn in der Zelle x ein Stein steht und in x+1 keiner, brauch ich nicht prüfen, wie morgenstern schon sagte.

komm leider erst morgen zum proggen :/

Midimaster

BeitragMo, Jul 25, 2011 10:04
Antworten mit Zitat
Benutzer-Profile anzeigen
Durch das Einfügen der Bilder in jedes neue Element des Types wird auch viel Speicher verbraten.

Es würde eigentlich genügen die 5 Bilder in ein Array zu speichern und nun nur die Elementnummer im Typ zu verwalten. Die gibt es ja eh schon als "Frame".


BlitzMax: [AUSKLAPPEN]
Global Images:TImage[0]=LoadImage("1.png")
....

TStone.Create( 0 , s*Abstand , 140+s2*30 )
' wobei der erste Parameter dann "Frame" festlegt und "Image" gar nicht mehr gebraucht würde.
.....

If ImagesCollide( Images[Self.Frame] , X , Y , 0 , Images[g.frame] , g.X , g.Y , 0)
.....

DrawImage Images[Self.Frame] , X , Y , 0




Dann sind es für die Grafikkarte wirklich die immer gleichen 5 Bilder und es werden nicht soviele Daten in die Karte geschaufelt.
  • Zuletzt bearbeitet von Midimaster am Mo, Jul 25, 2011 16:39, insgesamt 2-mal bearbeitet

M0rgenstern

BeitragMo, Jul 25, 2011 10:10
Antworten mit Zitat
Benutzer-Profile anzeigen
Ich wüsste trotzdem mal gerne, was genau du mit Zeilen wie der folgenden bezwecken willst:
BlitzMax: [AUSKLAPPEN]
Start6:TStone = New TStone.Create(Img1,20,200) 

Es wundert mich, dass das mit dem New davor überhaupt compiliert. Das New brauchst du gar nicht, das steckt ja schon in deinem Konstruktor mit drin.

Lg, M0rgenstern

Neue Antwort erstellen


Übersicht BlitzMax, BlitzMax NG Allgemein

Gehe zu:

Powered by phpBB © 2001 - 2006, phpBB Group