কেন কিছু পুরানো গেমগুলি আধুনিক হার্ডওয়্যারে খুব দ্রুত চলে?


64

আমি কয়েকটি পুরানো প্রোগ্রাম পেয়েছি আমি 90-এর দশকের প্রথম দিকের উইন্ডোজ কম্পিউটারটি টেনে এনে একটি অপেক্ষাকৃত আধুনিক কম্পিউটারে চালানোর চেষ্টা করেছি। আকর্ষণীয়ভাবে যথেষ্ট, তারা জ্বলন্ত দ্রুত গতিতে ছুটেছিল - না, সেকেন্ড ধরণের দ্রুত প্রতি 60০ ফ্রেম নয়, ওহ-মাই-গড-দ্য-চরিত্র-হ'ল-স্পিড-অফ-স্পিড-ধরণের দ্রুত। আমি একটি তীর কী টিপব এবং চরিত্রের স্প্রিটটি স্ক্রিনে স্বাভাবিকের চেয়ে অনেক দ্রুত জিপ করে। গেমটিতে সময়ের অগ্রগতিটি হওয়া উচিত ছিল তার থেকে অনেক দ্রুত। এমনকি আপনার সিপিইউকে ধীর করার জন্য এমন কিছু প্রোগ্রাম তৈরি করা হয়েছে যাতে এই গেমগুলি প্রকৃতপক্ষে খেলতে পারা যায়।

আমি শুনেছি এটি সিপিইউ চক্রের উপর নির্ভর করে গেমের সাথে সম্পর্কিত like আমার প্রশ্নগুলি হ'ল:

  • পুরানো গেমগুলি কেন এটি করে এবং কীভাবে তারা এগুলি থেকে পালিয়ে যায়?
  • কীভাবে নতুন গেমস এটি করে না এবং সিপিইউ ফ্রিকোয়েন্সি থেকে স্বাধীনভাবে চলে?

এটি কিছুক্ষণ আগে এসেছিল এবং আমি কোনও সামঞ্জস্যতা ট্রিক্রি করাকে স্মরণ করতে পারি না, তবে এটি বিন্দুটির পাশে। এটি কীভাবে ঠিক করা যায় সে সম্পর্কে প্রচুর তথ্য রয়েছে, তবে কেন তারা ঠিক সেভাবে চালায় সে সম্পর্কে এতটা নয় , যা আমি জিজ্ঞাসা করছি।
ট্রেইকের

9
পুরানো পিসির টার্বো বোতামটি মনে আছে? : ডি
ভিক্টর মেলগ্রেন

1
আহ। আমাকে এবিসি 80 এ 1 সেকেন্ড বিলম্বের কথা স্মরণ করিয়ে দেয় (বেসিক সহ সুইডিশ z80- ভিত্তিক পিসি)। FOR F IN 0 TO 1000; NEXT F;
মাককে

1
কেবল স্পষ্ট করে বলতে গেলে, "আমি 90s-এর দশকের প্রথম দিকের উইন্ডোজ কম্পিউটারটি সরিয়ে দিয়েছি এমন কয়েকটি পুরানো প্রোগ্রাম" কী কোনও উইন্ডোজ মেশিনে ডস প্রোগ্রাম, বা উইন্ডোজ প্রোগ্রাম যেখানে এই আচরণটি ঘটে? আমি এটি ডস-এ দেখতে অভ্যস্ত, কিন্তু উইন্ডোজ নয়, আইআইআরসি।
ব্রাজিলিয়ান গাই

উত্তর:


52

আমি বিশ্বাস করি যে তারা ধরে নিয়েছে যে সিস্টেমের ঘড়িটি একটি নির্দিষ্ট হারে চলবে এবং তাদের অভ্যন্তরীণ টাইমারগুলিকে সেই ঘড়ির হারের সাথে বেঁধে রাখবে। এই গেমগুলির বেশিরভাগই সম্ভবত ডসটিতে চলেছিল, এবং এটি সত্যিকারের মোড ছিল (সম্পূর্ণ, সরাসরি হার্ডওয়্যার অ্যাক্সেস সহ) এবং ধরে নিয়েছিল আপনি পিসিগুলির জন্য আইরিক 4.77 মেগাহার্টজ সিস্টেমটি চালাচ্ছেন এবং যে মডেলটি অ্যামিগা যেমন অন্যান্য সিস্টেমের জন্য দৌড়ায় whatever

তারা প্রোগ্রামের অভ্যন্তরীণ সময় লুপগুলি না লিখে সংক্ষিপ্ত পরিমাণে সংস্থান সংরক্ষণ সহ সেই অনুমানগুলির উপর ভিত্তি করে চতুর শর্টকাটও নিয়েছিল। তারা যতটা সম্ভব প্রসেসরের শক্তি গ্রহণ করেছিল - ধীর, প্রায়শই প্যাসিভলি শীতল চিপগুলির দিনগুলিতে এটি একটি শালীন ধারণা ছিল!

প্রসেসরের গতি আলাদা করতে পারার প্রাথমিকভাবে একটি উপায় ছিল পুরানো টার্বো বোতামটি (যা আপনার সিস্টেমকে ধীর করে দিয়েছিল)। আধুনিক অ্যাপ্লিকেশনগুলি সুরক্ষিত মোডে রয়েছে এবং ওএস সংস্থানগুলি পরিচালনা করতে পারে - তারা কোনও ডস অ্যাপ্লিকেশনকে (যা এনটিভিডিএম-তে 32-বিট সিস্টেমে চলছে) অনেক ক্ষেত্রে সমস্ত প্রসেসর ব্যবহার করার অনুমতি দেয় না । সংক্ষেপে, ওএসগুলি এপিআই হিসাবে স্মার্ট হয়ে উঠেছে।

ওল্ডস্কুল পিসিতে এই নির্দেশিকাটি প্রচুরভাবে ভিত্তি করে তৈরি করা হয়েছে যেখানে যুক্তি এবং স্মৃতি আমাকে ব্যর্থ করেছিল - এটি একটি দুর্দান্ত পাঠ, এবং সম্ভবত "কেন" এর গভীরতায় আরও গভীরতর হয়।

সিপিইউকিলারের মতো স্টাফ আপনার সিস্টেমকে "ধীর" করতে যতটা সম্ভব সম্পদ ব্যবহার করে, যা অদক্ষ। আপনার অ্যাপ্লিকেশনটি যে ঘড়ির গতি দেখেছে তা পরিচালনা করার জন্য আপনি ডসবক্স ব্যবহার করা ভাল ।


14
এর মধ্যে কয়েকটি গেম এমনকি কিছু ধরেও নেয়নি, তারা
যথাসম্ভব দ্রুত চালিয়েছিল

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ফাংশনগুলি ডাবল বাফারিং / ভি-সিঙ্ক ব্যবহার করে (যা ডস গেমস তৈরির সময়ে এক ধরণের ব্যয়বহুল ছিল), গেমটি সর্বোচ্চ সিপিইউ গতিতে চলবে। আধুনিক দিনে মোবাইল আই 7 এটি প্রতি সেকেন্ডে প্রায় 1,000,000 থেকে 5,000,000 বার চলবে (ল্যাপটপের কনফিগারেশন এবং বর্তমান সিপিইউ ব্যবহারের উপর নির্ভর করে)।

এর অর্থ হ'ল আমি যদি আমার bit৪ বিট উইন্ডোতে আমার আধুনিক সিপিইউতে কোনও ডস গেম কাজ করতে পারি তবে আমি এক হাজারেরও বেশি (1000!) এফপিএস পেতে পারি যা কোনও মানুষের পক্ষে খেলতে খুব দ্রুত হয় যদি পদার্থবিজ্ঞানের প্রসেসিং "ধরে নেওয়া হয়" এটি চলে তবে 50-60 fps এর মধ্যে।

বর্তমান দিনের বিকাশকারীরা (করতে পারেন) তা হ'ল:

  1. গেমটিতে ভি-সিঙ্ক সক্ষম করুন (* উইন্ডোযুক্ত অ্যাপ্লিকেশনগুলির জন্য উপলভ্য নয় ** [ওরফে শুধুমাত্র পূর্ণ-স্ক্রিন অ্যাপ্লিকেশনগুলিতে উপলব্ধ])
  2. শেষ আপডেটের মধ্যে সময়ের পার্থক্য পরিমাপ করুন এবং সময় পার্থক্য অনুযায়ী পদার্থবিজ্ঞানের আপডেট করুন যা কার্যকরভাবে এফপিএস হার নির্বিশেষে গেম / প্রোগ্রামকে একই গতিতে চালিত করে
  3. প্রোগ্রামেটিকভাবে ফ্রেমরেট সীমাবদ্ধ করুন

*** গ্রাফিক্স কার্ড / ড্রাইভার / ওএস কনফিগারেশনের উপর নির্ভর করে এটি সম্ভব হতে পারে।

পয়েন্ট 1 এর জন্য আমি দেখাব এমন কোনও উদাহরণ নেই কারণ এটি আসলে কোনও "প্রোগ্রামিং" নয়। এটি কেবল গ্রাফিক্স বৈশিষ্ট্য ব্যবহার করছে using

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+ এফপিএস পেতে পারেন কারণ লুপটি যত দ্রুত সম্ভব চলছে running যেহেতু পদার্থবিজ্ঞানের ইঞ্জিন জানে যে কত সময় কেটে গেছে, এটি "কোনও অনুমান" বা "একটি নির্দিষ্ট ফ্রেমরেট" এর উপর নির্ভর করতে হবে না সুতরাং গেমটি যে কোনও সিপিইউতে একই গতিতে কাজ করবে।

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 এমএস) তবে এটি গেমের স্ক্রিনটিকে আবার অঙ্কন করে, কার্যকরভাবে frame 30 এর কাছাকাছি একটি ফ্রেম রেট প্রয়োগ করে।

এছাড়াও, বিকাশকারী উপর নির্ভর করে তিনি উপরের কোডটি সামান্য পরিবর্তিত করে সমস্ত প্রসেসিংটি 30 fps এ সীমাবদ্ধ করতে বেছে নিতে পারেন:

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 Hz এ প্রোগ্রামটি চালিত করবে। এখন ডেটা, ইনপুট, অঙ্কন এবং সমস্ত স্টাফ প্রসেসিংয়ে 5 মিলিয়ন সেকেন্ড সময় লাগে। আমরা এখন এক লুপের জন্য 21 মিলি সেকেন্ডে আছি যার ফলস্বরূপ 50 Hz এর চেয়ে সামান্য কম হয়ে যায়, আপনি এখনও সহজেই 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 প্রসেসরের সাথে মেলে slow

ডাইরেক্টএক্সের মতো আধুনিক গেমস এবং লাইব্রেরিগুলিতে উচ্চ প্রেসিশন টাইমারগুলিতে অ্যাক্সেস রয়েছে তাই ক্যালিব্রেটেড কোড ভিত্তিক বিলম্ব লুপগুলি ব্যবহার করার দরকার নেই।


4

প্রথম সমস্ত পিসি শুরুতে একই গতিতে দৌড়েছিল, তাই গতির পার্থক্যের জন্য অ্যাকাউন্ট করার প্রয়োজন নেই।

এছাড়াও, শুরুতে বেশিরভাগ গেমগুলিতে সিপিইউ-লোড বেশ নির্ধারিত ছিল, তাই কিছু ফ্রেম অন্যদের চেয়ে দ্রুত চালিত হওয়ার সম্ভাবনা ছিল না।

আজকাল, ইয়ার বাচ্চাদের এবং ইয়ার অভিনব এফপিএস শ্যুটারগুলির সাথে আপনি এক সেকেন্ড তলটি দেখতে পারেন এবং পরের গ্র্যান্ড ক্যানিয়নে লোড-প্রকরণটি প্রায়শই ঘটে। :)

(এবং, কয়েকটি হার্ডওয়্যার কনসোল ক্রমাগত 60 fps এ গেমগুলি চালানোর জন্য যথেষ্ট দ্রুতগতির This

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.