PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Fragen zu Performance



Cornix
13.06.2010, 22:43
Schönen guten abend, erneut habe ich eine kleine Frage zur performance folgender Programmierung:
Um die Animationen meiner Figuren besser unter Kontrolle zu haben habe ich eine Klasse erstellt welche ich "Model" nenne. Dieses Model speichert eine Bilddatei, zum Beispiel "001-Fighter01" und dazu einige verschiedene Rects(x,y,width,height).
Das Model besitzt eine Anzahl an Abfragen welche jeweils ein Bitmap liefern, nämlich einen Ausschnitt aus dem im Model gespeicherten Ur-Bitmaps.
hier ein Beispiel:


def initialize
@bitmap = RPG::Cache.character("001-Fighter01",0)
@stand = [1,
Rect.new(0,0,32,48) ,
Rect.new(0,49,32,48) ,
Rect.new(0,97,32,48) ,
Rect.new(0,144,32,48)
]
end

def animation(animation_name,direction=1)
return animation_stand(direction) if animation_name == "stand"
end

def animation_stand(direction)
bitmap = Bitmap.new(@stand[direction].width,@stand[direction].height)
bitmap.blt(0,0,@bitmap,@stand[direction])
return bitmap
endIn jedem Frame würde ein Sprite nun die zu ihm gehörige Model-Instanz nach einem Bitmap für die zu spielende Animation abfragen. Beispiel:

def update
self.bitmap = @character.model.animation(@character.animation)
self.bitmap.hue_change(@character.hue)
@width = self.bitmap.width
@height = self.bitmap.height
self.ox = @width/2
self.oy = @height/2
self.src_rect.set(0,0,@width,@height)
self.x = @character.x
self.y = @character.y
self.z = @character.z
endIst dies effektiv? Beziehungsweise, würde es zu großen Performance einbußen führen für eine größere Anzahl von Sprites?
Im ursprünglichen RMXP standard Sprite wird ja das Bitmap für den Sprite nur sehr selten gewechselt, in diesem Fall würde ich in jedem Frame für jeden Sprite ein neues Bitmap abfragen und setzen.

XGazudin
14.06.2010, 08:25
Ich bin da kein Experte, aber ich vermute dass das keinen großen Unterschied machen wird.
Der eigentliche Rechenaufwand denke ich besteht im Blocktransfer, unabhängig davon auf welche Bitmap zu dem Zeitpunkt gezeigt wird.
Da der Hauptunterschied bei dir darin besteht dass du den Zeiger auf die Bitmap, von der du einen Teil kopieren möchtest, öfters änderst, meine ich sollte das kein größerer Aufwand sein als die RMXP standardmethode.

Und selbst wenn das einen Unterschied machen sollte, vermute ich würde der nur auf älteren Rechnern irgendwie mit bloßem Auge merkbar sein....wenn überhaupt.

Cornix
14.06.2010, 12:53
Vielen Dank für die Anteilnahme, ich habe dieses System natürlich bereits selbst getestet. Es geht mir hier nicht um tatsächliche Performance einbußen sondern auch um den theoretischen Teil, sprich ums Prinzip, ist es aufwendiger? Wenn ja, ist es ein erheblicher Unterschied?

Shining Advances
14.06.2010, 13:18
unperformant!
du müllst dir deinen arbeitsspeicher voll, weil du die ganzen bitmaps neu erzeugst und nicht löschst.
bei 40 updates in der sekunde kommt ne menge an datenmüll zusammen.
da kommt, je nach menge der animationen die gleichzeitig abgespielt werden, der gc irgendwann nicht mehr mit.
die folge ist, dass dein spiel abstürzt, weil du keine neuen bitmaps mehr erstellen kannst (auch wenn du noch ram frei hast. weiß aber auch nicht wieso das so ist ._.)

wenn du dir im handbuch/hilfe vom xp die rpg::sprite klasse ansiehst, merkst du, dass dort nur mit src_rect gearbeitet wird. genauso ist es auch bei der sprite_character klasse. enterbrain hätte das nicht gemacht, wenn sie nicht wüssten, dass es schneller ist, als ständig neue bitmaps zu erzeugen.

da du in @stand eh schon rects gespeichert hast, kannst du die doch ganz einfach verwenden.
mach im update eher sowas wie:
self.bitmap = @character.model.bitmap
self.src_rect = @character.model.stand[direction]

XGazudin
14.06.2010, 15:46
Dann entschuldige ich mich dafür so daneben gelegen zu haben^^
Wieder was gelernt :O

Cornix
14.06.2010, 20:19
[...]

da du in @stand eh schon rects gespeichert hast, kannst du die doch ganz einfach verwenden.
mach im update eher sowas wie:
self.bitmap = @character.model.bitmap
self.src_rect = @character.model.stand[direction]
Vielen Dank! Natürlich, darauf hätte ich auch selbst kommen können.
Dass die ständige Erstellung neuer Bitmaps anscheinend zu Performance Problemen führt habe ich mit meinen Tests bereits herausgefunden, dass nur eine begrenzte Anzahl erstellt werden darf wusste ich allerdings bisher noch nicht.
Die von dir vorgeschlagene Methode kann allerdings nicht ganz umgesetzt werden, würde ich "self.bitmap = @character.model.bitmap" benutzen könnte ich keinen Hue_Change für die einzelnen Sprites durchführen. Ist aber nicht besonders schwer zu verändern.

Vielen Dank.
Cornix.

-KD-
15.06.2010, 00:49
Wenn du das wirklich brauchst, leg halt für jeden Animationsschritt ein eigenes Bitmap mit dem jeweiligen Ausschnitt und Hue an, speichere es in einen Array und wechsle es immer aus.
Wichtig ist, dass du nicht jedes Mal ein neues Bitmap erstellst und schon gar nicht jedes Mal den Hue neu setzt (das ist nämlich auch sehr aufwendig).

Cornix
15.06.2010, 14:48
Ja, Danke, ich habe es bereits erledigen können, war keine allzu schwere Aufgabe. Jeder Sprite speichert nun ein neues Bitmap und führt einen block transfer mit dem zugehörigen Model.Bitmap durch, die src_rect wird auf die Animationsabhängige Rect gesetzt.

-KD-
15.06.2010, 14:59
Erm, nee, ich dachte du willst innerhalb der Animationsschritte Hue-Changes haben. Wenn du pro Character ein Hue und mehrere Rects hast, dann verwende keine Blocktransfers, sondern die normalen RPG::Cache Methoden. Denen kannst du den Hue Wert mitgeben und die kümmern sich selbstständig um das Cachen der Bitmaps.