2010-07-22 6 views
8

Ich schreibe eine alte Schule ASCII-DOS-Eingabeaufforderungsspiel. Ehrlich gesagt versuche ich, ZZT zu emulieren, um mehr über diese Marke des Spielentwurfs zu lernen (selbst wenn es antiquated ist)ASCII DOS Games - Rendering-Methoden

mir geht es gut, erhielt meinen Vollbildtextmodus, um zu arbeiten und ich kann Welten schaffen und mich bewegen herum ohne Probleme, aber ich kann keine vernünftige Timing-Methode für meine Renderings finden.

weiß, dass ich meine Rendering-und Pre-Rendering-Code ist schnell, weil, wenn ich jede Verzögerung nicht add() s oder (clock() - renderBegin)/CLK_TCK Kontrollen von time.h der macht unglaublich schnell sind.

Ich möchte nicht mit delay() arbeiten, da es meines Wissens plattformspezifisch ist und obendrein kann ich keinen Code ausführen, während es verzögert (Wie Benutzereingabe und -verarbeitung). Also habe ich beschlossen, etwas zu tun:

do { 
    if(kbhit()) { 
     input = getch(); 
     processInput(input); 
    } 

    if(clock()/CLOCKS_PER_SEC-renderTimer/CLOCKS_PER_SEC > RenderInterval) { 
     renderTimer = clock(); 
     render(); 
     ballLogic(); 
    } 
}while(input != 'p'); 

der sollte in „Theorie“ gut funktionieren. Das Problem ist, dass ich, wenn ich diesen Code (Einstellung der RenderInterval auf 0.0333 oder 30fps) nicht nahe an 30fps, bekomme ich mehr wie 18 bei max.

Ich dachte, vielleicht würde ich versuchen, den RenderInterval auf 0.0 zu setzen, um zu sehen, ob die Leistung hochkletterte ... es tat es nicht. Ich war (mit einem RenderInterval von 0.0) bei max ~ 18-20fps.

Ich vielleicht vielleicht, da ich ständig all diese Uhr() und "dividiere das durch diese" Methoden Ich verlangsamte die CPU etwas beängstigend, aber wenn ich die Render-und BallLogic Anrufe aus der if-Anweisung Klammern nahm und setze RenderInterval auf 0.0 Ich bekomme, wieder blitzschnell rendert.

Das macht keinen Sinn für mich, wenn ich das If Check-in verließ, sollte es nicht genauso langsam laufen? Ich meine, es immer noch alle Berechnungen

BTW mit Borland ich kompilieren Turbo C++ zu tun hat V1.01

+1

ZZT:

die Hauptschleife someting wie sein lassen! Ich habe dieses Spiel geliebt. – caf

+0

Sie und ich beide, Café. ('#throwstar suchen'). @ Parad0x13: Wenn es Ihnen nichts ausmacht, weg von DOS zu gehen, schrieb ich eine Bibliothek, um diesen Grafikstil auf jeder von SDL unterstützten Plattform zu emulieren: http://libfake437.googlecode.com –

+0

Wenn Sie das Ergebnis von 'Uhr speichern () 'und den gespeicherten Wert zuweisen, Sie werden einen Anruf speichern (der schnellste Code ist der Code, den Sie nicht anrufen) und es wird genauer (sonst verlieren Sie die Zeit zwischen dem ersten Aufruf' Uhr() ' , hat die ganze Mathematik gemacht und den Zweig gehandhabt). Dieser Genauigkeitsverlust lässt das Spiel langsamer laufen, als Sie möchten, selbst wenn Sie die CPU-Nutzung nicht mehr ausschöpfen. (edit: haha, habe gerade das Datum dazu gesehen, naja) –

Antwort

1
clock()-renderTimer > RenderInterval * CLOCKS_PER_SEC 

ein bisschen schneller berechnen würde, möglicherweise sogar schneller, wenn Sie im Voraus berechnen die RenderInterval * CLOCKS_PER_SEC Teil .

+0

Danke für deine Antwort, ich sehe die Optimierung. Auch damit bleibt das Problem jedoch bestehen. Probieren Sie es einfach – Parad0x13

+0

Der Compiler führt alle Arten von Optimierungen auf Schleifen, die Besonderheiten (vor allem wenn sie Zweige enthalten) erstellen - versuchen Sie in beiden Fällen den generierten Code zu sehen. In der Tat, der Prozessor macht einige ähnliche Arbeit (Nachschlagen Verzweigung Vorhersage). – Ofir

+0

Ich habe den Preprozessor überprüft, aber ich kann nicht herausfinden, welche Optimierungen aktiviert sind. – Parad0x13

0

Was ist damit: Sie subtrahieren von x (= Clock()) y (= renderTimer). Sowohl x und y werden durch CLOCKS_PER_SEC unterteilt:

clock()/CLOCKS_PER_SEC-renderTimer/CLOCKS_PER_SEC > RenderInterval 

Wäre es nicht mor efficiente zu schreiben:

(clock() - renderTimer) > RenderInterval 

Das erste Problem, das ich mit der Teilung sah, war, dass Sie nicht gehen um eine reelle Zahl daraus zu bekommen, da es zwischen zwei Long-Ints passiert. Das zweite Problem ist, dass es effizienter ist, RenderInterval * CLOCKS_PER_SEC zu multiplizieren und auf diese Weise loszuwerden, was die Operation vereinfacht.

Durch Hinzufügen der Klammern wird die Lesbarkeit verbessert. Und vielleicht wird es Ihnen durch die Vereinfachung dieser Phormula einfacher, was falsch läuft.

+0

Ich habe diese Formeloptimierungen ausprobiert, aber ich habe weiterhin dieselben Ergebnisse erzielt. – Parad0x13

+0

Was ist, wenn Sie RenderInterval = 1 erzwingen? – Baltasarq

0

Wie Sie mit Ihrer letzten Frage gesehen haben, sind Sie durch CLOCKS_PER_SEC begrenzt, die nur etwa 18 ist. Sie erhalten einen Frame pro diskreten Wert der Uhr, weshalb Sie auf 18 fps beschränkt sind.

Sie den Bildschirm vertikalen Austastlücke für Timing verwenden könnte, ist es für traditionelle Spiele ist, als es „Zerreißen“ vermeidet (wo die Hälfte Bildschirm zeigt einen Rahmen aus und zeigt eine andere)

0

ich herausgefunden, warum es nicht war Rendering sofort, der Timer, den ich erstellt habe, ist in Ordnung das Problem ist, dass der tatsächliche clock_t ist nur genau auf .054547XXX oder so und so konnte ich nur mit 18fps rendern. Die Art und Weise, wie ich das beheben würde, ist mit einer genaueren Uhr ... was ist eine ganz andere Geschichte

2

Das beste Spielerlebnis wird in der Regel durch die Synchronisierung mit dem vertikalen Rücklauf des Monitors erreicht. Zusätzlich zum Timing wird das Spiel auch flüssiger auf dem Bildschirm ausgeführt, zumindest wenn Sie einen CRT-Monitor an den Computer angeschlossen haben.

Im 80x25-Textmodus erfolgt der vertikale Rücklauf (auf VGA) 70 Mal/Sekunde. Ich erinnere mich nicht, ob die Frequenz bei EGA/CGA die gleiche war, aber ich bin mir ziemlich sicher, dass es bei Hercules und MDA 50 Hz waren. Wenn Sie die Dauer von beispielsweise 20 Frames messen, sollten Sie eine ausreichend gute Schätzung der Häufigkeit haben, mit der Sie es zu tun haben.

while (playing) { 
    do whatever needs to be done for this particular frame 
    VSync(); 
    } 

    ... /* snip */ 

    /* Wait for vertical retrace */ 
    void VSync() { 
    while((inp(0x3DA) & 0x08)); 
    while(!(inp(0x3DA) & 0x08)); 
    }