গেম স্টেট ম্যানেজমেন্ট (গেম, মেনু, টাইটেলস্ক্রিন, ইত্যাদি)


11

মূলত, আমি এখনও অবধি তৈরি প্রতিটি খেলায় আমার কাছে সর্বদা "কারেন্ট_স্টেট" এর মত চলক থাকে যা "গেম", "শিরোনাম স্ক্রিন", "গেমওভারস্ক্রিন" ইত্যাদি হতে পারে can

এবং তারপরে আমার আপডেট ফাংশনে আমার একটি বিশাল পরিমাণ রয়েছে:

if current_state == "game" 
  game stuf
  ...
else if current_state == "titlescreen"
  ...

যাইহোক, আমি মনে করি না এটি হ্যান্ডলিং রাষ্ট্রগুলির একটি পেশাদার / পরিষ্কার উপায়। এটি কীভাবে আরও ভাল উপায়ে করা যায় সে সম্পর্কে কোনও ধারণা? নাকি এটি স্ট্যান্ডার্ড উপায়?


আপনি কোন ভাষা, কাঠামো ইত্যাদি ব্যবহার করছেন?
পেটর আব্দুলিন

সাধারণত লুয়া + ভালবাসে। আমি আরও আবিষ্কার করেছি যে বিভিন্ন ফ্রেমওয়ার্কগুলিতে এটি পরিচালনা করার বিভিন্ন উপায় রয়েছে। এসএফএমএল খুব সুন্দর স্ক্রিন ক্লাস বলে মনে হচ্ছে।
ডেভিড গমেস

1
আপনি কি রাষ্ট্রের মেশিনগুলি দেখেছেন?
দারকারা

1
আপনি উপরের ডানদিকে অনুসন্ধান বারে গেমস্টেটগুলি সন্ধান করতে পারেন। কিছু ফলাফল দেওয়া উচিত।
ট্র্যাভিসজি

অবশ্যই দ্বিতীয় দারকারা - এটি স্টেট মেশিনগুলির জন্য ঠিক ব্যবহৃত হয় for
বালাজেরেক

উত্তর:


14

যেহেতু আপনি পর্দার কথা বলছেন, তাই আমি মনে করি যে সমস্ত যুক্তিটি বিভিন্ন স্ক্রিনে আলাদা করা ভাল। আমি সাধারণত যা করি:

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

এটি আপনার যুক্তিকে খুব সুন্দরভাবে আলাদা করবে।

উদাহরণ কোড:

### Screen interface ###
public interface Screen {

    public void show();

    public void update(float delta);

    public void render(float delta);

    public void hide ();
}

### An implementation of screen ###
public class MainMenuScreen implements Screen {

    private Game game;

    public MainMenuScreen(Game game) {
        this.game = game;
    }

    public void show() {
        // init stuff
    }

    public void update(float delta) {
        // react to clicks, update animations etc.
        if (buttonwasclicked) {
            game.setScreen(new GameScreen(game)); // change the screen
        }
    }

    public void render(float delta) {
        // draw everything
    }

    public void hide() {
        // release all resources, as the screen is being hidden
    }
}

### Game, drawing the appropriate screen ###
public class Game {

    public Screen screen;

    public void update() {
        screen.update(getDeltaTime);
        screen.render();
    }

    public void setScreen(Screen screen) {
        this.screen.hide();

        this.screen = screen;
        this.screen.show();
    }
}

বা আপনার গেম সেটআপের উপর নির্ভর করে আপনার গেম হিসাবে আপনার কাছে সম্ভবত একটি অসীম লুপ রয়েছে।

while(true) {
    calculatetimesincelastframe()
    screen.update(time);
    screen.render(time);
}

5

যদি আপনি ইতিমধ্যে মধ্যবিত্ত ব্যবহার করেন, তাহলে সেখানে বরাবর সঙ্গে এটা বলা যেতে একটি চমৎকার রাষ্ট্রীয় মেশিন লাইব্রেরি Statefull । এটি ব্যবহার করা সহজ এবং ম্যাটসেম্যান প্রস্তাবিত একই ধারণাগুলি গ্রহণ করেছে।


2

যদি আপনার current_stateভেরিয়েবলটি স্ট্রিং হয় তবে লুয়ায় এটি সত্যিই সহজ:

game_states = {}
function game_states.game()
    -- game stuff
end
function game_states.titlescreen()
    -- title screen stuff
end

-- then, inside the Update function:
game_states[current_state]()

1

আমি যা করি তা মোটামুটি নিম্নরূপ:

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

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


এই উত্তরটি একটি পৃথক প্রশ্নের ভাল উত্তর ।
ম্যাটসেম্যান

তা কেমন করে? তিনি তার বিভিন্ন গেমের রাজ্যগুলি কীভাবে স্থাপন করবেন সে সম্পর্কে জিজ্ঞাসা করেছিলেন, এবং আমার সমাধানটি এখনকার মতো একটি রাষ্ট্রীয় মেশিন ব্যবহার করা নয়, বরং বিটগুলি বিভিন্ন সিস্টেমে বিভক্ত করার জন্য যা কোনও রাজ্য মেশিন নয় বরং একটি ডিএজি।
অ্যালেক্স অ্যামেস

1

লুয়া + লাভ 2 ডিতে আমি কীভাবে আমার রাজ্যগুলি সংগঠিত করব তা এখানে। এটি দীর্ঘ / যদি বিবৃতিগুলি এড়িয়ে যায়।

প্রথমত, আমি একটি বেসিক ক্লাস তৈরি করি যাতে একটি আপডেট (ডিটি) এবং রেন্ডার () পদ্ধতি থাকে। আপনি এটি হ্যান্ডলিং পদ্ধতিগুলি অনকায়ডাউন (কী) এর মতো দিতে পারেন। আমি এই শ্রেণীটিকে স্টেজ বলি, তবে পদ্ধতিগুলি প্রয়োগ করে এমন কোনও বস্তু কাজ করবে। তারপরে, আমি প্রতিটি গেম স্টেটের জন্য প্রয়োজনীয় ক্লাসগুলির জন্য একটি ক্লাসের উদাহরণ তৈরি করি। আমি তখন রাজ্যের নাম এবং রাজ্যের উদাহরণ সহ একটি কী / মান সারণী তৈরি করি। তারপরে বৈশ্বিক পরিমণ্ডলে বর্তমান স্টেটের সন্ধান করুন যাতে কোনও নির্দিষ্ট শর্ত পূরণ হলে রাজ্যগুলি এটি পরিবর্তন করতে পারে।

states = {}
states["title"] = title   -- Where title implements Stage class.
states["game"] = game     -- You could create the instance of 'game' lazily too.
currentState = "title"

function love.update(dt)
    if states[currentState] ~= nil then
       states[currentState]:update(dt) 
    end
end

-1

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

if current_state == "game" 
  game()
else if current_state == "titlescreen"
  titlescreen()

বা অন্য কোনও কিছু আপনাকে এই পদ্ধতির বিরক্ত করে (মানে আপডেট পদ্ধতিটি দীর্ঘকাল বাদে)?

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