উইন্ডোটির আকার পরিবর্তন / সরানোর সময় আমি কীভাবে এক্সএনএ আপডেটগুলি থামিয়ে দেওয়া থেকে আটকাব?


15

এক্সএনএ কল করা বন্ধ করে Updateএবং Drawগেমের উইন্ডোটি পুনরায় আকার দেওয়া বা সরানোর সময় বন্ধ করে দেয় ।

কেন? এই আচরণ রোধ করার কোনও উপায় আছে?

(এটি আমার নেটওয়ার্ক কোডটি বিচ্ছিন্ন করে দেয়, কারণ নেটওয়ার্ক বার্তাগুলি পাম্প করা হচ্ছে না))

উত্তর:


20

হ্যাঁ. এটিতে এক্সএনএর ইন্টার্নালগুলির সাথে অল্প পরিমাণে গণ্ডগোল জড়িত। আমি এই ভিডিওর দ্বিতীয়ার্ধে একটি স্থির একটি প্রদর্শনী পেয়েছি ।

পটভূমি:

এটি হওয়ার কারণটি হ'ল XNA তার গেমের ঘড়ি স্থগিত করে যখন Gameঅন্তর্নিহিত Formআকারটি পুনরায় আকার দেওয়া হয় (বা সরানো হয়, ইভেন্টগুলি একই হয়)। এটি, পরিবর্তে, কারণ এটি তার গেম লুপটি চালাচ্ছে Application.Idle। যখন উইন্ডোটির আকার পরিবর্তন করা হয়, উইন্ডোজ কিছু ক্রেজি উইন 32 মেসেজ লুপ স্টাফ করে যা Idleগুলি চালানো থেকে বাধা দেয় ।

সুতরাং, যদি Gameএটির ঘড়িটি স্থগিত না করা হয় তবে একটি আকার পরিবর্তন করার পরে এটি একটি প্রচুর পরিমাণে সঞ্চিত হয়ে যায় যে এটির পরে এটি একটি ফাটলে আপডেট করতে হবে - স্পষ্টভাবে কাম্য নয়।

কিভাবে ঠিক হবে এটা:

এক্সএনএ-তে ইভেন্টগুলির একটি দীর্ঘ শৃঙ্খলা রয়েছে (যদি আপনি এটি ব্যবহার Gameকরেন তবে এটি কাস্টম উইন্ডোতে প্রযোজ্য নয়) যা গেমের ঘড়ির জন্য মূলত অন্তর্নিহিত ইভেন্টের আকার পরিবর্তন Formকরে Suspendএবং Resumeপদ্ধতিগুলি সংযুক্ত করে ।

এগুলি ব্যক্তিগত, তাই ইভেন্টগুলি আনহুক করার জন্য আপনাকে প্রতিবিম্বটি ব্যবহার করতে হবে (যেখানে thisরয়েছে Game):

this.host.Suspend = null;
this.host.Resume = null;

প্রয়োজনীয় আবশ্যকতা এখানে:

object host = typeof(Game).GetField("host", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(this);
host.GetType().BaseType.GetField("Suspend", BindingFlags.NonPublic | BindingFlags.Instance).SetValue(host, null);
host.GetType().BaseType.GetField("Resume", BindingFlags.NonPublic | BindingFlags.Instance).SetValue(host, null);

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

তারপরে আপনাকে নিজের টিক উত্স সরবরাহ করতে হবে, যখন XNA কখন থেকে টিক দিচ্ছে না Application.Idle। আমি কেবল একটি ব্যবহার করেছি System.Windows.Forms.Timer:

timer = new Timer();
timer.Interval = (int)(this.TargetElapsedTime.TotalMilliseconds);
timer.Tick += new EventHandler(timer_Tick);
timer.Start();

এখন, timer_Tickশেষ পর্যন্ত কল করবে Game.Tick। এখন যেহেতু এই ঘড়িটি স্থগিত করা হয়নি, আমরা কেবল এক্সএনএর নিজস্ব টাইমিং কোডটি ব্যবহার করা মুক্ত। সহজ! একেবারেই নয়: এক্সএনএ-র অন্তর্নির্মিত টিকিংটি না ঘটে কেবল তখনই আমরা আমাদের ম্যানুয়াল টিকিংটি ঘটতে চাই। এটি করার জন্য এখানে কিছু সাধারণ কোড দেওয়া হল:

bool manualTick;
int manualTickCount = 0;
void timer_Tick(object sender, EventArgs e)
{
    if(manualTickCount > 2)
    {
        manualTick = true;
        this.Tick();
        manualTick = false;
    }

    manualTickCount++;
}

এবং তারপরে, Updateএক্সএনএ সাধারণত টিক দিচ্ছে তবে এই কোডটি কাউন্টারটিকে পুনরায় সেট করতে রাখুন।

if(!manualTick)
    manualTickCount = 0;

নোট করুন যে এই টিকিংটি XNA এর যথেষ্ট কম নির্ভুল। তবে এটি রিয়েল টাইমটির সাথে কমবেশি আবদ্ধ থাকা উচিত।


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

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

(কিন্তু এই এখনও হওয়া উচিত যথেষ্ট অধিকাংশ ক্ষেত্রে জন্য। XNA'S টাইমার ইতিমধ্যে উত্সর্গমূলক তোতলামি প্রতিরোধ সঠিকতা, তাই যদি আপনি প্রয়োজন নিখুঁত টাইমিং, আপনি অন্য কিছু করা উচিত।)


2
সুন্দর ব্যাপক উত্তর।
MichaelHouse

1
আপনি কেন প্রশ্নটি জিজ্ঞাসা করলেন, তাত্ক্ষণিকভাবে উত্তর দিন?
অ্যালাস্টার পিটস

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