जो लोग कोडिंग भाग / डेवलपर परिप्रेक्ष्य में रुचि रखते हैं, उनके लिए जर्समैन गीक के जवाब (क्योंकि मेरा संपादन अस्वीकृत हो गया) के अतिरिक्त:
प्रोग्रामर के नजरिए से, उन लोगों के लिए जो रुचि रखते हैं, डॉस बार ऐसे समय थे जहां हर सीपीयू टिक महत्वपूर्ण था इसलिए प्रोग्रामर ने कोड को जितनी जल्दी हो सके रखा।
एक विशिष्ट परिदृश्य जहां कोई भी कार्यक्रम अधिकतम सीपीयू की गति से चलेगा, यह सरल (छद्म सी) है:
int main()
{
while(true)
{
}
}
यह हमेशा के लिए चलेगा, अब, इस कोड स्निपेट को छद्म-डॉस-गेम में बदल दें:
int main()
{
bool GameRunning = true;
while(GameRunning)
{
ProcessUserMouseAndKeyboardInput();
ProcessGamePhysics();
DrawGameOnScreen();
//close game
if(Pressed(KEY_ESCAPE))
{
GameRunning = false;
}
}
}
जब तक DrawGameOnScreen
फ़ंक्शन डबल बफरिंग / वी-सिंक का उपयोग नहीं करता है (जो उन दिनों में महंगा था जब डॉस गेम बनाए गए थे), गेम अधिकतम सीपीयू गति से चलेगा। एक आधुनिक दिन मोबाइल i7 पर यह प्रति सेकंड (लैपटॉप कॉन्फ़िगरेशन और वर्तमान सीपीयू उपयोग के आधार पर) लगभग 1,000,000 से 5,000,000 बार तक चलेगा।
इसका मतलब यह होगा कि अगर मैं अपने 64 बिट खिड़कियों में अपने आधुनिक सीपीयू पर काम करने वाला कोई भी डॉस गेम प्राप्त कर सकता हूं तो मुझे एक हजार (1000!) से अधिक एफपीएस मिल सकता है जो कि किसी भी मानव के लिए खेलने के लिए बहुत तेज़ है अगर भौतिकी प्रसंस्करण "मान लेता है" तो यह चलता है 50-60 एफपीएस के बीच।
वर्तमान में डेवलपर क्या कर सकते हैं (:)
- गेम में वी-सिंक को सक्षम करें (* विंडो किए गए एप्लिकेशन के लिए उपलब्ध नहीं है ** [केवल पूर्ण-स्क्रीन एप्लिकेशन में उपलब्ध है]]
- अंतिम अद्यतन के बीच समय के अंतर को मापें और समय के अंतर के अनुसार भौतिकी को अद्यतन करें जो प्रभावी रूप से एफपीएस दर की परवाह किए बिना खेल / कार्यक्रम को समान गति से चलाता है।
- प्रोग्राम को सीमाबद्ध रूप से सीमित करें
*** ग्राफिक्स कार्ड / ड्राइवर / ओएस कॉन्फ़िगरेशन के आधार पर यह संभव हो सकता है।
बिंदु 1 के लिए कोई उदाहरण नहीं है जो मैं दिखाऊंगा क्योंकि यह वास्तव में कोई "प्रोग्रामिंग" नहीं है। यह सिर्फ ग्राफिक्स सुविधाओं का उपयोग कर रहा है।
बिंदु 2 और 3 के लिए मैं इसी कोड स्निपेट और स्पष्टीकरण को दिखाऊंगा:
2:
int main()
{
bool GameRunning = true;
long long LastTick = GetCurrentTime();
long long TimeDifference;
while(GameRunning)
{
TimeDifference = GetCurrentTime()-LastTick;
LastTick = GetCurrentTime();
//process movement based on how many time passed and which keys are pressed
ProcessUserMouseAndKeyboardInput(TimeDifference);
//pass the time difference to the physics engine so it can calculate anything time-based
ProcessGamePhysics(TimeDifference);
DrawGameOnScreen();
//close game if escape is pressed
if(Pressed(KEY_ESCAPE))
{
GameRunning = false;
}
}
}
यहां आप देख सकते हैं कि उपयोगकर्ता इनपुट और भौतिकी समय के अंतर को ध्यान में रखते हैं, फिर भी आप स्क्रीन पर 1000+ एफपीएस प्राप्त कर सकते हैं क्योंकि लूप जितनी तेजी से चल रहा है। क्योंकि भौतिकी इंजन को पता है कि कितना समय बीत गया, उसे "कोई धारणा नहीं" या "एक निश्चित फ्रैमरेट" पर निर्भर रहना पड़ता है, इसलिए यह गेम किसी भी सीपीयू पर समान गति से काम करेगा।
3:
डेवलपर्स फ्रैमरेट को सीमित करने के लिए क्या कर सकते हैं, उदाहरण के लिए, 30 एफपीएस वास्तव में कुछ भी कठिन नहीं है, बस एक नज़र डालें:
int main()
{
bool GameRunning = true;
long long LastTick = GetCurrentTime();
long long TimeDifference;
double FPS_WE_WANT = 30;
//how many milliseconds need to pass before we need to draw again so we get the framerate we want?
double TimeToPassBeforeNextDraw = 1000.0/FPS_WE_WANT;
//For the geek programmers: note, this is pseudo code so I don't care for variable types and return types..
double LastDraw = GetCurrentTime();
while(GameRunning)
{
TimeDifference = GetCurrentTime()-LastTick;
LastTick = GetCurrentTime();
//process movement based on how many time passed and which keys are pressed
ProcessUserMouseAndKeyboardInput(TimeDifference);
//pass the time difference to the physics engine so it can calculate anything time-based
ProcessGamePhysics(TimeDifference);
//if certain amount of milliseconds pass...
if(LastTick-LastDraw >= TimeToPassBeforeNextDraw)
{
//draw our game
DrawGameOnScreen();
//and save when we last drawn the game
LastDraw = LastTick;
}
//close game if escape is pressed
if(Pressed(KEY_ESCAPE))
{
GameRunning = false;
}
}
}
यहां क्या होता है कि कार्यक्रम यह गिनता है कि कितने मिलीसेकंड पास हुए हैं, अगर एक निश्चित राशि (33 एमएस) तक पहुंच जाती है, तो यह गेम स्क्रीन को फिर से परिभाषित करता है, प्रभावी रूप से ~ 30 के पास एक फ्रेम दर लागू करता है।
इसके अलावा, डेवलपर पर निर्भर करता है कि वह उपरोक्त सभी कोड के साथ 30 प्रसंस्करण एफपीएस को सीमित करने का विकल्प चुन सकता है।
int main()
{
bool GameRunning = true;
long long LastTick = GetCurrentTime();
long long TimeDifference;
double FPS_WE_WANT = 30;
//how many miliseconds need to pass before we need to draw again so we get the framerate we want?
double TimeToPassBeforeNextDraw = 1000.0/FPS_WE_WANT;
//For the geek programmers: note, this is pseudo code so I don't care for variable types and return types..
double LastDraw = GetCurrentTime();
while(GameRunning)
{
LastTick = GetCurrentTime();
TimeDifference = LastTick-LastDraw;
//if certain amount of miliseconds pass...
if(TimeDifference >= TimeToPassBeforeNextDraw)
{
//process movement based on how many time passed and which keys are pressed
ProcessUserMouseAndKeyboardInput(TimeDifference);
//pass the time difference to the physics engine so it can calculate anything time-based
ProcessGamePhysics(TimeDifference);
//draw our game
DrawGameOnScreen();
//and save when we last drawn the game
LastDraw = LastTick;
//close game if escape is pressed
if(Pressed(KEY_ESCAPE))
{
GameRunning = false;
}
}
}
}
कुछ अन्य तरीके हैं, और उनमें से कुछ मैं वास्तव में नफरत करते हैं।
उदाहरण के लिए, का उपयोग कर sleep(<amount of milliseconds>)
।
मुझे पता है कि फ्रैमरेट को सीमित करने के लिए यह एक तरीका है, लेकिन तब क्या होता है जब आपके गेम की प्रोसेसिंग में 3 मिलीसेकंड या इससे अधिक का समय लगता है? और फिर आप नींद को अंजाम देते हैं ...
यह एक कम फ्रैमर्ट में परिणाम देगा जो केवल sleep()
कारण होना चाहिए।
उदाहरण के लिए, 16 एमएस की नींद का समय लें। इस कार्यक्रम को 60 हर्ट्ज पर चलाया जाएगा। अब डेटा, इनपुट, ड्रॉइंग और सभी सामानों की प्रोसेसिंग में 5 मिलिसेकंड लगते हैं। हम एक लूप के लिए 21 मील की दूरी पर हैं, जिसके परिणामस्वरूप 50 हर्ट्ज से थोड़ा कम है, जबकि आप आसानी से 60 हर्ट्ज पर हो सकते हैं लेकिन नींद के कारण यह असंभव है।
एक समाधान प्रसंस्करण समय को मापने के रूप में एक अनुकूली नींद बनाना और वांछित नींद से प्रसंस्करण समय में कटौती करना होगा, जिसके परिणामस्वरूप हमारी "बग" को ठीक किया जाएगा:
int main()
{
bool GameRunning = true;
long long LastTick = GetCurrentTime();
long long TimeDifference;
long long NeededSleep;
while(GameRunning)
{
TimeDifference = GetCurrentTime()-LastTick;
LastTick = GetCurrentTime();
//process movement based on how many time passed and which keys are pressed
ProcessUserMouseAndKeyboardInput(TimeDifference);
//pass the time difference to the physics engine so it can calculate anything time-based
ProcessGamePhysics(TimeDifference);
//draw our game
DrawGameOnScreen();
//close game if escape is pressed
if(Pressed(KEY_ESCAPE))
{
GameRunning = false;
}
NeededSleep = 33 - (GetCurrentTime()-LastTick);
if(NeededSleep > 0)
{
Sleep(NeededSleep);
}
}
}