একটি ভূমিকা প্লে গেমের লড়াইয়ের ক্রম প্রোগ্রামিং


13

আমি একটি সংক্ষিপ্ত "গেম" লেখার চেষ্টা করছি যেখানে কোনও খেলোয়াড় ঘুরে বেড়ায় এবং দানবদের সাথে লড়াই করে তবে যুদ্ধটি কীভাবে পরিচালনা করতে হয় সে সম্পর্কে আমার কোনও ধারণা নেই।

উদাহরণস্বরূপ, বলুন আমার কাছে একটি "ওয়ারিয়র" এবং একটি "ট্রোল" রয়েছে। কীভাবে দু'জন একে অপরের লড়াই করে? আমি জানি আমি এর মতো কিছু করতে পারি

Conan = Warrior.new();
CaveTroll = Troll.new();
Conan.attack(CaveTroll);
CaveTroll.attack(Conan);

তবে গেমের কোন অংশটি দৈত্যটিকে নিয়ন্ত্রণ করে? আমি কি উপরের ক্রমটি কেবল একটি লুপে আটকে দেব যতক্ষণ না তাদের একজন মারা যায়? বা গেম "ইঞ্জিন" এর একটি অংশ থাকা দরকার যা বিশেষত যুদ্ধের সাথে সম্পর্কিত? বা এটি কী ট্রোলের কৃত্রিম বুদ্ধিমত্তার কোনও দিক যা এর ক্রিয়াকলাপগুলির যত্ন নেওয়া প্রয়োজন?

এছাড়াও, দৈত্যটি গ্রহণ করে এমন ক্রিয়াগুলি কে / কি নির্ধারণ করে? হতে পারে কোনও ট্রল বশ করতে পারে, লাথি মারতে পারে, কামড় দিতে পারে, মন্ত্রকে কাস্ট করতে পারে, পশন করতে পারে, মায়াবী আইটেম ব্যবহার করতে পারে। গেম ইঞ্জিন নির্ধারণ করে যে ট্রোলটি কী পদক্ষেপ নেয় বা এটি ট্রল শ্রেণি যে কোনও কিছু পরিচালনা করে?

দুঃখিত আমি আরও সুনির্দিষ্ট হতে পারি না তবে এর সাথে কোন দিকে যেতে হবে সে সম্পর্কে আমার কিছু গাইডেন্স দরকার।


শান্ত! জানত না যে সাইটটির অস্তিত্ব রয়েছে। আমি কি আমার প্রশ্নটি সেখানে সরিয়ে নিতে পারি? বা আমি কি কেবল সেখানে এটি কাটা / আটকানো উচিত?

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

@ ফেন্ডো আমি জিজ্ঞাসা করার জন্য ক্ষমাপ্রার্থী, তবে আপনি কোন সাইটটি বোঝাতে চাইছেন? গেম দেব?
ব্যবহারকারী 712092

উত্তর:


12

আমি আপনার গেমের মধ্যে মিনিগেম হিসাবে যুদ্ধের অনুক্রমটি কল্পনা করি। আপডেট টিক্স (বা টার্ন টিক্স) এই ইভেন্টগুলি পরিচালনা করে এমন কোনও উপাদানকে নির্দেশিত হয়। আপনার এই গেমের লুপটি গেমের রাজ্যের মধ্যে পরিবর্তনের জন্য মুক্ত রেখে এই পদ্ধতিকে একটি পৃথক শ্রেণিতে যুদ্ধের অনুক্রম যুক্তি যুক্ত করে।

void gameLoop() {
    while(gameRunning) {
        if (state == EXPLORATION) {
            // Perform actions for when player is simply walking around
            // ...
        }
        else if (state == IN_BATTLE) {
            // Perform actions for when player is in battle
            currentBattle.HandleTurn()
        }
        else if (state == IN_DIALOGUE) {
            // Perform actions for when player is talking with npcs
            // ...
        }
    }

}

যুদ্ধের অনুক্রমের শ্রেণিটি দেখতে এইরকম হবে:

class BattleSequence {
    public:
        BattleSequence(Entity player, Entity enemy);
        void HandleTurn();
        bool battleFinished();

    private:
        Entity currentlyAttacking;
        Entity currentlyReceiving;
        bool finished;
}

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

void HandleTurn() {
    // Perform turn actions
    currentlyAttacking.fight(currentlyReceiving);

    // Switch sides
    Entity temp = currentlyAttacking;
    currentlyAttacking = currentlyReceiving;
    currentlyReceiving = temp;

    // Battle end condition
    if (currentlyReceiving.isDead() || currentlyAttacking.hasFled()) {
        finished = true;
    }
}

সত্তাটি কী করতে চলেছে তা যুদ্ধের পদ্ধতিটি স্থির করে। নোট করুন যে এর জন্য বিরোধী সত্তাকে জড়িত করার দরকার নেই, যেমন দোলা খাওয়া বা পালানো।

আপডেট: একাধিক দানব এবং একটি প্লেয়ার পার্টি সমর্থন করতে, আপনি একটি গ্রুপ শ্রেণি প্রবর্তন:

class Group {
    public:
        void fight(Group opponents) {
            // Loop through all group members so everyone gets
            // a shot at the opponents
            for (int i = 0; i < memberCount; i++) {
                Entity attacker = members[i];
                attacker.fight(opponents);
            }
        }

        Entity get(int targetID) {
            // TODO: Bounds checking
            return members[targetID];
        }

        bool isDead() {
            bool dead = true;
            for (int i = 0; i < memberCount; i++) {
                dead = dead && members[i].isDead();
            }
            return dead;
        }

        bool hasFled() {
            bool fled = true;
            for (int i = 0; i < memberCount; i++) {
                fled = fled && members[i].hasFled();
            }
            return fled;
        }

    private:
        Entity[] members;
        int memberCount;
}

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

class Entity {
    public:
        void fight(Group opponents) {
            // Algorithm for selecting an entity from the group
            // ...
            int targetID = 0; // Or just pick the first one

            Entity target = opponents.get(targetID);

            // Fighting algorithm
            target.applyDamage(10);
        }
}

আমি ধরে নিচ্ছি এটি কেবল একজন খেলোয়াড় বনাম একটি দানব হিসাবে কাজ করবে। অথবা একাধিক দানব বনাম একটি প্লেয়ারের পক্ষে কাজ করা কি এটি আপডেট করা সহজ হবে?
হার্ভ

উভয় দানব প্লেয়ারকে প্লেয়ার সাইড হিসাবে গ্রুপগুলির জন্য সমর্থন যুক্ত করা বেশ সহজ (আপনার পরিস্থিতিতে প্লেয়ার গ্রুপে কেবলমাত্র একজন সদস্য থাকবে: প্লেয়ারের চরিত্র)। আমি এই দৃশ্যের জন্য উত্তর আপডেট করেছি।
ভুত

1

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

গৃহীত পদক্ষেপের জন্য, আপনি অবশ্যই এটিকে এলোমেলো করে তুলতে পারেন, তবে পুরো এইচপি সহ কোনও দৈত্যের জন্য নিরাময়ের বানানটি ছুঁড়ে ফেলা উচিত নয়। কোন পদক্ষেপ গ্রহণ করবে তা নির্ধারণের জন্য এটিতে কিছু প্রাথমিক যুক্তি রয়েছে বলে অর্থ প্রদান করে। উদাহরণস্বরূপ, কিছু ক্রিয়াকলাপ অন্যদের তুলনায় বেশি অগ্রাধিকার পেতে পারে (যেমন ট্রল 30% সময় কিক করে), পাশাপাশি যুদ্ধগুলি আরও আকর্ষণীয় করার জন্য অন্যান্য শর্তাদি (যেমন ট্রল এইচপি পূর্ণ এইচপির 10% এর কম হয়, সেখানে 20% থাকে নিরাময় স্পেল castালাইয়ের সম্ভাবনা, অন্যথায় সুযোগটি 1%)। এটি আপনার পছন্দ মতো জটিল হতে পারে।

আমি মনে করি দানব শ্রেণীর কী পদক্ষেপ নেওয়া উচিত তা নির্বাচন করে পরিচালনা করা উচিত, যুদ্ধের বিষয়টি দৈত্যটিকে একটি ক্রিয়া জিজ্ঞাসা করে এবং দানব একটি পছন্দ করে এবং তারপরে এটি প্রয়োগ করতে এগিয়ে যায়। একটি ধারণা হ'ল একটি কৌশল অবজেক্ট যা আপনি দানবগুলিতে প্লাগ করেন এবং যা প্রতিটি যুদ্ধের ক্রিয়াকলাপের জন্য নির্ধারিত অগ্রাধিকার, বিভাগ এবং শর্তাদির ভিত্তিতে সম্ভাব্য দানব ক্রিয়াগুলির তালিকা থেকে নির্বাচন করে। তারপরে আপনার কাছে একটি আক্রমণাত্মক স্ট্র্যাটেজি ক্লাস থাকতে পারে যা প্রতিরক্ষামূলক দক্ষতার তুলনায় আক্রমণকে অগ্রাধিকার দেয় এবং আর একটি সতর্কতত্ত্ব যা নিরাময়ের সম্ভাবনা বেশি। একজন বস তার বর্তমান অবস্থার উপর ভিত্তি করে কৌশলগতভাবে কৌশল পরিবর্তন করতে সক্ষম হবেন।

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


1

হ্যাঁ, আপনার ইঞ্জিনে একটি বিশেষ অংশ থাকা দরকার যা যুদ্ধ পরিচালনা করে।

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

এআই সম্পর্কে, আমি মনে করি ইঞ্জিনটি এটি নিজেই পরিচালনা করা দরকার, যাতে বলা যাক যে আপনার একাধিক শত্রু রয়েছে যা একই কাজ করতে পারে (কামড়), আপনি কেবল এআইকে অন্য দানবকে অর্পণ করতে পারেন এবং সেখানে আপনি যান!


0

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

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

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

class Main
{

//...members variables...
var model:GameModel = new GameModel();

//...member functions...
function realTimeUpdate() //called x times per second, on a timer.
{
    for each (var entity in model.entities)
    {
        //command processing
        if (entity == player)
            decideActionsFromPlayerInput(entity);
        else //everyone else is your enemy!
            decideActionsThroughDeviousAI(entity);

        act(entity);
    }
}
//OR
function turnBasedUpdate()
{
    if (model.whoseTurn == "player")
    {
        decideActionsFromInput(model.player); //may be some movement or none at all
        act(player);
    }
    else
    {
        var enemy;
        for each (var entity in model.entities)
        {
            if (entity != model.player)
            {
                enemy = entity;
                decideActions(enemy);
                act(enemy);
            }
        }
    }
}

//AND THEN... (common to both turn-based and real-time)
function decideActionsThroughDeviousAI(enemy)
{
    if (distanceBetween(enemy, player) <= enemy.maximumAttackDistance)
        storeAttackCommand(enemy, "kidney punch", model.player);
    else
        storeMoveCommand(player, getVectorFromTo(enemy, model.player));

}

function decideActionsFromPlayerInput(player)
{
    //store commands to your player data based on keyboard input
    if (KeyManager.isKeyDown("A"))
        storeMoveCommand(player, getForwardVector(player));
    if (KeyManager.isKeyDown("space"))
        storeAttackCommand(player, "groin slam", currentlyHighlightedEnemy);
}
function storeAttackCommand(entity, attackType, target)
{
    entity.target = target;

    entity.currentAttack = attackType;
    //OR
    entity.attackQueue.add(attackType);
}
function storeMoveCommand(entity, motionVector)
{
    entity.motionVector = motionVector;
}
function act(entity)
{
    entity.position += entity.motionVector;
    attack(entity.target, entity.currentAttack);
}
}

class GameModel
{
    var entities:Array = []; //or List<Entity> or whatever!
    var player:Entity; //will often also appear in the entity list, above
    var difficultyLevel:int;
    var globalMaxAttackDamage:int;
    var whoseTurn:Boolean; //if turnbased
    //etc.

}

একটি চূড়ান্ত নোট এটি আপনার গেম যুক্তি থেকে আপনার প্রদর্শন লজিক পৃথক রাখা দরকারী। ডিসপ্লে যুক্তিযুক্ত হবে, "আমি এটি পর্দায় কোথায় আঁকবো এবং কোন রঙে?" বনাম। গেম যুক্তি যা আমি উপরের সিউডকোডে উল্লেখ করেছি।

(দেবের দ্রষ্টব্য: ক্লাসগুলি ব্যবহার করার সময়, এটি আলগাভাবে একটি কার্যকরী প্রোগ্রামিং পদ্ধতির অনুসরণ করে যা সমস্ত পদ্ধতিকে আদর্শিকভাবে রাষ্ট্রহীন হিসাবে বিবেচনা করে, একটি পরিষ্কার ডেটা মডেল এবং প্রসেসিং পদ্ধতির জন্য অনুমতি দেয় যা বজায় থাকা অবস্থায় সৃষ্ট বাগগুলি কমিয়ে দেয় F এফপি চূড়ান্ত এমভিসি, যেহেতু এটি এমভিসি'র অর্জন করে উদ্বেগের স্পষ্টভাবে বিচ্ছিন্নকরণের লক্ষ্য this এই প্রশ্নটি দেখুন ))


1
"একটি একক, প্রধান মডেল অবজেক্ট রাখুন যা আপনার বিশ্বের সমস্ত বিবরণ বর্ণনা করে। অসুবিধা এবং পদার্থবিজ্ঞানের পরামিতি? উদ্বেগের সংঘাতের কথা বলুন! -1।

2
@ জো - আপনি কি আমার কাছে পুরো কনফিগারেশন শ্রেণিবিন্যাসের রূপরেখা চান? আমরা এখানে এটি সহজ রাখছি, আমরা না? ডাউনটিটিংয়ের আগে আপনি যদি ভাবেন তবে আমি প্রশংসা করব।
প্রকৌশলী

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

1
@ জো: আমি সম্মত হই যে এমভিসি একটি গেমের জন্য মোটামুটি পছন্দ, তবে আমি খুব নিশ্চিত যে এখানে ভি এর ভূমিকা সুস্পষ্ট।
জাচ কন কন

4
@ জাচ: যখন "এফপি চূড়ান্ত এমভিসি" এর মতো দাবি করা হয়, তখন পোস্টারটি এমভিসি এবং ফাংশনাল প্রোগ্রামিং উভয়ই বুঝতে ব্যর্থ হয় except
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.