গেম অবজেক্টগুলি একে অপর সম্পর্কে সচেতন হওয়া উচিত?


18

গেমের অবজেক্টগুলিকে সংগঠিত করার উপায় খুঁজে পাওয়া আমার পক্ষে কঠিন মনে হয় যাতে তারা বহুকর্মী হয় তবে একই সাথে বহুবর্ষীয় হয় না।

এখানে একটি উদাহরণ রয়েছে: ধরে নিই যে আমরা আমাদের সমস্ত বস্তুর কাছে যেতে চাই update()এবং করি draw()। এটি করার জন্য আমাদের একটি বেস ক্লাসটি সংজ্ঞায়িত করতে হবে GameObjectযা এই দুটি ভার্চুয়াল খাঁটি পদ্ধতি রয়েছে এবং বহুকীতাবাদকে লাথি মারতে দিন:

class World {
private:
    std::vector<GameObject*> objects;
public:
    // ...
    update() {
        for (auto& o : objects) o->update();
        for (auto& o : objects) o->draw(window);
    }
};

আপডেট পদ্ধতিটি নির্দিষ্ট শ্রেণীর অবজেক্টটি আপডেট করার জন্য যে অবস্থায় থাকতে পারে তার যত্ন নেওয়ার কথা। আসল বিষয়টি হ'ল প্রতিটি বস্তুর চারপাশের বিশ্ব সম্পর্কে জানা থাকা দরকার। উদাহরণ স্বরূপ:

  • একটি খনি এটির সাথে সংঘর্ষ করছে কিনা তা জানা দরকার
  • অন্য সৈন্যের সান্নিধ্যে আছে কিনা তা একজন সৈনিকের জানা উচিত
  • একটি জুম্বির জানা উচিত যে ব্যাসার্ধের মধ্যে নিকটতম মস্তিষ্কটি কোথায়

প্যাসিভ ইন্টারঅ্যাকশনগুলির জন্য (প্রথমটির মতো) আমি ভাবছিলাম যে সংঘর্ষ সনাক্তকরণের সাথে কোনও বস্তুর সাথে সংঘর্ষের নির্দিষ্ট ক্ষেত্রে কী করা উচিত তা হ'ল on_collide(GameObject*)

অন্যান্য তথ্য (বেশিরভাগ দুটি উদাহরণের মতো) এর বেশিরভাগই গেম ওয়ার্ল্ড updateপদ্ধতিতে পাস করে সন্ধান করতে পারে । এখন পৃথিবী তাদের ধরণের উপর ভিত্তি করে অবজেক্টগুলিকে আলাদা করে না (এটি একটি একক বহুবাহী পাত্রে সমস্ত বস্তু সংরক্ষণ করে), সুতরাং বাস্তবে এটি কোন আদর্শের সাথে ফিরে আসবে world.entities_in(center, radius)এটি একটি ধারক GameObject*। তবে অবশ্যই সৈনিকটি তার দল থেকে অন্য সৈন্যদের আক্রমণ করতে চায় না এবং একটি জম্বি অন্যান্য জম্বিদের বিষয়ে মামলা করে না। সুতরাং আমাদের আচরণের পার্থক্য করা দরকার। একটি সমাধান নিম্নলিখিত হতে পারে:

void TeamASoldier::update(const World& world) {
    auto list = world.entities_in(position, eye_sight);
    for (const auto& e : list)
        if (auto enemy = dynamic_cast<TeamBSoldier*>(e))
            // shoot towards enemy
}

void Zombie::update(const World& world) {
    auto list = world.entities_in(position, eye_sight);
    for (const auto& e : list)
        if (auto enemy = dynamic_cast<Human*>(e))
            // go and eat brain
}

তবে অবশ্যই dynamic_cast<>প্রতি ফ্রেমের সংখ্যা মারাত্মকভাবে বেশি হতে পারে এবং আমরা সকলেই জানি কতটা ধীর dynamic_castহতে পারে। একই সমস্যাটি সেই on_collide(GameObject*)প্রতিনিধিদের ক্ষেত্রেও প্রযোজ্য যা আমরা আগে আলোচনা করেছি।

সুতরাং কোডটি সংগঠিত করার এটি কী আদর্শ উপায় যাতে বস্তুগুলি অন্য বস্তুর বিষয়ে সচেতন হতে পারে এবং তাদের উপেক্ষা করতে বা তাদের ধরণের ভিত্তিতে পদক্ষেপ নিতে সক্ষম হয়?


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

আমি গেম যুক্তির জন্য টাইপ সিস্টেমটি ব্যবহার করার বিরুদ্ধে পরামর্শ দেব। উদাহরণস্বরূপ, পরিবর্তে ফলাফলের উপর নির্ভর করে এর dynamic_cast<Human*>একটা ভালো কিছু বাস্তবায়ন bool GameObject::IsHuman(), যা আয় falseডিফল্টরূপে কিন্তু ফিরে যাওয়ার উপেক্ষা করা হয় trueমধ্যে Humanবর্গ।
কংগ্রেসবঙ্গাস

একটি অতিরিক্ত: আপনি প্রায় কখনও একে অপরের সত্তায় কোনও টন অবজেক্ট প্রেরণ করেন না যা তাদের আগ্রহী হতে পারে। এটি একটি প্রকৃত অপ্টিমাইজেশন যা আপনাকে সত্যই বিবেচনা করতে হবে।
teodron

@ কংগসবঙ্গাস একটি ভেটেবল এবং কাস্টম IsAওভাররাইড ব্যবহার করা আমার পক্ষে অনুশীলনে গতিশীল কাস্টিংয়ের চেয়ে সামান্যতম ভাল প্রমাণিত হয়েছিল। সর্বোত্তম কাজটি হ'ল ব্যবহারকারীর পক্ষে, যেখানেই সম্ভব, পুরো সত্তা পুলে অন্ধভাবে পুনরাবৃত্তি করার পরিবর্তে ডেটা তালিকা সাজানো।
teodron

4
@ জেফফ্রে: আদর্শভাবে আপনি টাইপ-নির্দিষ্ট কোড লিখেন না। আপনি ইন্টারফেস- স্পেসিফিক কোড লিখুন (সাধারণ অর্থে "ইন্টারফেস")। একটি জন্য যুক্তিবিজ্ঞান TeamASoldierএবং TeamBSoldierসত্যিই অভিন্ন - অন্য দলের কাউকে গুলি করে। অন্যান্য সত্তাগুলির এটির জন্য প্রয়োজনীয় সমস্ত একটিGetTeam() এটির সুনির্দিষ্ট পদ্ধতি এবং কংগাসবঙ্গাসের উদাহরণ অনুসারে, এটি আরও IsEnemyOf(this)ধরণের ইন্টারফেসে বিমূর্ত করা যেতে পারে । কোডটিতে সৈন্যদল, জম্বি, খেলোয়াড় ইত্যাদির আঞ্চলিক শ্রেণিবিন্যাস সম্পর্কে যত্ন নেওয়ার দরকার নেই types
শান মিডলডিচ

উত্তর:


11

প্রতিটি সত্তার সিদ্ধান্ত গ্রহণ নিজের মধ্যে বাস্তবায়ন করার পরিবর্তে আপনি বিকল্পভাবে নিয়ামক-প্যাটার্নে যেতে পারেন। আপনার কাছে কেন্দ্রীয় কন্ট্রোলার ক্লাস থাকবে যা সমস্ত বিষয় সম্পর্কে সচেতন (যা তাদের কাছে গুরুত্বপূর্ণ) এবং তাদের আচরণ নিয়ন্ত্রণ করে।

একটি মুভমেন্টকন্ট্রোলার সমস্ত পদার্থের চলাচল পরিচালনা করতে পারে যা চলতে পারে (বর্তমান চলন ভেক্টরের উপর ভিত্তি করে রুট সন্ধান, অবস্থান আপডেট করা)।

একজন মাইনবিহেভিয়ারকন্ট্রোলার সমস্ত খনি এবং সমস্ত সৈন্যদের পরীক্ষা করত এবং যখন কোন সৈনিক খুব কাছে আসে তখন বিস্ফোরণে একটি খনিকে নির্দেশ দেয়।

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

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


1
সম্ভবত এটি "সিস্টেম" নামেও পরিচিত যা একটি সত্ত্বা-উপাদান উপাদানগুলির মধ্যে কিছু ধরণের উপাদানগুলির জন্য যুক্তি পরিচালনা করে।
teodron

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

1
@ জেফফ্রে "এটি সি-স্টাইলের সমাধানের মতো মনে হচ্ছে" - এমনকি যখন এটি সত্য হবে, তবে কেন এটি অগত্যা খারাপ জিনিস হবে? অন্যান্য উদ্বেগগুলি বৈধ হতে পারে তবে তাদের সমাধান রয়েছে। দুর্ভাগ্যক্রমে তাদের মন্তব্যগুলির সঠিকভাবে সম্বোধন করার জন্য একটি মন্তব্য খুব ছোট short
ফিলিপ

1
@ জেফফ্রে এমন পদ্ধতির ব্যবহার করে যেখানে উপাদানগুলির নিজস্ব কোনও যুক্তি নেই এবং "যুক্তিসঙ্গত" সমস্ত যুক্তি পরিচালনা করার জন্য দায়বদ্ধ সেগুলি উপাদানগুলির মধ্যে নির্ভরতা তৈরি করে না এবং এটির জন্য সুপার কমপ্লেক্স মেসেজিং সিস্টেমের প্রয়োজন নেই (কমপক্ষে প্রায় জটিল নয়) । উদাহরণস্বরূপ দেখুন: gamadu.com/artemis/tutorial.html

1

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

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

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

সুতরাং আপনি একবার ফ্রেম প্রতি যা করেন তা হ'ল 1. বর্তমান বস্তুগুলি বাফার করুন - বিশ্বব্যাপী রাষ্ট্রটি স্থির করুন, ২. নিজের এবং বাফারের উপর ভিত্তি করে সমস্ত বস্তু আপডেট করুন, ৩. আপনার বস্তুগুলি আঁকুন এবং তারপরে বাফার পুনর্নবীকরণের সাথে শুরু করুন।


1

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

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

এখন বলুন যে কোনও গেমের অবজেক্টটি আস্তে আস্তে সব সময় ঘোরার কথা, আপনি একটি পৃথক উপাদান তৈরি করতে পারেন যা কেবল এটি করে এবং এটি গেমওজেক্টের সাথে সংযুক্ত করে।

আপনি যদি এমন কোনও চলমান প্ল্যাটফর্ম থাকতে চান যা ঘোরানোও ছিল, একটি traditionalতিহ্যবাহী শ্রেণীর উত্তরাধিকার সূত্রে কোডটি নকল ছাড়াই করা কঠিন হয়ে পড়ে।

এই সিস্টেমটির সৌন্দর্যটি হ'ল যে কোনও ঘূর্ণনযোগ্য বা একটি মুভিংপ্ল্যাটফর্ম ক্লাস না করে আপনি সেই দুটি উপাদান গেমবজেক্টের সাথে সংযুক্ত করেছেন এবং আপনার এখন একটি মুভিংপ্ল্যাটফর্ম রয়েছে যা অটোরেটেটস।

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

টনি হক হক প্রো স্কেটার বিকাশকারীদের মধ্যে একটিতে এটিতে ডিফাক্টো লেখা রয়েছে এবং এটি পড়ার পক্ষে ভাল: http://COboyprogramming.com/2007/01/05/evolve-your-heirachy/


1

উত্তরাধিকারের উপরে পছন্দসই রচনা।

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

এই নিবন্ধটি দৃ rob় এবং পারফরম্যান্স সত্তা-উপাদান আর্কিটেকচারের মাধ্যমে গেমস বিকাশে উত্তরাধিকারের ওপরে রচনা নীতিটির অন্তর্দৃষ্টি দেয়।

পূর্বনির্ধারিত উপাদানগুলির কিছু সুপারসেটের (পৃথক) সাবসেটের বাইরে সত্ত্বা তৈরির মাধ্যমে, আপনি আপনার এআই কংক্রিট, বিশ্ব এবং তাদের চারপাশের অভিনেতাদের 'উপাদানগুলি' স্টেটগুলি পড়ে বোঝার ক্ষুদ্রতর উপায় সরবরাহ করেন।


1

ব্যক্তিগতভাবে আমি ড্র ফাংশনটি অবজেক্ট ক্লাসের বাইরে রাখার পরামর্শ দিই। এমনকি আমি অবজেক্টগুলির অবস্থান / স্থানাঙ্কগুলি অবজেক্টের বাইরে রাখার প্রস্তাব দিই।

সেই অঙ্কন () পদ্ধতিটি ওপেনজিএল, ওপেনজিএল ইএস, ডাইরেক্ট 3 ডি, সেই এপিআইগুলিতে আপনার মোড়ক স্তর বা ইঞ্জিন এপিআই এর নিম্ন স্তরের রেন্ডারিং এপিআই নিয়ে কাজ করবে। এটি হতে পারে যে আপনি সেই সময়ের মধ্যে অদলবদল করতে হবে (আপনি যদি ওপেনজিএল + ওপেনজিএল ইএস + ডাইরেক্ট 3 ডি সমর্থন করতে চান তবে।

গেমওজেক্টে কেবল এটির দৃশ্যমান চেহারা সম্পর্কে প্রাথমিক তথ্য যেমন মেশ বা শ্যাডার ইনপুট, অ্যানিমেশন পরিস্থিতি সহ আরও একটি বড় বান্ডিল থাকতে হবে।

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

আমি যা প্রস্তাব দিচ্ছি তা সরাসরি আঁকার পরিবর্তে আপনি যে সমস্ত বস্তুকে অন্য ডেটা স্ট্রাকচারে বাঁধতে চান তা আপনি বেঁধে রাখুন। এই বাঁধাইয়ের জন্য কেবলমাত্র অবজেক্টের অবস্থান এবং রেন্ডারিং তথ্য সম্পর্কিত একটি রেফারেন্স থাকা দরকার।

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

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

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

আপনি যখন কোনও স্তরে কোনও অবজেক্ট যুক্ত করেন। এটি নিম্নলিখিতগুলি করবে:

1) একটি অবস্থান কাঠামো তৈরি করুন:

 class Location { 
     float x, y, z; // Or a special Coordinates class, or a vec3 or whatever.
     SpacialIndex& spacialIndex; // Note this could be the area/level/map/whatever here
 };

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

আপনি যদি গতিশীল মেমরি বরাদ্দ সম্পর্কে উদ্বিগ্ন হন তবে একটি মেমরি পুল ব্যবহার করুন।

2) আপনার অবজেক্টের অবস্থান এবং দৃশ্য গ্রাফের মধ্যে একটি আবদ্ধ / লিঙ্কিং।

typedef std::pair<Object, Location> SpacialBinding.

3) বাইন্ডিংটি উপযুক্ত বিন্দুতে স্তরের ভিতরে ফাঁকা সূচকগুলিতে যুক্ত হয়।

আপনি যখন রেন্ডার করার প্রস্তুতি নিচ্ছেন।

1) ক্যামেরা পান (এটি ঠিক অন্য কোনও জিনিস হবে, এটির অবস্থান ব্যতীত প্লেয়ারের চরিত্রটি ট্র্যাক করবে এবং আপনার রেন্ডারারের কাছে এটির একটি বিশেষ রেফারেন্স থাকবে, বাস্তবে এটির সত্যই প্রয়োজন।

2) ক্যামেরার স্প্যাসিয়াল বাইন্ডিং পান।

3) বাইন্ডিং থেকে স্পেসিয়াল সূচক পান।

৪) ক্যামেরাটিতে দৃশ্যমান (সম্ভবত) প্রদর্শিত অবজেক্টগুলিকে জিজ্ঞাসা করুন।

5 এ) আপনার ভিজ্যুয়াল তথ্য প্রক্রিয়া করা প্রয়োজন। টেক্সচারগুলি জিপিইউতে আপলোড হয়েছে on এটি অগ্রিমভাবে সম্পন্ন করা হবে (যেমন স্তরের লোড হিসাবে) তবে সম্ভবত রানটাইমের সময় করা যেতে পারে (একটি উন্মুক্ত বিশ্বের জন্য, আপনি যখন কোনও অংশের কাছে পৌঁছানোর সময় জিনিসপত্র লোড করতে পারেন তবে এখনও আগাম সম্পন্ন করা উচিত)।

5 বি) depthচ্ছিকভাবে একটি ক্যাশেড রেন্ডার ট্রি তৈরি করুন, যদি আপনি গভীরতা / উপাদান বাছাই করতে চান বা নিকটবর্তী বস্তুগুলির ট্র্যাক রাখতে চান যা পরবর্তী সময়ে দৃশ্যমান হতে পারে। অন্যথায় আপনি কেবলমাত্র স্পেসিয়াল ইনডেক্সটি প্রতিবারই জিজ্ঞাসা করতে পারেন এটি আপনার গেম / পারফরম্যান্সের প্রয়োজনীয়তার উপর নির্ভর করবে।

আপনার রেন্ডারারের সম্ভবত একটি রেন্ডারবাইন্ডিং অবজেক্টের প্রয়োজন হবে যা অবজেক্ট, স্থানাঙ্কগুলির মধ্যে লিঙ্ক করবে

class RenderBinding {
    Object& object;
    RenderInformation& renderInfo;
    Location& location // This could just be a coordinates class.
}

তারপরে আপনি যখন রেন্ডার করেন, কেবল তালিকা অনুযায়ী চালান।

আমি উপরে রেফারেন্স ব্যবহার করেছি তবে সেগুলি স্মার্ট পয়েন্টার, কাঁচা পয়েন্টার, অবজেক্ট হ্যান্ডেলস এবং আরও হতে পারে।

সম্পাদনা করুন:

class Game {
    weak_ptr<Camera> camera;
    Level level1;

    void init() {
        Camera camera(75.0_deg, 1.025_ratio, 1000_meters);
        auto template_player = loadObject("Player.json")
        auto player = level1.addObject(move(player), Position(1.0, 2.0, 3.0));
        level1.addObject(move(camera), getRelativePosition(player));

        auto template_bad_guy = loadObject("BadGuy.json")
        level1.addObject(template_bad_guy, {10, 10, 20});
        level1.addObject(template_bad_guy, {10, 30, 20});
        level1.addObject(move(template_bad_guy), {50, 30, 20});
    }

    void render() {
        camera->getFrustrum();
        auto level = camera->getLocation()->getLevel();
        auto object = level.getVisible(camera);
        for(object : objects) {
            render(objects);
        }
    }

    void render(Object& object) {
        auto ri = object.getRenderInfo();
        renderVBO(ri.getVBO());
    }

    Object loadObject(string file) {
        Object object;
        // Load file from disk and set the properties
        // Upload mesh data, textures to GPU. Load shaders whatever.
        object.setHitPoints(// values from file);
        object.setRenderInfo(// data from 3D api);
    }
}

class Level {
    Octree octree;
    vector<ObjectPtr> objects;
    // NOTE: If your level is mesh based there might also be a BSP here. Or a hightmap for an openworld
    // There could also be a physics scene here.
    ObjectPtr addObject(Object&& object, Position& pos) {
        Location location(pos, level, object);
        objects.emplace_back(object);
        object->setLocation(location)
        return octree.addObject(location);
    }
    vector<Object> getVisible(Camera& camera) {
        auto f = camera.getFtrustrum();
        return octree.getObjectsInFrustrum(f);
    }
    void updatePosition(LocationPtr l) {
        octree->updatePosition(l);
    }
}

class Octree {
    OctreeNode root_node;
    ObjectPtr add(Location&& object) {
        return root_node.add(location);
    }
    vector<ObjectPtr> getObjectsInRadius(const vec3& position, const float& radius) { // pass to root_node };
    vector<ObjectPtr> getObjectsinFrustrum(const FrustrumShape frustrum;) {//...}
    void updatePosition(LocationPtr* l) {
        // Walk up from l.octree_node until you reach the new place
        // Check if objects are colliding
        // l.object.CollidedWith(other)
    }
}

class Object {
    Location location;
    RenderInfo render_info;
    Properties object_props;
    Position getPosition() { return getLocation().position; }
    Location getLocation() { return location; }
    void collidedWith(ObjectPtr other) {
        // if other.isPickup() && object.needs(other.pickupType()) pick it up, play sound whatever
    }
}

class Location {
    Position position;
    LevelPtr level;
    ObjectPtr object;
    OctreeNote octree_node;
    setPosition(Position position) {
        position = position;
        level.updatePosition(this);
    }
}

class Position {
    vec3 coordinates;
    vec3 rotation;
}

class RenderInfo {
    AnimationState anim;
}
class RenderInfo_OpenGL : public RenderInfo {
    GLuint vbo_object;
    GLuint texture_object;
    GLuint shader_object;
}

class Camera: public Object {
    Degrees fov;
    Ratio aspect;
    Meters draw_distance;
    Frustrum getFrustrum() {
        // Use above to make a skewed frustum box
    }
}

একে অপরের সম্পর্কে 'সচেতন' করার জন্য। এটি সংঘর্ষ সনাক্তকরণ। এটি সম্ভবত অক্টোবরে কার্যকর করা হবে। আপনার মূল অবজেক্টে আপনাকে কিছু কলব্যাক সরবরাহ করতে হবে। এই জিনিসগুলি বুলেটের মতো উপযুক্ত পদার্থবিজ্ঞানের ইঞ্জিন দ্বারা সর্বোত্তমভাবে পরিচালিত হয়। সেক্ষেত্রে কেবল অস্ট্রির সাথে পদার্থবিজ্ঞান এবং অবস্থানের সাথে কোলিশনমেশ.সেটপজিশন () এর মতো কোনও লিঙ্ক যুক্ত করুন with


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

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