Register    Login    Forum    Search    FAQ

Board index » General Programming




Post new topic Reply to topic  [ 1 post ] 
Author Message
 Post subject: สร้าง GUI ให้กับเกมส์ ด้วยมือคุณ !! (ตอนที่ 1)
 Post Posted: Tue Aug 25, 2009 11:40 pm 
Offline
Site Admin

Joined: Sat Feb 19, 2011 1:33 am
Posts: 15
GUI หรือ Graphics User Interfce คือ รูปภาพที่ใช้ติดต่อกับผู้ใช้ ซึ่งการใช้รูปภาพแทนข้อความ
มีประโยชน์อย่างมาก เพราะให้ความเข้าใจที่ง่ายกว่า แต่ถ้ามองดูลึกแล้วๆ GUI ไม่จำเป็นต้องเป็นเพียงรูปภาพแบบ static เท่านั้น
เพราะเราสามารถเปลี่ยนรูปภาพไปเป็นลักษณะต่างๆได้ เช่น กล่องข้อความ
ปุ่มต่างๆ หรือแม้กระทั่ง list control ที่ใช้แสดงรายการต่างๆ
แต่ถ้าจะพูดให้ถูก GUI ในแง่ของการ Programming คือ จุด หรือ พิกัด ต่างๆมากกว่า

GUI Introduction
GUI หรือ Graphics User Interfce คือ รูปภาพที่ใช้ติดต่อกับผู้ใช้ ซึ่งการใช้รูปภาพแทนข้อความ
มีประโยชน์อย่างมาก เพราะให้ความเข้าใจที่ง่ายกว่า แต่ถ้ามองดูลึกแล้วๆ GUI ไม่จำเป็นต้องเป็นเพียงรูปภาพแบบ static เท่านั้น
เพราะเราสามารถเปลี่ยนรูปภาพไปเป็นลักษณะต่างๆได้ เช่น กล่องข้อความ
ปุ่มต่างๆ หรือแม้กระทั่ง list control ที่ใช้แสดงรายการต่างๆ
แต่ถ้าจะพูดให้ถูก GUI ในแง่ของการ Programming คือ จุด หรือ พิกัด ต่างๆมากกว่า
เพราะเมื่อเราทำการสร้าง GUI ขึ้นมานั้น ส่วนมาก เราจะต้องทำงานกับ Mouse Cursor คือการตวจสอบว่า
Mouse Position นั้น อยู่ในกลุ่มของจุดที่เรากำหนดไว้หรือไม่ เพื่อให้เกิด Event ต่างๆ เพื่อตอบสนองต่อผู้ใช้

โดยพื้นฐานของ GUI นั้น ที่ผมบอกไปคือกลุ่มของจุด ดังนั้นเราจึงต้องสร้าง Class หรือ Function ก็ได้
ที่มีการ ตวรจสอบ Mouse Position ซึ่งจะกล่าวถึงในตอนต่อๆไป
โดยเราสามารถออกแบบกลุ่มของจุดเป็บรูปทรงเรขาคณิต
เพื่อให้ง่ายต่อการออกแบบและใช้งานก็ได้ โดย Object ที่สร้างขึ้นมาเพื่อใช้ในการตรวจสอบ
เราอาจจะออกแบบเป็น สีเหลี่ยม และ วงกลม ตามตัวอย่างด้านล่างนี้
Code:
typedef struct ZP_STC_SQUARESLOT
{
//slot width.
float fw;
//slot height.
float fh;
//x1 coordinate.
float fx1;   
//y1 coordinate.
float fy1;   
//x2 coordinate.
float fx2;   
//y2 coordinate.
float fy2;   
//x1 offset.
float fOfsx1;   
//y1 offset.
float fOfsy1;   
//x2 offset.
float fOfsx2;   
//y2 offset.
float fOfsy2;   
//center position of slot ( x axis ).
float fCtx;   
//center position of slot ( y axis ).
float fCty;
}ZP_STC_SQUARESLOT;
typedef ZP_STC_SQUARESLOT * ZP_PTSTC_SQUARESLOT;

typedef struct ZP_STC_CIRCLESLOT
{
//slot radius.
float fr;
//x1 coordinate.
float fx1;   
//y1 coordinate.
float fy1;   
//x1 offset.
float fOfsx1;   
//y1 offset.
float fOfsy1;   
}ZP_STC_CIRCLESLOT;
typedef ZP_STC_CIRCLESLOT * ZP_PTSTC_CIRCLESLOT;

จาก โครงสร้าง Object ข้างต้น จะมีตัวแปร อยู่หลายตัว
ที่ผู้เริ่มต้นที่จะเขียน GUI อาจจะยังไม่เข้าใจ เช่น fOfsx1 fOfsx2 fCtx fCty
ตัวแปรเหล่านี้ เป็นตัวเก็บค่า Offset ของ สีเหลี่ยม และวงกลม รวมไปถึงจุดกึ่งกลาง
ของรูปสี่เหลี่ยม เพื่อใช้ในการตรวจสอบต่างๆ เมื่อจำเป็น ซึ่งตัวแปลเหล่านี้ จำเป็นต้องใช้
เพราะ อยู่ดีๆ เราจะวาดรูปบน Window ขึ้นมาเฉยๆไม่ได้
แต่มันจะต้องมี กรอบขนาดใหญ่ เพื่อกำหนดกลุ่ม ของการทำงาน
หรือที่เรานิยมเรียกกันว่า Dialog นั่นเอง


การสร้าง Dialog เราจะใช้ Object คล้ายกับข้างบน
แต่รายละเอียดบางอย่างจะไม่เหมือนกัน
Code:
typedef struct ZP_STC_GLOBALRECT
{
long lWidth;
long lHeight;
long lPx1;
long lPy1;
long lPx2;
long lPy2;
long lOffsetPosX;
long lOffsetPosY;
long lOffsetXFromRigth;
}ZP_STC_GLOBALRECT;

ค่า Offset ของ Dialog นั้นมีไว้เพื่อปรับตำแหน่งคำนวณค่า พิกัดอ้างอิง
เมื่อมีการเคลื่อนที่ของ Dialog ภายใน Window

สำหรับ GlobalRect นั้น เราสามารถนำมาใช้กำหนดจุดให้กับส่วนสำคัญ 3 ส่วนของ Dialog ได้ นั่นก็คือ
- Frame คือ กรอบของ Dialog
- Drag คือ ส่วนของการ ลาก และ ย้าย Dialog
- Close คือ ส่วนของการปิด Dialog
หรือเราอาจจะเพิ่ม ส่วนของ Minimize และ Maximize เข้าไปอีกก็ได้

ต่อไปเป็นเรื่องของ State ซึ่งเป็นการ ระบุ หรือ บอกสถานะ ความเป็น จริง หรือ เท็จ
ของ Dialog รวมไปถึง ของ Object ที่อยู่ใน Dialog ด้วย ซึ่งค่าเหล่านี้
จะได้รับมาจาก Event ต่างๆที่เกิดขึ้น หรือจากการ กำหนดค่าเริ่มต้นให้มัน
เพื่อใช้ในการตรวจสอบ หรือเรียกค่า ออกมา
เพื่อให้เข้าใจง่ายขึ้น จะให้ดูจาก โครงสร้างของ State ด้านล่างนี้
Code:
typedef struct ZP_STC_GLOBALSTATESETTINGS
{
int LAREATYPE;
long lMainTexture; // Texture ID of Dialog.
long lRollovertexture;
long lPresstexture;
bool bStartEvent;
bool bStartDetectEvent;
bool bHasRolloverTexture;
bool bHasPressTexture;
bool bEnable;
bool bCreated;
bool bRenderRolloverTexture;
bool bRenderTexturePress;
bool bHidden;
bool bMultiLayerEventDetect;
}ZP_STC_GLOBALSTATESETTINGS

จาก โครงสร้างด้านบน จะเห็นว่า มีทั้งตัวแปลเก็บค่าของ Texture และตัวแปล Bool
ที่เอาไว้บอกถึง สถานะของ Dialog และอีกสิ่งที่ควรมีไว้ก็คือ เก็บค่าสีนั่นเอง
Code:
typedef struct ZP_STC_COLOREVENTSET
{
ZP_STC_RGBACOLOR stcMain;
ZP_STC_RGBACOLOR stcRollover;
ZP_STC_RGBACOLOR stcPress;
}ZP_STC_COLOREVENTSET;

จากโครงสร้างจะเห็นว่า การเก็บค่าสีนั้น ยังมีการแบ่งแยกออกไปตาม Event ต่างๆที่เกิดขึ้นอีกด้วย
เพื่อเพิ่มความหลากหลายให้กับการใช้งานมากขึ้น โดยโครงสร้างย่อยของสี ก็คงไม่พ้นค่า r g b a นั่นเอง
Code:
typedef struct ZP_STC_RGBACOLOR
{
float r;
float g;
float b;
float a;
}ZP_STC_RGBACOLOR;
typedef ZP_STC_RGBACOLOR * ZP_PTSTC_RGBACOLOR;

จากกลุ่มของ STATE COLOR และ RECT เราสามารถนำมารวมเป็นโครงสร้างของ Dialog ได้ดังนี้
Code:
typedef struct ZP_STC_DIALOGOBJ
{
ZP_STC_GLOBALRECT stcRect;
ZP_STC_GLOBALSTATESETTINGS stcSet;
ZP_STC_COLOREVENTSET stcColor;
}ZP_STC_DIALOGOBJ;

โครงสร้างนี้ สามารถนำไปใช้ได้หลายอย่าง ซึ่งดูเหมือนการทำ GUI จะไม่ยากอย่างที่คิด
แต่จริงๆแล้ว มันไม่ใช่แบบนั้นเลย เพราะโครงสร้างเพียงแค่นี้ คงไม่พอแน่ๆ สำหรับการสร้าง
Control ต่างๆ ภายใน Dialog ซึ่งยังมีอีกหลายส่วนที่สำคัญ ซึ่งจะทยอยกล่าวถึงไปทีละขั้นตอน
แต่จาก โครงสร้างด้านบนเราจะสามารถสร้างกรอบ Dialog พื้นที่ Drag และ พื้นที่ Close ได้แล้ว
แล้ว Object ภายใน Dialog อื่นๆล่ะ จะสร้างยังไง ? คำถามนี้คงต้องใช้เวลาตอบยาวหน่อยล่ะครับ

ตัวอย่าง
ประกาศ ตัวแปรไว้ในคลาส
Code:
ZP_STC_DIALOGOBJ pstcFrame;
ZP_STC_DIALOGOBJ pstcDrag;
ZP_STC_DIALOGOBJ pstcClose;

ตัวอย่างการเขียน Function Create Dialog
Code:
inline void ZPGuiSystem::CreateDlg(long lSetPosX,long lSetPosY,long lDlgWidth,long lDlgHeight,long lDlgTextrue)
{
pstcFrame.stcRect.lWidth = lDlgWidth;
pstcFrame.stcRect.lHeight = lDlgHeight;
pstcFrame.stcRect.lPx1 = lSetPosX;
pstcFrame.stcRect.lPy1 = lSetPosY;
pstcFrame.stcRect.lPx2 = lSetPosX + lDlgWidth;
pstcFrame.stcRect.lPy2 = lSetPosY + lDlgHeight;

pstcFrame.stcSet.LAREATYPE  = ZP_DIALOGAREA;
pstcFrame.stcSet.lMainTexture  = lDlgTextrue;
pstcFrame.stcSet.bStartEvent  = false;
pstcFrame.stcSet.bStartDetectEvent = false;
pstcFrame.stcSet.bHasRolloverTexture = false;
pstcFrame.stcSet.bHasPressTexture = false;
pstcFrame.stcSet.bEnable  = false;
pstcFrame.stcSet.bCreated  = true;
pstcFrame.stcSet.bHidden  = false;
pstcFrame.stcSet.bMultiLayerEventDetect = true;

pstcDrag.stcSet.bCreated  = false;
pstcClose.stcSet.bCreated  = false;

ZP_STC_RGBACOLOR crv;
crv.r = 1.0f;
crv.g = 1.0f;
crv.b = 1.0f;
crv.a = 1.0f;
pstcFrame.stcColor.stcMain  = crv;
pstcFrame.stcColor.stcRollover  = crv;
pstcFrame.stcColor.stcPress  = crv;
}

ตัวอย่างการเขียน Function Create Drag

Code:
inline void ZPGuiSystem::CreateDrag(long lOffsetPosX,long lOffsetPosY,long lDgZWidth,long lDgZHeight,long lDgZTexture)

pstcDrag.stcRect.lWidth  = lDgZWidth;
  pstcDrag.stcRect.lHeight  = lDgZHeight;
pstcDrag.stcRect.lOffsetPosX  = lOffsetPosX;
pstcDrag.stcRect.lOffsetPosY  = lOffsetPosY;
pstcDrag.stcRect.lPx1  = pstcFrame.stcRect.lPx1 + pstcDrag.stcRect.lOffsetPosX;
pstcDrag.stcRect.lPy1  = pstcFrame.stcRect.lPy1 + pstcDrag.stcRect.lOffsetPosY;
pstcDrag.stcRect.lPx2  = pstcDrag.stcRect.lPx1 + pstcDrag.stcRect.lWidth;
pstcDrag.stcRect.lPy2  = pstcDrag.stcRect.lPy1 + pstcDrag.stcRect.lHeight;

pstcDrag.stcSet.LAREATYPE  = ZP_DRAGAREA;
pstcDrag.stcSet.lMainTexture  = lDgZTexture;
pstcDrag.stcSet.bStartEvent  = false;
pstcDrag.stcSet.bStartDetectEvent = false;
pstcDrag.stcSet.bHasRolloverTexture = false;
pstcDrag.stcSet.bHasPressTexture = false;
pstcDrag.stcSet.bEnable  = false;
pstcDrag.stcSet.bCreated  = true;
pstcDrag.stcSet.bMultiLayerEventDetect = true;

ZP_STC_RGBACOLOR crv;
crv.r  = 1.0f;
crv.g  = 1.0f;
crv.b  = 1.0f;
crv.a  = 1.0f;
pstcDrag.stcColor.stcMain  = crv;
pstcDrag.stcColor.stcRollover  = crv;
pstcDrag.stcColor.stcPress  = crv;
}


ตัวอย่างการเขียน Function Create Close

Code:
inline void ZPGuiSystem::CreateClose(long lOffsetPosXFromRigth,long lOffsetPosY,long lCbWidth,long lCbHeight,long lCbTexture)

pstcClose.stcRect.lWidth  = lCbWidth;
  pstcClose.stcRect.lHeight  = lCbHeight;
pstcClose.stcRect.lOffsetXFromRigth = lOffsetPosXFromRigth;
pstcClose.stcRect.lOffsetPosY  = lOffsetPosY;
pstcClose.stcRect.lPx1 = pstcFrame.stcRect.lPx2 - (pstcClose.stcRect.lWidth + pstcClose.stcRect.lOffsetXFromRigth);
pstcClose.stcRect.lPy1 = pstcFrame.stcRect.lPy1 + pstcClose.stcRect.lOffsetPosY;
pstcClose.stcRect.lPx2 = pstcFrame.stcRect.lPx2 - pstcClose.stcRect.lOffsetXFromRigth;
pstcClose.stcRect.lPy2 = pstcFrame.stcRect.lPy2 - ( pstcFrame.stcRect.lHeight - (pstcClose.stcRect.lHeight + pstcClose.stcRect.lOffsetPosY) );

pstcClose.stcSet.LAREATYPE  = ZP_CLOSEAREA;
pstcClose.stcSet.lMainTexture  = lCbTexture;
pstcClose.stcSet.bStartEvent  = false;
pstcClose.stcSet.bStartDetectEvent = false;
pstcClose.stcSet.bHasRolloverTexture = false;
pstcClose.stcSet.bHasPressTexture = false;
pstcClose.stcSet.bEnable  = false;
pstcClose.stcSet.bCreated  = true;
pstcClose.stcSet.bMultiLayerEventDetect = true;

ZP_STC_RGBACOLOR crv;
crv.r = 1.0f;
crv.g = 1.0f;
crv.b = 1.0f;
crv.a = 1.0f;
pstcClose.stcColor.stcMain  = crv;
pstcClose.stcColor.stcRollover  = crv;
pstcClose.stcColor.stcPress  = crv;
}

จากตัวอย่างการสร้าง Dialog Drag และ Close จะสังเกตุเห็นได้ว่า ทั้ง Drag และ Close นั้น ถูกอ้างอิงโดย Dialog อีกที
เพราะมันต้องทำหน้าที่อยู่ใน Dialog และเมื่อเราทำการปรับ Offset การเคลื่อนที่ของ Dialog เราก็จะได้ไม่ต้องไปยุ่ง
กับ Drag และ Close เลย และจากค่าของ State ต่างๆนั้น เราสามารถเปลี่ยนได้โดย Function ที่ใช้สำหรับกำหนดค่าเริ่มต้นได้


Top 
 Profile  
 
Display posts from previous:  Sort by  
 
Post new topic Reply to topic  [ 1 post ] 

Board index » General Programming


Who is online

Users browsing this forum: No registered users and 1 guest

 
 

 
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
cron