2010-07-22 27 views
8

Ben eski bir okul ASCII DOS-Prompt oyunu yazıyorum. Dürüst olmak gerekirse, bu oyun tasarımı hakkında daha fazla bilgi edinmek için ZZT'ye öykünmeye çalışıyorum (antika olsa bile)ASCII DOS Oyunları - Oluşturma yöntemleri

Ben iyiyim, tam ekran metin modumu çalıştırdım ve dünyalar yaratabilirim sorun olmadan etrafında ama benim işleyiciler için iyi bir zamanlama yöntemi bulamıyorum.

Oluşturma ve ön işleme kodumun hızlı olduğunu biliyorum çünkü time.h'dan herhangi bir gecikme() s veya (clock() - renderBegin)/CLK_TCK denetimi eklemezseniz, render'lar şaşırtıcı derecede hızlıdır.

Gecikme() kullanmak istemiyorum çünkü bilgi platformuma özeldir ve bunun üzerine herhangi bir kodu geciktirirken çalıştıramıyorum (kullanıcı girişi ve işleme gibi). Bu yüzden böyle bir şey yapmaya karar verdim: "Teori" nin çalışması iyi olacaktı. Bu, aşağıdaki gibi bir şey yapmaya karar verdim:

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

    if(clock()/CLOCKS_PER_SEC-renderTimer/CLOCKS_PER_SEC > RenderInterval) { 
     renderTimer = clock(); 
     render(); 
     ballLogic(); 
    } 
}while(input != 'p'); 
Sorun şu ki, bu kodu çalıştırdığımda (RenderInterval'ı 0.0333 veya 30fps'ye ayarlıyorum), 30 fps'ye yakın ANYWHERE alamıyorum, en fazla 18 tane daha aldım.

Performansın başlatılıp başlatılmadığını görmek için RenderInterval'ı 0.0 olarak ayarlamayı deneyebilirim. Ben ~ ~ 18-20fps alma (0.0 bir RenderInterval ile) oldu.

olsa belki sürekli tüm bu saati arayarak() ve CPU aşağı bir şey korkutucu yavaşlama oldu yöntemleri "Bununla bu bölmek" ama işlemek aldı ve ne zaman ifadesinin parantez eğer ballLogic dışarı çağırır ediyorum beri ve RenderInterval'ı 0,0'ya ayarlıyorum, yine, çılgınca hızlı bir şekilde render ediyorum.

Bu benim için bir çekicidir, çünkü eğer kontrol etmeden ayrılırsam, yavaş çalışmamalı mıyım? Ben hala

BTW

Ben Borland Turbo C ile derleme ++ v1.01 tüm hesaplamaları yapmak zorunda anlamına

+1

ZZT! Bu oyunu sevdim. – caf

+0

Sen ve ben ikimiz, caf. (#throwstar seek'). @ Parad0x13: Saate' sonucunu kapalı kaydediniz (http://libfake437.googlecode.com –

+0

: Eğer DOS uzaklaşan sakıncası yoksa, ben SDL tarafından desteklenen herhangi bir platformda bu grafik stilini taklit bir kütüphane yazdım) '' ((saat aksi takdirde ilk aradığında arasındaki zaman kaybetmek (en hızlı kod aramıyorsun kodudur) ve daha doğru olacaktır) o ve bunun için bir çağrı kazandıracak, depolanan değeri atamak' , tüm matematikleri yaptı ve dalı ele aldı. Bu hassaslık kaybı, cpu kullanımını artık kullanmıyor olsanız bile oyunun istediğiniz kadar yavaş çalışmasını sağlar. –

cevap

1
clock()-renderTimer > RenderInterval * CLOCKS_PER_SEC 

eğer muhtemelen daha da hızlı RenderInterval * CLOCKS_PER_SEC bölümünü önceden hesaplanması, biraz daha hızlı hesaplamak ediyorum .

+0

Ben optimizasyonu bakın Yanıtınız için teşekkür ederiz: (düzenleme haha, sadece iyi oh bu tarih gördüğümüz). Bununla birlikte, sorun hala var. Sadece denedim – Parad0x13

+0

Derleyici, döngüler üzerinde her türlü optimizasyonu yapar, bu özellik (özellikle de şubeler içeriyorsa) özellik yaratabilir - her iki durumda da oluşturulan koda bakmaya çalışın. Aslında, işlemci benzer bir çalışma yapar (şube tahminine bakın). – Ofir

+0

İşlemciyi kontrol ettim ama hangi optimizasyonların etkin olduğunu anlayamıyorum – Parad0x13

0

Bu konuda ne var? X (= clock()) y (= renderTimer) 'dan çıkarılıyorsunuz. Hem x ve y CLOCKS_PER_SEC bölü edilmektedir: Ben bölünme ile gördüm

(clock() - renderTimer) > RenderInterval 

ilk sorun gitmiyorsun olmasıydı:

clock()/CLOCKS_PER_SEC-renderTimer/CLOCKS_PER_SEC > RenderInterval 

o mor efficiente yazmaya olmaz ondan gerçek bir sayı elde etmek, çünkü iki uzun iniş arasında gerçekleşir. Secons problemi, RenderInterval * CLOCKS_PER_SEC değerini çoğaltmanın daha verimli olması ve bu yoldan kurtulmanın, işlemi basitleştirmesidir.

Köşeli parantez eklemek, daha fazla okunabilirlik sağlar. Ve belki de bu orospuyu basitleştirerek neyin yanlış gittiğini kolaylaştıracaksınız.

+0

yerine> Bu formül optimizasyonlarını denedim ama aynı sonuçları almaya devam ettim. – Parad0x13

+0

RenderInterval = 1'i zorlarsanız ne olur? – Baltasarq

0

En son sorunuzu belirttiğiniz gibi, yalnızca 18 yaşında olan CLOCKS_PER_SEC tarafından sınırlandırılmıştır. Saatin her bir değeri için bir kare alırsınız, bu nedenle 18 fps ile sınırlıdır.o "yırtılma" kaçınır olarak

Sen zamanlama için ekran dikey karartma aralığını kullanabilirsiniz

, bu oyunlar için geleneksel var o değildi neden

0

anladım (burada yarım ekran bir kare gösterir ve yarım başka gösterir) hemen render benim yarattığım zamanlayıcı sorun fiili clock_t .054547XXX ya da öylesine ve bu yüzden sadece 18fps de kullanılabilir hale getirdik yegane hassas olmasıdır gayet iyi. Bunu düzeltmek istiyorum yolu genellikle monitörün dikey retrace ile senkronize ederek elde edilir bambaşka bir hikaye

2

iyi oyun deneyimi daha doğru saati ... kullanmaktır. Zamanlama sağlamanın yanı sıra, bu, en azından, bilgisayara bağlı bir CRT monitörünüz varsa, oyunun daha düzgün çalışmasını sağlar. 80x25 boyutlarındaki metin modunda

, (VGA) yatay geri dönüş 70 kat/saniye oluşur. EGA/CGA'da frekansın aynı olup olmadığını hatırlamıyorum, ancak Herkül ve MDA'nın 50 Hz olduğunu gayet eminim. 20 kare süreyi ölçerek, hangi frekansla uğraştığınızı yeterince iyi tahmin etmelisiniz.

ana döngü someting böyle olalım:

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)); 
    }