C++ - کاربرد زبان c در بازی سازی- قسمت اول- صفحه 3

3. Show the Window

نشون دادن پنجره آسون ترین قسمت کاره به راحتی ساخت یک جعبه پیام. برای اینکار به یک تابع که دوتا پارامتر داره نیاز داریم. نمونه اولیه:
BOOL ShowWindow(HWND hWnd,
int nCmdShow);

پارامتر اول هندل پنجره ای که ساختیم میخوایم نشون داده بشه.
int nCmdShow

آخرین پارامتر WINMAIN یادتونه؟ این همونه که البته ما نیازی بهش نداریم ولی میزاریم اینجا خود ویدوز به ما بگه چکار کنیم.در بازی اهمیتی نداره که ویندوز به ما میگه چکار کنیم چون اونموقع در حالت Full Screen هستیم.
در اینجا بخوایم یا نخوایم مقدار nCmdShow میزاریم.

متاسفانه هنوز کار تموم نشده.



مدیریت رویدادهای ویندوز و پیامها

همونطور که قبلا بحث کردیم برنامه نویسی ویندوز بر پایه رویدادهاست به این معنی که پنجره ما فقط وقتی نیاز داره کاری را انجام بده که ویندوز به اون میگه .در حالت دیگه فقط صبر میکنه.

زمانی که یک ویندوز یک پیام را به ما میده چند تا چیز به سرعت رخ میده. این پیام در صف رویداد ها قرار میگیره . و ما از تابع GetMessage() برای گرفتن اون پیام استفاده میکنیم(اون پیام را از صف پیام ها میگیریم) از تابع translatemessage() استفاده میکنیم تا پیام را به فرمت مورد نیاز تبدیل کنیم و از تابع dispatchmessage() استفاده میکنیم و پیام را به WindowProc() میدیم تا در اونچا کد لازم برای جواب به پیام انتخاب بشه.

اگر بخوایم به صورت نمودار فرضش کنیم به صورت شکل پایین میشه

     سایز این تصویر تغییر یافته است.برای دیدن سایز واقعی آن اینجا کلیک کنید.سایز این تصویر 279*546 میباشد.

 


 

مدیریت رویداد ها نصف برنامه ما رو شامل میشه . و خودش به دو قسمت تقسیم میشه:
1. The Main Loop
The WindowProc() Function.2

حلقه اصلی شامل تابع های GetMessage TranslateMessage و DispatchMessage است .تابع WindowProc() تنها شامل کد اجرای پیام های حتمی(مورد نیاز همیشه) برنامه است.

1. The Main Loop

همونطور که تو نمودارم معلومه این قسمت از سه تابع تشکیل شده . هر تابع تقریبا سادست و ما نیازی به بحث در مورد اونا به صورت دقیق تر نداریم. کد پایین کد مورد نیاز برای حلقه اصلیه برنامست:
// this struct holds Windows event messages
MSG msg;

// wait for the next message in the queue, store the result in 'msg'
while(GetMessage(&msg, NULL, 0, 0))
{
// translate keystroke messages into the right format
TranslateMessage(&msg);

// send the message to the WindowProc function
DispatchMessage(&msg);
}


MSG msg;

MSG یک ساختار که تمام اطلاعات مربوط به یک رویداد تنهای پیام است . (Single even message) به طور عادی نیازی به دسترسی به اجزای داخلش ندارید ولی اعضای اونو این زیر نوشتم:
Member            Description

HWND hWnd      Contains the handle of the window which recieved the message.

UINT message    Contains the identifier of the message sent.

WPARAM wParam Contains additional information about the message. The exact                                     meaning depends on what message was sent.        
 
LPARAM lParam     Identical to WPARAM, and simply contains more information.

DWORD                time Contains the exact time at which the message was posted in                                the event queue. 

POINT pt                Contains the exact mouse position, in screen coordinates, when the                               message was posted.



while(GetMessage(&msg, NULL, 0, 0))

GetMessage() یک تابع که هر پیامی را از صف پیام ها میگیره و داخل ساختار MSG میزاره. و همیشه مقدار true را بر میگردون به جز زمانی که برنامه میخواد خارج بشه کهfalse میده.وقتی false میده ما از حلقه خارج میشیم..
تابع GetMessage() دارای چهار پارامتر است به صورت زیر...

BOOL GetMessage(LPMSG lpMsg,
HWND hWnd,
UINT wMsgFilterMin,
UINT wMsgFilterMax);


LPMSG lpMsg,

این پارامتر یک اشاره گر به ساختار پیام است مثل همونی که بحث کردیم. تنها کاری که باید بکنیم اینه که آدرس ساختاری که ساختیم اینجا بدیم.

HWND hWnd,

این یک هندل به این پنجره ای که باید پیام از اون بیاد.هرچند ممکنه توجه کنی که ما اینچا NULL گذاشتیم در این پارامتر NULL به این معنی که پیام بعدی برای هر کدوم از پنجره های ما بگیر. اگه بخوایم میتونیم هندل پنجره را بزاریم ولی ما اینچا فقط یکی داریم و نیازی به این نیست.و فقطNULL میزاریم.

UINT wMsgFilterMin, UINT wMsgFilterMax

این پارامتر میتونه برای محدود کردن نوع پیام هایی که برای ما از صف پیام ها میاد استفاده بشه.باری مثال استفاده از WM_KEYFIRST در wMsgFilterMIn و استفاده از WM_KEYLAST پیام ها را به نوع پیام هایی که مال کی بورد محدود میکنه. WM_KEYFIRST و WM_KEYLAST هم معنی مقدارهای integer اولین و آخرین پیام های کی بوردن. به همینصورت WM_MOUSEFIRST و WM_MOUSELAST برای محدود کردن به پیام های موس.اگه 0 بزاری براش هر پیامی را بدون در نظر گرفتن مقدارش میگیره.

TranslateMessage(&msg);

این تابع برای تبدیل عمل فشار کلید های معین را به یک فرمت مشخص انجام میده ولی برای ما در بازی مهم نیست چون در آینده ما از Directinput برای شناسایی فشار کلیدها و ورودی های مختلف مثل موس یا game pad استفاده میکنیم درمورد این تابع خوبه بعدا خودتون یه مطالعه ای کنید اینجا کم توضیح دادم.

DispatchMessage(&msg);

به طور ساده همون کاری را انجام میده که اسمش میگه. این تابع پیام ها را میفرسته به تابع WindowProc() یکه پارامتر هم دارد که آدرس ساختار پیام که ساختیم.


2. The WindowProc() Function

یک خلاصه از کاری که تا اینجا انجام شد این بود که ما پیام ها را گرفتیم (getmessage) ترجمه کردیم(translatemessage) و به WINDOWPROC فرستادیم ( dispatchmessage).
زمانی که تابع WindowProc فراخوانی میشه چهار قسمت از ساختار MSG به اون رد میشه . درزیر نمونه اولیه آمده
LRESULT CALLBACK WindowProc(HWND hWnd,
UINT message,
WPARAM wParam,
LPARAM lParam);

اگر نگاهی به ساختار msg انداخته باشید میبینید اینه تو اون بود میتونید همونجا بخونید که چی هستن.مرسی!
زمانی که یک پیام داخل windowproc میشه ما میتونیم از شناسه uMSG استفاده کنیم و بفهمیم که کدوم پیام آمده.
بیشتر برنامه نویسا و تمام برنامه نویسان بازی که من میشناسم از switch() برای این کار استفاده میکنن.در پایین مثالش آمده:
// sort through and find what code to run for the message given
switch(message)
{
// this message is read when the window is closed
case WM_DESTROY:
{
// ...
// ...
} break;
}
در اینجا چک کرده که اگر پیام WM_DESTROY امد چکار کن این پیام وقتی میاد که پنجره در حال بسته شدن و زمانی که بسته شد کد ما اجرا میشه وقتی ما فقط این پیام را چک میکنیم دیگه به بقیه پیام ها کار نداریم و برنامه اونارو نادیده میگیره و در برابر اونا کاری نمیکنه.تمام کاری که ما اینجا میکنیم اینه که به برنامه بگیم ما کارمون با این پیام تمومه و مقدار 0 را بازگشت میدیم و برای نشان دادن اینکه همه چیز تمیز و پاک و باید برنامه خارج بشه ما از کد زیر استفاده میکنیم:

case WM_DESTROY:
{
// close the application entirely
PostQuitMessage(0);
return 0;
} break;

تابع PostQuitMessage() پیام WM_QUITرا میفرسته که دارای یک مقدار integer صفر است.همونطور که گفتیم وقتی برنامه خارج میشه که getmessage () مقدار false بازگشت بده و وقتی ما 0 را میفرستیم این تابع مقدار false میده.
در نهایت کاری که این تابع میکنه اینه که به کار تابع winmain پایان میده.

اگر کد برنامه را دیده باشید میفهمید که یک تابع دیگه مونده که باید بگیم.DefWindowProc(). کاری که این تابع میکنه اینه که پیام هایی را که ما کار بهشون نداشتیم را مدیریت میکنه به جای ما. به طور خلاصه پیام هایی را که ما برای آنها 0 بازگشت ندادیم را مدیریت میکنه .به خاطر همین ما اینو در آخر تابع قرار دادیم تا هرچیزی که ما از دادیم و بگیره...

ادامه دارد...

 

پژوهشگر و گرداورنده : امیر نوری

تاریخ آپلود :31/01/2010


© Copyright 2010/ Animationdata.com & Partners     

 

                          صفحه 1              صفحه 2             صفحه 3            عناوین مطالب

 

آمار بازدیدکنندگان

آنلاین: 7
امروز: 651
دیروز: 292
ماه: 1701
سال: 9069
کل: 191228
آخرین بازدید: 22:19