# Jump-n-Run Auslastung verringern



## lain (17. Jan 2010)

Hey,

Ich hab mir ein kleines Jump-n-run Applet zusammen gebaut. Nur ich denke so wie es momentan aussieht ist das Performance technisch nicht grad das beste.
Meine Map wird aus nem Array an BufferedImages gezeichnet und das aber permanent.. also die komplette Map wird ständig regepainted. 
Und das eigentlich nur damit der Spieler sich auch bewegt. 

Es gibt doch sicherlich eine Methode die zwei Sachen voneinander zu trennen?!
Das ich die Map einmal zeichne.. und bei Bedarf repainte... aber den Spieler permanent. ???:L


----------



## Empire Phoenix (18. Jan 2010)

Wenne etwas im vordergrund geändert wird muss das dahinter befindliche schon neu gezeichnet werden, aber du könntest das zb einschränken auf das Gebiet wo der player vorher wirklich war. (player verschieben, alte position neu rendern, player neu rendern)


----------



## Steev (18. Jan 2010)

Normalerweise wird alles über die entsprechenden Methoden neu gezeichnet. wenn du partial neu zeichnen willst, dann musst du auf jedem Fall die Resize-Events mit berücksichtigen. Dann gibt es noch so "lustige" Fehldarstellungen, wenn man ein anderes Fenster über dein Fenster herzieht. Solche Events müsste man ebenfalls abfragen. Oder eben einfach alles neu zeichnen.

Gruß
Steev


----------



## Landei (18. Jan 2010)

Wenn deine Map nicht so groß ist, kannst du sie einmal komplett auf ein BufferedImage zeichnen (muss natürlich neu gezeichnet werden, wenn sich am Hintergrund etwas ändert). Dann zeichnest du in paintComponent nur das entsprechend verschobene BufferedImage, was normalerweise sehr schnell gehen sollte, und alles andere drüber.


----------



## Quaxli (18. Jan 2010)

Du kannst mal in mein Tutorial gucken. Dort findest Du auch was darüber, wie man eine Karte aus Tiles zusammensetzt und immer nur die aktuell benötigten zeichnet.


----------



## lain (18. Jan 2010)

Steev hat gesagt.:


> Normalerweise wird alles über die entsprechenden Methoden neu gezeichnet. wenn du partial neu zeichnen willst, dann musst du auf jedem Fall die Resize-Events mit berücksichtigen. Dann gibt es noch so "lustige" Fehldarstellungen, wenn man ein anderes Fenster über dein Fenster herzieht. Solche Events müsste man ebenfalls abfragen. Oder eben einfach alles neu zeichnen.
> 
> Gruß
> Steev



Ich zeichne einfach alles in meiner paint Methode in der Main Klasse ... ob Spieler oder die Map.
Resize Events kann man ja auch umgehen oder "verbieten" das sollte vorerst mal nicht das Hauptproblem darstellen.



Quaxli hat gesagt.:


> Du kannst mal in mein Tutorial gucken. Dort findest Du auch was darüber, wie man eine Karte aus Tiles zusammensetzt und immer nur die aktuell benötigten zeichnet.



Ich schaus mir später mal an.



Landei hat gesagt.:


> Wenn deine Map nicht so groß ist, kannst du sie einmal komplett auf ein BufferedImage zeichnen (muss natürlich neu gezeichnet werden, wenn sich am Hintergrund etwas ändert). Dann zeichnest du in paintComponent nur das entsprechend verschobene BufferedImage, was normalerweise sehr schnell gehen sollte, und alles andere drüber.



hm ich weiss nicht ob das von der Umsetzung her passt auf längere Sicht gesehen aber sowas in die Art suche ich.

Bloß als Beispiel bei Spielen in Flash wird ja auch nicht alles *permanent* neu gezeichnet. Die Tiles werden einmal dargestellt. Und später beim scrolling werden einfach die neuen Tiles dran gezeichnet und die alten verschwinden.
Im Prinzip brauche ich ja nur ein repaint um die Position vom Spieler zu verändern oder wenn neue Tiles dran gezeichnet werden.


----------



## Landei (18. Jan 2010)

Noch ein heißer Tipp: Killer Game Programming in Java, Kapitel 11 ff.


----------



## Steev (18. Jan 2010)

lain hat gesagt.:


> Die Tiles werden einmal dargestellt. Und später beim scrolling werden einfach die neuen Tiles dran gezeichnet und die alten verschwinden.
> Im Prinzip brauche ich ja nur ein repaint um die Position vom Spieler zu verändern oder wenn neue Tiles dran gezeichnet werden.



Ich würde die Tiles auch bei jedem repaint neu zeichnen. Aber nur die Tiles, die wirklich sichtbar sind. Alle anderen Tiles sollten nur gerendert werden, wenn sie auch sichtbar sind. Guck dir vieleicht mal http://www.java-forum.org/spiele-multimedia-programmierung/90658-kollisionserkennung-jumpnrun.html


----------



## Quaxli (18. Jan 2010)

Ich würde auf jeden Fall die Tiles neu zeichnen. Je nachdem, wie das Spiel aufgebaut ist, bewegen sich ja nur die Tiles und simulieren so die Bewegung der Spielfigur.


----------



## lain (18. Jan 2010)

Quaxli hat gesagt.:


> Ich würde auf jeden Fall die Tiles neu zeichnen. Je nachdem, wie das Spiel aufgebaut ist, bewegen sich ja nur die Tiles und simulieren so die Bewegung der Spielfigur.



Beides wird getrennt gezeichnet... 
Da fällt mir ein das ich noch ein Problem was Performance betrifft habe.


```
@Override
    public void paint(Graphics g)
    {
            map.paintMap(g);
            //dummy.paintChar(g);
            //dummy2.paintChar(g);
            player.paintChar(g);

    }
```

Meine CPU läuft auf 99% wenn ich das so ausführe... Wenn ich bsp das map.paintMap auskommentiere fährt es auf ca 66% runter.. und wenn der spieler auskommentiert wird auf 5% ... woran liegt das o_o ? Sind so simple Grafiken ...


----------



## Steev (18. Jan 2010)

Hast du in deiner Repaint-Schleife auch ein Sleep? Wenn ja wie groß. Oder machst du das ganze per Frame Limiter?


----------



## Empire Phoenix (19. Jan 2010)

Denek ich auch der zeichnet so schnell er kann. Meine empfehlung ist ein BusyWaiting (wir haben 60 frames S also berechnen wie lange ein frame dargestellt wird , und dann zwischen den frames warten die differenz zwischen darstellzeit und renderzeit)
der vorteil hierbei ist ein gleichmäßiges Spiel,alternativ müsstest du überall die vergangene zeit einrechenen, weil zb rechner mit drecksgrafic 
-(zb. Radeon 5x ATI im Rückwärtsgang? 2D-Leistung bleibt auf der Strecke : Einführung: 2D-Grafik ? ungeliebtes Stiefkind oder Routineübung?) -
deutlich länger pro Frame brauchen und folglich das Spiel langsamer läuft.


----------



## lain (19. Jan 2010)

Steev hat gesagt.:


> Hast du in deiner Repaint-Schleife auch ein Sleep? Wenn ja wie groß. Oder machst du das ganze per Frame Limiter?



Das Spiel läuft über den Main Thread und der hat ne sleep Wartezeit von 20-40 .. je nach dem was ich teste.. mit 20 siehts aufjedenfall schöner aus aber meine CPU beklagt sich ziemlich über die Auslastung wobei es da nicht viel unterschied macht. 
Ne davon hab ich noch nichts gehört ... Das versucht Phoenix wahrscheinlich gerade noch zu erklären.



Empire Phoenix hat gesagt.:


> Denek ich auch der zeichnet so schnell er kann. Meine empfehlung ist ein BusyWaiting (wir haben 60 frames S also berechnen wie lange ein frame dargestellt wird , und dann zwischen den frames warten die differenz zwischen darstellzeit und renderzeit)
> der vorteil hierbei ist ein gleichmäßiges Spiel,alternativ müsstest du überall die vergangene zeit einrechenen, weil zb rechner mit drecksgrafic
> -(zb. Radeon 5x ATI im Rückwärtsgang? 2D-Leistung bleibt auf der Strecke : Einführung: 2D-Grafik ? ungeliebtes Stiefkind oder Routineübung?) -
> deutlich länger pro Frame brauchen und folglich das Spiel langsamer läuft.



Nagut kannst du mir ein Beispiel dazu geben wie das aussieht?
Wird die sleepzeit je nach dem geändert oder wie sieht das aus?


----------



## Quaxli (19. Jan 2010)

lain hat gesagt.:


> Nagut kannst du mir ein Beispiel dazu geben wie das aussieht?
> Wird die sleepzeit je nach dem geändert oder wie sieht das aus?



Genau.

Meine persönliche Vorliebe ist aber der andere Ansatz: Einen möglichst hohen Wert für FPS und die Bewegung aller Objekte in Abhängigkeit der Zeit, die der letzte Schleifendurchlauf benötigt hat.
Dies hat den Vorteil, daß die Bewegungen feiner gesteuert werden können, was ich z. B. bei Kollisionsermittlungen vorteilhaft finde.


----------



## Empire Phoenix (20. Jan 2010)

was ich z. B. bei Kollisionsermittlungen vorteilhaft finde.

NAchteil wenn das Game lagt, fliegen die objecte dann halt mal eben durch wände..., weil die Physic dann plötzlich nciht nur für wenige MilliSekunden interpolieren muss sondern für ganze Sekunden, und in einer Sekunde kann viel passieren. (Und laggen kann durch vieles passieren, Antivir free update, Tv-Karte, beliebiger anderer Programmabsturz,Singelcore der nebenhe irgetwas anderes macht,ect man kann also nicht sagen mein game brauch kaum Leistung daher passiert das nicht)

Zudem hat eine feste rate den Vorteil, das man deterministisch arbeiten kann. Wenn int Tick 1 zustand a herscht, folgt daraus das in Tick2 immer ganz genau nur ein zweiter zustand B folgen kann. (Zudem kann man wenn man Lust hat für jedes Physicobject ausrechnen wie schnell es sich wirklich bewegen darf, da man ja keine schwankungen im physictimestep zu erwarten hat)

So hier jetzt meine derzeitige Schleife

```
final ServerSolarSystem solarsys = new ServerSolarSystem(mapx,mapy);
			Thread updatethread = new Thread(){
				public void run(){
					while(true){
						long start = System.currentTimeMillis();
						solarsys.Update();
						long end = System.currentTimeMillis();
						int timepertick = (int) (end-start);
						int sleeptime = NHGlobals.ServerTickTime - timepertick;
						if(sleeptime > 0){
							try {
								Thread.sleep(sleeptime);
							} catch (InterruptedException e) {
								// TODO Auto-generated catch block
								e.printStackTrace();
							}
						}
						
					}
				}
			};
			updatethread.setName("SolarSystem " + mapx + "-" + mapy);
			updatethread.start();
```

Wenn vorhanden ist es sinnvoll nicht System.currentX zu nehmen, weil die meisten Implementierungen davon relativ ungenau sind (10ms rum)


----------



## Quaxli (20. Jan 2010)

Seit Java6 würde ich aber schon System.nanoTime() verwenden, anstelle von System.currentTimeMilis().
Warum sollte man sich mit einer ungenaueren Auflösung zufrieden geben, wenn es etwas besseres gibt?


----------



## lain (20. Jan 2010)

Empire Phoenix hat gesagt.:


> was ich z. B. bei Kollisionsermittlungen vorteilhaft finde.
> 
> NAchteil wenn das Game lagt, fliegen die objecte dann halt mal eben durch wände..., weil die Physic dann plötzlich nciht nur für wenige MilliSekunden interpolieren muss sondern für ganze Sekunden, und in einer Sekunde kann viel passieren. (Und laggen kann durch vieles passieren, Antivir free update, Tv-Karte, beliebiger anderer Programmabsturz,Singelcore der nebenhe irgetwas anderes macht,ect man kann also nicht sagen mein game brauch kaum Leistung daher passiert das nicht)
> 
> ...




Alles klar danke! das sieht super aus .. ich probiers später direkt mal aus  !


----------

