কিভাবে গেম ইঞ্জিনগুলিতে হার্ড কোডিং এড়ানো যায়


22

আমার প্রশ্ন একটি কোডিং প্রশ্ন নয়; এটি সাধারণভাবে গেম ইঞ্জিন ডিজাইনের সমস্ত ক্ষেত্রে প্রযোজ্য।

আপনি কীভাবে হার্ড কোডিং এড়াবেন?

এই প্রশ্নটি মনে হয় অনেক গভীর। বলুন, আপনি যদি এমন কোনও গেম চালাতে চান যা অপারেশনের জন্য প্রয়োজনীয় ফাইলগুলি লোড করে, আপনি কীভাবে load specificfile.wadইঞ্জিনের কোডে কিছু বলা এড়াতে পারবেন ? এছাড়াও, ফাইলটি লোড হওয়ার পরে, আপনি কীভাবে এড়ানো করবেন load aspecificmap in specificfile.wad?

এই প্রশ্নটি পুরো ইঞ্জিন ডিজাইনের ক্ষেত্রে প্রযোজ্য এবং ইঞ্জিনের যতটা সম্ভব কম কোড করা উচিত। এটি অর্জনের সেরা উপায় কী?

উত্তর:


42

ডেটা-চালিত কোডিং

আপনার উল্লেখ করা প্রতিটি জিনিসই এমন কিছু যা ডেটাতে নির্দিষ্ট করা যায়। আপনি কেন বোঝাচ্ছেন?aspecificmap ? কারণ গেম কনফিগারেশনটি বলে যে কোনও খেলোয়াড় নতুন গেম শুরু করার সময় এটি প্রথম স্তর, বা যে কারণ প্লেয়ারের সেভ ফাইলের বর্তমান সেভ পয়েন্টের নাম এটি হ'ল তারা ইত্যাদি save

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

কেবলমাত্র "মূল" সংস্থানগুলির একটি বিশেষ সংখ্যক সেট থাকা দরকার যা হার্ড কোডিং এড়ানোর জন্য বৈধভাবে শক্ত বা অসম্ভব। কিছুটা কাজ করে, এটি একক হার্ড-কোডেড ডিফল্ট সম্পদ নামের মতো main.wadবা পছন্দ মতোই সীমাবদ্ধ থাকতে পারে । এই ফাইলটি সম্ভবত রানটাইমে গেমের কাছে কমান্ড-লাইন আর্গুমেন্ট পেরিয়ে পরিবর্তন করা যেতে পারে akagame.exe -wad mymain.wad

ডেটা-চালিত কোড লেখার জন্য কয়েকটি অন্যান্য নীতির উপর নির্ভর করে। উদাহরণস্বরূপ, সিস্টেম বা মডিউলগুলি কোনও নির্দিষ্ট উত্সের জন্য জিজ্ঞাসা করা এবং তার পরিবর্তে depend নির্ভরতাগুলি উল্টাতে পারে can অর্থাত, এর সূচনা কোডটি DebugDrawerলোড আপ করবেন না debug.font; পরিবর্তে, DebugDrawerএর সূচনা কোডটিতে একটি সংস্থান হ্যান্ডেল নিন। এই হ্যান্ডেলটি মূল গেম কনফিগারেশন ফাইল থেকে লোড হতে পারে।

আমাদের কোডবেস থেকে একটি কংক্রিট উদাহরণ হিসাবে, আমাদের কাছে একটি "গ্লোবাল ডেটা" অবজেক্ট রয়েছে যা রিসোর্স ডাটাবেস থেকে লোড করা হয় (এটি স্বয়ংক্রিয়ভাবে ডিফল্টরূপে./resources ফোল্ডার হয় তবে কমান্ড লাইনের যুক্তি দিয়ে ওভারলোড করা যেতে পারে)। এই বৈশ্বিক তথ্যটির রিসোর্স ডেটাবেস আইডি হ'ল কোডবেসে একমাত্র প্রয়োজনীয় হার্ড-কোডেড রিসোর্সের নাম (আমাদের কাছে অন্য কারও কারও কারও মাঝে মাঝে প্রোগ্রামাররা অলস হয়ে যায়, তবে আমরা সাধারণত ফিক্সিং / শেষ পর্যন্ত শেষ করি)। এই গ্লোবাল ডেটা অবজেক্টটি এমন উপাদানগুলিতে পূর্ণ যাঁর একমাত্র উদ্দেশ্য কনফিগারেশন ডেটা সরবরাহ করা। উপাদানগুলির মধ্যে একটি হ'ল ইউআই গ্লোবাল ডেটা উপাদান যা সংস্থানীয় অন্যান্য কনফিগারেশন আইটেমগুলির মধ্যে সমস্ত মূল ইউআই সংস্থানগুলিতে (হরফ, ফ্ল্যাশ ফাইল, আইকন, স্থানীয়করণ ডেটা, ইত্যাদি) সংস্থান করে। একটি UI 'তে বিকাশকারীর কাছ থেকে প্রধান UI' তে সম্পদ নামান্তর করার সিদ্ধান্ত নেয় যখন /ui/mainmenu.swfথেকে/ui/lobby.swfতারা কেবল সেই বৈশ্বিক ডেটা রেফারেন্স আপডেট করে; কোনও ইঞ্জিন কোডে কোনও পরিবর্তন করার দরকার নেই।

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

এই পদ্ধতির অন্যান্য অনেক সুবিধা রয়েছে। একটির জন্য, এটি রিসোর্স প্যাকিং এবং পুরো প্রক্রিয়াটির জন্য বান্ডিল অবিচ্ছেদ্য করে তোলে। ইঞ্জিনের হার্ড-কোডিং পাথগুলিও বোঝায় যে সেই একই পাথগুলিকে যে কোনও স্ক্রিপ্ট বা সরঞ্জাম প্যাকেজ গেমের সম্পদগুলিতে প্যাকেজে হার্ড কোডিং করতে হবে এবং সেই পাথগুলি তখন সিঙ্ক থেকে বেরিয়ে আসতে পারে। পরিবর্তে সেখান থেকে একটি একক মূল সম্পদ এবং রেফারেন্স চেইনের উপর নির্ভর করে আমরা একক কমান্ডের মতো একটি সম্পদ বান্ডিল তৈরি করতে পারি bundle.exe -root config.data -out main.wadএবং জানতে পারি যে এটি আমাদের প্রয়োজনীয় সমস্ত সম্পদকে অন্তর্ভুক্ত করবে। আরও, যেহেতু বান্ডলারটি কেবলমাত্র উত্স রেফারেন্স অনুসরণ করে, আমরা জানি যে এটি কেবল আমাদের প্রয়োজনীয় সম্পদগুলিকে অন্তর্ভুক্ত করবে এবং সমস্ত প্রকল্পের জীবনের উপর নির্ভরযোগ্যভাবে জমে থাকা বাম-ওভার ফ্লাফকে এড়িয়ে চলবে (প্লাস আমরা স্বয়ংক্রিয়ভাবে তার তালিকা তৈরি করতে পারি) ছাঁটাই জন্য fluff)।

এই পুরো জিনিসটির একটি জটিল কর্নার কেস স্ক্রিপ্টগুলিতে। ইঞ্জিন ডেটা চালিত করা ধারণাগতভাবে সহজ, তবে আমি অনেকগুলি প্রকল্প (এএএ শখের শখ) দেখেছি যেখানে স্ক্রিপ্টগুলিকে ডেটা হিসাবে বিবেচনা করা হয় এবং তাই কেবল নির্বিচারে রিসোর্স পাথগুলি ব্যবহার করার "অনুমতি দেওয়া" হয়। এটা করবেন না। যদি কোনও লুয়া ফাইলের কোনও সংস্থান প্রয়োজন এবং এটি ঠিক যেমন একটি ফাংশন কল করে textures.lua("/path/to/texture.png")তবে সম্পদ পাইপলাইনটি জানার ক্ষেত্রে প্রচুর সমস্যা হতে চলেছে যে স্ক্রিপ্টটি /path/to/texture.pngসঠিকভাবে পরিচালনা করতে হবে এবং এই টেক্সচারটিকে অব্যবহৃত এবং অপ্রয়োজনীয় হিসাবে বিবেচনা করতে পারে। স্ক্রিপ্টগুলি অন্য যে কোনও কোডের মতো চিকিত্সা করা উচিত: সংস্থানসমূহের জন্য ইঞ্জিন এবং রিসোর্স পাইপলাইন পরিদর্শন করতে পারে এমন কোনও কনফিগারেশন এন্ট্রিতে সংস্থান এবং টেবিল সহ তাদের প্রয়োজনীয় ডেটা নির্দিষ্ট করা উচিত। foo.luaপরিবর্তে "লোড স্ক্রিপ্ট " বলে এমন ডেটা বলতে হবে "foo.luaএবং এগুলিকে এই প্যারামিটারগুলি দিন "যেখানে প্যারামিটারগুলিতে প্রয়োজনীয় কোনও সংস্থান অন্তর্ভুক্ত থাকে example উদাহরণস্বরূপ কোনও স্ক্রিপ্ট এলোমেলোভাবে শত্রুদের উদ্ভব করে, সেই কনফিগারেশন ফাইল থেকে সম্ভাব্য শত্রুদের তালিকাটি স্ক্রিপ্টে পাস করুন The ইঞ্জিন তারপরে শত্রুগুলিকে স্তর সহ প্রি-লোড করতে পারে ( যেহেতু এটা সম্ভব spawns সম্পূর্ণ তালিকা জানে) ও রিসোর্স পাইপলাইন যেহেতু তারা নিশ্চিতভাবেই কনফিগারেশন ডেটা দ্বারা সমর্থিত করছি) খেলা সঙ্গে সব শত্রুকে বান্ডেল করতে (জানে না। স্ক্রিপ্ট পথ নামের স্ট্রিং উত্পন্ন যদি শুধু একটি কল loadতারপর তন্ন তন্ন ফাংশন ইঞ্জিন বা রিসোর্স পাইপলাইন স্পষ্টভাবে কোন সম্পদ লোড করার চেষ্টা করতে পারে তা জানার কোনও উপায় রয়েছে।


উত্তম উত্তর, খুব ব্যবহারিক, এবং এটি বাস্তবায়ন করার সময় লোকেরা যে সমস্যাগুলি এবং ত্রুটিগুলি ঘটায় সেগুলিও ব্যাখ্যা করে! +1 টি
whn

+1 টি। যোগ করুন যে আপনি সংশোধন সক্ষম করতে চাইলে কনফিগারেশন ডেটা রয়েছে এমন সংস্থানগুলিতে নির্দেশ করার ধরণটিও খুব সহায়ক helpful গেমগুলিকে সংশোধন করা খুব শক্ত এবং ঝুঁকিপূর্ণ যার জন্য আপনার নিজের তৈরি এবং সেগুলিকে নির্দেশ করার চেয়ে মূল ডেটা ফাইলগুলি পরিবর্তন করা দরকার। এমনকি আপনি যদি অগ্রাধিকারের একটি সংজ্ঞায়িত ক্রম সহ একাধিক ফাইলগুলিতে নির্দেশ করতে পারেন তবে আরও ভাল।
জুটনার্গ

12

আপনি সাধারণ ক্রিয়ায় হার্ডকডিং এড়ানো একইভাবে।

আপনি প্যারামিটারগুলি পাস করেন এবং আপনার তথ্য কনফিগারেশন ফাইলগুলিতে রাখেন।

সেই পরিস্থিতিতে ইঞ্জিন লেখা এবং ক্লাস লেখার মধ্যে সফটওয়্যার ইঞ্জিনিয়ারিংয়ের মধ্যে একেবারেই কোনও পার্থক্য নেই।

MgrAssets
public:
  errorCode loadAssetFromDisk( filePath )
  errorCode getMap( mapName, map& )

private:
  maps[name, map]

তারপরে আপনার ক্লায়েন্ট কোডটিতে একটি "মাস্টার" কনফিগারেশন ফাইল পড়ে ( এটি একটি হার্ড কোডড বা কমান্ড লাইন আর্গুমেন্ট হিসাবে পাস করা হয়েছে) এতে তথ্য রয়েছে যা সম্পত্তির ফাইলগুলি কোথায় এবং কী কী মানচিত্র রয়েছে তা জানায়।

সেখান থেকে সবকিছু "মাস্টার" কনফিগারেশন ফাইল দ্বারা চালিত হয়।


1
হ্যাঁ, কাস্টম যুক্তি আনতে সেই প্লাসটি কোনও ধরণের মেকানিজম। ব্যবহারকারী সংজ্ঞায়িত কার্যকারিতা দ্বারা ইঞ্জিনের মূল বৈশিষ্ট্যগুলি প্রসারিত করতে সি #, অজগর ইত্যাদি জাতীয় কোনও ভাষা এম্বেড করে থাকতে পারে
qrring

3

আমি অন্যান্য উত্তরগুলি পছন্দ করি তাই আমি একটু বিপরীত হতে চলেছি। ;)

আপনি আপনার ইঞ্জিনে আপনার ডেটা সম্পর্কে জ্ঞান কোডিং এড়াতে পারবেন না। তথ্য যেখানেই আসে না কেন, ইঞ্জিনটি এটি সন্ধান করতে হবে। তবে, আপনি প্রকৃত তথ্যটি নিজের ইঞ্জিনে নিজেই এনকোডিং এড়াতে পারবেন।

একটি "খাঁটি" ডেটা চালিত পদ্ধতির মাধ্যমে প্রাথমিক কনফিগারেশনটি লোড করার জন্য প্রয়োজনীয় কমান্ড লাইন প্যারামিটারগুলি দিয়ে আপনি এক্সিকিউটেবল শুরু করতে পারবেন তবে সেই তথ্যের ব্যাখ্যা কীভাবে করতে হবে তা জানতে ইঞ্জিনকে কোডিং করতে হবে। যেমন যদি আপনার কনফিগারেশন ফাইলগুলি তাদেরকে JSON, আপনি ভেরিয়েবল আপনি যেমন জন্য চেহারা হার্ড কোড প্রয়োজন ইঞ্জিন সন্ধান জানি করতে হবে "intro_movies"এবং "level_list"এবং তাই ঘোষণা।

যাইহোক, একটি "সুগঠিত" ইঞ্জিন কনফিগারেশন ডেটা এবং এটি উল্লেখ করে এমন ডেটা সরিয়ে দিয়ে অনেকগুলি গেমের জন্য কাজ করতে পারে।

সুতরাং হার্ড কোডিং এড়ানোর জন্য মন্ত্রটি তেমন কিছু নয় কারণ এটি নিশ্চিত হওয়া যে আপনি সর্বনিম্ন পরিশ্রমের সাথে চেষ্টা করেও পরিবর্তন আনতে পারেন।

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

struct Weapon
{
    enum IconID icon;
    enum ModelID model;
    int damage;
    int rateOfFire;
    // etc...
};

const struct Weapon g_weapons[] =
{
    { ICON_PISTOL, MODEL_PISTOL, 5, 6 },
    { ICON_RIFLE, MODEL_RIFLE, 10, 20 },
    // etc...
};

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


জেসনকে পার্স করা ভয়ানকভাবে কঠিন নয়। জড়িত শুধুমাত্র "ব্যয়" শেখা হয়। (বিশেষত, উপযুক্ত মডিউল বা গ্রন্থাগারটি ব্যবহার করতে শেখা Go উদাহরণস্বরূপ গোতে ভাল জসন সমর্থন রয়েছে))
ওয়াইল্ডকার্ড

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

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

আপনার যুক্তি কী তা আমি নিশ্চিত নই। এই উত্তরে আমি YAGNI এর পক্ষে পরামর্শ দিচ্ছি; আপনার যদি এমন কিছু করে ব্যয় করা / সময় নষ্ট করার প্রয়োজন না হয় যা আপনাকে সাহায্য করে না তবে তা করবেন না। আপনি যদি সময় কাটাতে চান তবে দুর্দান্ত। হতে পারে আপনার পরে সময়টি ব্যয় করতে হবে, সম্ভবত আপনি তা করবেন না, তবে সামনের দিকে এটি করা কেবল আপনাকে গেমটি তৈরির কাজ থেকে বিরত করছে। গেমের বিকাশ তুচ্ছ; একটি গেম তৈরি করতে যাওয়া প্রতিটি একক কাজ সহজ। এটি কেবলমাত্র বেশিরভাগ গেমের মিলিয়ন মিলিয়ন সাধারণ কাজ রয়েছে এবং একটি দায়িত্বশীল দেব সেই লক্ষ্যগুলি চয়ন করে যা সেই লক্ষ্যে দ্রুত পৌঁছে।
ড্যাশ-টম-ব্যাং 21

2
আসলে, আমি আপনার উত্তর upvated; যেমন কোন সত্য যুক্তি । আমি কেবল লক্ষ করতে চেয়েছিলাম যে JSON পার্স করা কঠিন নয় । আবার পড়া, আমি মনে করি আমি বেশিরভাগই স্নিপেটে সাড়া দিচ্ছিলাম "তবে তারপরে আপনাকে পার্সিং এবং অনুবাদ এবং সেই সমস্ত জাজ করা দরকার।" তবে আমি সম্মত হই যে ব্যক্তিগত প্রকল্প গেমস এবং এ জাতীয় জন্য, YAGNI। :)
ওয়াইল্ডকার্ড
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.