कुछ पुराने गेम आधुनिक हार्डवेयर पर बहुत तेज़ी से क्यों चलते हैं?


64

मुझे कुछ पुराने कार्यक्रम मिले हैं, मैंने 90 के दशक के शुरुआती विंडोज़ कंप्यूटर को बंद कर दिया था और उन्हें अपेक्षाकृत आधुनिक कंप्यूटर पर चलाने की कोशिश की। दिलचस्प रूप से पर्याप्त है, वे एक तेज तेज गति से भागे - नहीं, 60 फ्रेम प्रति सेकेंड के तेज नहीं, बल्कि ओह-माय-गॉड-ए-कैरेक्टर-इज़-वॉकिंग-ऑफ-द-स्पीड-ऑफ-साउंड तरह के तेजी से। मैं एक तीर कुंजी दबाऊंगा और किरदार का स्प्राइट स्क्रीन पर सामान्य से ज्यादा तेज गति से जिप करेगा। खेल में समय की प्रगति की तुलना में बहुत तेजी से हो रहा था। यहां तक कि आपके CPU को धीमा करने के लिए भी प्रोग्राम बनाए गए हैं ताकि ये गेम वास्तव में खेलने योग्य हो।

मैंने सुना है कि यह सीपीयू साइकल, या कुछ इस तरह के खेल से संबंधित है। मेरे प्रश्न हैं:

  • पुराने खेल ऐसा क्यों करते हैं, और वे इसके साथ कैसे दूर हो गए?
  • नए गेम कैसे नहीं करते हैं और यह सीपीयू आवृत्ति से स्वतंत्र रूप से चलता है?

यह कुछ समय पहले था और मुझे किसी भी संगतता चालबाजी को याद नहीं है, लेकिन यह बिंदु के बगल में है। इसे ठीक करने के तरीके के बारे में बहुत सारी जानकारी है, लेकिन इतना नहीं कि वे इस तरह से क्यों दौड़ते हैं, जो मैं पूछ रहा हूं।
ट्रेक

9
पुराने पीसी पर टर्बो बटन याद रखें? : डी
विक्टर मेलग्रेन

1
आह। मुझे ABC80 (मूल के साथ स्वीडिश z80- आधारित पीसी) पर 1 सेकंड की देरी याद है। FOR F IN 0 TO 1000; NEXT F;
मैके १e

1
बस स्पष्ट करने के लिए, "कुछ पुराने कार्यक्रम जिन्हें मैंने 90 के दशक की शुरुआत में शुरू किया था- विंडोज कंप्यूटर" उन डॉस प्रोग्राम हैं जो विंडोज मशीन या विंडोज प्रोग्राम पर होते हैं, जहां यह व्यवहार होता है? मैं इसे डॉस पर देखने के लिए उपयोग कर रहा हूं, लेकिन विंडोज़ नहीं, आईआईआरसी।
वह ब्राजील के लड़के

जवाबों:


52

मेरा मानना ​​है कि उन्होंने माना कि सिस्टम क्लॉक एक विशिष्ट दर पर चलेगा, और उनकी आंतरिक टाइमर में उस घड़ी की दर से बंधा होगा। इन खेलों में से अधिकांश संभवतः डॉस पर चलते थे, और वास्तविक मोड (पूर्ण, प्रत्यक्ष हार्डवेयर एक्सेस के साथ) थे और यह मान लिया था कि आप पीसी के लिए iirc 4.77 मेगाहर्ट्ज सिस्टम और जो भी मानक प्रोसेसर है कि मॉडल अमिगा जैसी अन्य प्रणालियों के लिए चला रहे थे।

उन्होंने उन अनुमानों के आधार पर चतुर शॉर्टकट भी लिया, जिनमें कार्यक्रम के अंदर आंतरिक समय के छोरों को न लिखकर संसाधनों की थोड़ी बचत करना शामिल है। वे भी उतनी ही प्रोसेसर शक्ति लेते थे, जितनी कि धीमी गति के दिनों में एक सभ्य विचार था, अक्सर निष्क्रिय रूप से ठंडा चिप्स!

शुरू में अलग-अलग प्रोसेसर की गति प्राप्त करने का एक तरीका अच्छा पुराना टर्बो बटन था (जो आपके सिस्टम को धीमा कर देता था)। आधुनिक अनुप्रयोग संरक्षित मोड में हैं और ओएस संसाधनों का प्रबंधन करने के लिए जाता है - वे कई मामलों में प्रोसेसर के सभी का उपयोग करने के लिए एक डॉस एप्लिकेशन (जो 32-बिट सिस्टम पर एनटीवीडीएम में चल रहा है) की अनुमति नहीं देगा । संक्षेप में, OSes के पास API के रूप में स्मार्ट हो गए हैं।

भारी रूप से ओल्डस्कूल पीसी पर इस गाइड पर आधारित जहां तर्क और स्मृति मुझे विफल रही - यह एक महान पढ़ा है, और शायद "क्यों" में अधिक गहराई तक जाता है।

CPUkiller जैसे सामान आपके सिस्टम को "धीमा" करने के लिए यथासंभव संसाधनों का उपयोग करते हैं, जो अक्षम है। आपके एप्लिकेशन द्वारा देखी जाने वाली घड़ी की गति को प्रबंधित करने के लिए DOSBox का उपयोग करना बेहतर होगा ।


14
इन खेलों में से कुछ भी कुछ भी ग्रहण नहीं किया, वे बस के रूप में तेजी से दिखाए जा सकते थे के रूप में भाग गया, 'बजाने' जो था उन CPU के ;-) पर
जनवरी Doggen

2
जानकारी के लिए फिर से। "नए गेम यह कैसे नहीं करते हैं और सीपीयू आवृत्ति के स्वतंत्र रूप से चलाते हैं?" कुछ के लिए gamedev.stackexchange.com खोजने का प्रयास करें game loop। मूल रूप से 2 विधियाँ हैं। 1) खेल जितना तेज चलता है उसके आधार पर उतनी ही तेजी से दौड़ें और गति को गति दें आदि। 2) यदि आप बहुत तेज़ प्रतीक्षा कर रहे हैं ( sleep()) जब तक हम अगले 'टिक' के लिए तैयार नहीं होते हैं।
जॉर्ज डकेट

24

जो लोग कोडिंग भाग / डेवलपर परिप्रेक्ष्य में रुचि रखते हैं, उनके लिए जर्समैन गीक के जवाब (क्योंकि मेरा संपादन अस्वीकृत हो गया) के अतिरिक्त:

प्रोग्रामर के नजरिए से, उन लोगों के लिए जो रुचि रखते हैं, डॉस बार ऐसे समय थे जहां हर सीपीयू टिक महत्वपूर्ण था इसलिए प्रोग्रामर ने कोड को जितनी जल्दी हो सके रखा।

एक विशिष्ट परिदृश्य जहां कोई भी कार्यक्रम अधिकतम सीपीयू की गति से चलेगा, यह सरल (छद्म सी) है:

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. प्रोग्राम को सीमाबद्ध रूप से सीमित करें

*** ग्राफिक्स कार्ड / ड्राइवर / ओएस कॉन्फ़िगरेशन के आधार पर यह संभव हो सकता है।

बिंदु 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);
        }
    }
}

16

एक मुख्य कारण देरी लूप का उपयोग करना है जो प्रोग्राम शुरू होने पर कैलिब्रेट किया जाता है। वे गिनते हैं कि एक ज्ञात राशि में कितनी बार लूप निष्पादित होता है और इसे छोटे विलंब उत्पन्न करने के लिए विभाजित करता है। इसके बाद गेम के निष्पादन को गति देने के लिए एक नींद () फ़ंक्शन को लागू करने के लिए उपयोग किया जा सकता है। समस्या तब आती है जब प्रोसेसर काउंटर पर लूप पर इतना तेज होने के कारण अधिकतम हो जाता है, जिससे छोटी सी देरी बहुत छोटी हो जाती है। इसके अलावा आधुनिक प्रोसेसर लोड के आधार पर गति को बदलते हैं, कभी-कभी प्रति-कोर के आधार पर भी, जो देरी को और भी अधिक बनाता है।

वास्तव में पुराने पीसी खेल के लिए वे बस के रूप में उपवास के रूप में वे खेल को गति देने की कोशिश करने के लिए कोई संबंध नहीं कर सकता था। यह आईबीएम पीसी एक्सटी दिनों में अधिक मामला था, जहां एक टर्बो बटन मौजूद था, जिसने इस कारण से 4.77mhz प्रोसेसर से मिलान करने के लिए सिस्टम को धीमा कर दिया था।

डायरेक्टएक्स जैसे आधुनिक गेम और लाइब्रेरी में उच्च प्रीसेशन टाइमर का उपयोग होता है, इसलिए कैलिब्रेटेड कोड आधारित विलंब छोरों का उपयोग करने की आवश्यकता नहीं होती है।


4

शुरुआत में सभी पहले पीसी एक ही गति से चलते थे, इसलिए गति में अंतर के लिए खाते की आवश्यकता नहीं थी।

इसके अलावा, शुरुआत में कई गेमों में काफी फिक्स्ड सीपीयू-लोड था, इसलिए यह संभावना नहीं थी कि कुछ फ्रेम दूसरों की तुलना में तेजी से चलेंगे।

आजकल, येर किड्स और येर फैंसी एफपीएस शूटरों के साथ, आप एक सेकंड में फर्श पर देख सकते हैं, और अगले पर भव्य कैनियन में, लोड-भिन्नता अधिक बार होती है। :)

(और, कुछ हार्डवेयर कंसोल लगातार 60 एफपीएस पर गेम चलाने के लिए काफी तेज़ हैं। यह ज्यादातर इस तथ्य के कारण है कि कंसोल डेवलपर्स 30 हर्ट्ज का विकल्प चुनते हैं और पिक्सल को दो बार चमकदार बनाते हैं ...)

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.