Register    Login    Forum    Search    FAQ

Board index » General Programming




Post new topic Reply to topic  [ 4 posts ] 
Author Message
 Post subject: Defend Master Game Design Model
 Post Posted: Sat Feb 19, 2011 6:56 pm 
Offline
Site Admin

Joined: Sat Feb 19, 2011 1:33 am
Posts: 15
บทนำ  -  ถึงผู้ที่อย่างสร้างเกมส์ของตนเอง ( ขอเน้นไปทางเกมส์ 3D นะครับ ) โดยไม่รู้จะเริ่มต้นยังไง
อยากแนะนำให้ทำความเข้าใจภาพรวมก่อน จึงค่อยไปลงลึกถึงรายละเอียดในการเขียนโปรแกรม

เวลาเราจะทำเกมส์หนึ่งๆ ถ้าเริ่มจาก 0 เลย เราก็มักจะคิดไม่ออกว่าจะเริ่มทำยังไง
บางคนก็สร้างฉากไปเรื่อยเปื่อย บางทีก็สวยอลังการมาก ฝันอยากทำเกมส์ แต่เขียนระบบอื่นไม่เป็น
( ยกตัวอย่าง คนที่ใช้ UDK สร้าง Environment มาโชว์ มีไม่กี่คนที่จะทำเกมส์เสร็จจริงๆ เพราะเกมส์จริงๆไม่ได้มีแค่ฉาก )
บางคนก็เขียนเกี่ยวกับการเคลื่อนไหวตัวละคร ควบคุมโมเดล ปั้นโมเดล จับโบนขยับไปมา เพ้นท์ Texture ซะสวยงาม
บางคนก็แก้งานจากตัวอย่างที่เค้าแถมให้มาจาก engine ( ส่วนมากจะเป็นมือใหม่สำหรับ Engine นั้นๆ )

วิธีข้างต้นมันไม่ผิด ได้ความรู้เหมือนกัน แต่มันเหมือนเป็นการเดินทางอ้อม หรือไม่ก็มัวแต่แหวกพงหญ้าหาทางเดินถนนลาดยาง
และบางอย่าง มันเป็นเพียงแค่ สิ่งๆหนึ่งที่อยู่ในเกมส์ หรือเรียกว่า ส่วนประกอบ  แต่ไม่ใช่ GAME

เรื่องแบบนี้มันเป็นเรื่องปกติสำหรับคนช่วงก่อนหน้านี้ สมัยที่มีการพัฒนาเกมส์ใหม่ๆ เหมือนผม เหมือนคนอื่นๆ
ที่ยังคงงุนงงว่า ถ้าเราจะทำเกมส์เพียงคนเดียวจริงๆ มันต้องทำทุกอย่างเองจริงๆเหรอ
หลายคนไปเริ่มจาก 0  ขลุกอยู่แต่กับ DirectX , OpenGL 
Programmer หลายคนคงต้องไปฝึกปั้นโมเดลมาแน่ๆ ฮ่าๆๆ แล้วก้ต้องมาคิดได้ทีหลังว่า  " อย่าเลย "
หลายคนก็ไม่คิดจะเริ่มจาก 0 ผมเองก็เช่นกัน
ผมไม่เคยแตะ Direct Draw เลย ตลอด 6 ปี ที่ศึกษามา ใช้เป็นแต่ Direct Input อย่างเดียว

มีสิ่งหนึ่งที่ผมคิดตั้งแต่เริ่มศึกษาใหม่ๆ   คือต้องเลือกระหว่าง  การลดระยะเวลาในการศึกษา กับ การเป็นคนที่รู้ไปซะทุกอย่างแต่ไม่มีเวลาที่จะทำ

อีโก้ของโปรแกรมเมอร์เกือบจะทุกคนคือ  อยากทำอะไรด้วยฝีมือตนเอง ตั้งแต่เริ่ม   
แต่นั่นไม่ใช่สิ่งที่ดี โปรแกรมเมอร์ควรเลือกทางสายกลาง คือ อะไรที่ตัวเองคิดว่าทำได้ดีกว่าคนอื่น ก็ทำเอง
อะไรที่ตัวเองคิดว่า หยิบจับนำมาใช้ประโยชน์ได้จากผู้ที่เค้าเก่งกว่า ก็ควรเอามาใช้เพื่อต่อยอด
เพราะเวลาในชีวิตของคุณมีจำกัด !!

หลายปีผ่านไป ผมว่ายังมีหลายคนที่ยังคิดว่า ยังต้องการทำเกมส์ด้วยตัวเองเพียงคนเดียว
ผมก็คนนึงล่ะ แต่มันมีความจริงข้อหนึ่งที่ต้องยอมรับคือ คุณทำเองทุกอย่าง แต่ไม่ได้หมายความว่า งานมันออกมาจะดีทุกอย่าง
ดังนั้น ถ้าเห็นสมควรจะมีทีม ก็ควรสร้างทีม แล้วส่งงานที่ตัวเองไม่ถนัด ไปให้คนอืนทำซะ !!
( ถ้าเกมส์ Content ไม่เยอะ ทำคนเดียวคงไม่มีปัญหา  แต่ตรงกันข้าม ถ้า Content ของเกมส์เยอะ เรือง Team Work สำคัญมาก )

ณ ตอนนี้ คนรุ่นใหม่ที่เข้ามาศึกษาการสร้างเกมส์ในปัจจุบัน ควรเริ่มเดินที่ Start Point ที่ถูกต้องสักที
ว่าคุณต้องการเป็น Game Developer หรือ Content Developer เลือกสักทาง แล้วจับกลุ่ม มุ่งสู่ฝัน  ลั้ลลา ....

จบบทนำละ

----------------------

จากบทนำผมก็ของเลือกเป็น Game Developer ละกันนะครับ แนวทางของผมชัดเจนมากครับ คือ
สร้างระบบเกมส์ ส่วนพวก Content ทำเองก็เอาแค่พอใช้ได้พอละ แล้วที่ยากๆต้องใช้เวลานาน ผมขอให้เป็นหน้าที่ของคนอื่นโลด

วันนี้ผมจะมาเสนอแนวทางการสร้างเกมส์เอาแบบมีแบบแผนหน่อยนะ จะได้ไม่ต้องเสียเวลาไปทำอย่างอื่น

จากเกมส์ที่ทำออกมา ผมใช้เวลาจำกัดในการทำทุกอย่าง ซึ่ง ตัวระบบเองก็ถูกจำกัดไปด้วย จริงๆมันอยากเพิ่มนู้นเพิ่มนี่อีกหลายอย่าง
แต่ก็ อยากเปลี่ยนไปใช้ UDK ก็เลยต้องหยุดเอาไว้ก่อน ซึ่งตอนนี้ความคืบหน้าเรื่อง UDK ก็กำลังศึกษาการเขียน Unreal Script
เรียนรู้พวก Classes กับ การ Implement อยู่ครับ   ผมว่า ถ้า UDK ทำ เป็น Library เขียนสดแบบ Truevision3D  บวกกับใช้
Editor ของตัวเองในการ Mix & Match ให้เข้ากันได้ ก็จะดีไม่น้อย ที่ทุกวันนี้ UDK มันใช้ยาก เพราะ จับต้นชนปลาย หาจุดเข้าจุดออกไม่ถูก
ภาษาโปรแกรมพอๆกับภาษาต่างดาว ฮ่าๆๆ  นอกเรื่องมาพอสมควรละ


ก่อนอื่นเรามาดู Game Design Model กันก่อน

Image

จากรูปเป็น Design Model พื้นฐานของเกมส์นี้นะครับ
ถ้าเราดูจากรูป เราอาจจะเห็นแค่ว่า มันเป็นการทำงานของอะไรสักอย่าง  แต่สิ่งที่อยากให้สังเกตุคือ ชื่อในแต่ละ Block
ซึ่งจะมี Subfix เป็น Template และ Object

ส่วนที่เราให้ความสำคัญคือ Template  ซึ่งเป็นแม่แบบของ Object ที่เราจะต้องใช้ภายในเกมส์
ตัว Template สามารถสร้างเป็น Class หรือ Structure เฉยๆ ก็ได้ แล้วแต่ความเทพในการเขียนโปรแกรม
แต่ผมเขียนเป็น Class
ซึ่งในแต่ละ Template สามารถ มีส่วนประกอบของ Template จาก Class อื่นๆรวมอยู่ด้วย
และเมื่อเข้าสู่ Game Loop การใช้ Template ก็เป็นเพียงแค่ การเรียกใช้งาน ID ของ Template นั้นๆ
เพื่อสร้าง Object ที่ต้องการออกมา

ตัวอย่าง Template ของ Item ซึ่งผมจะเขียนเป็น Class ที่มีทั้งส่วนของการสร้าง Template และ ส่วนของการสร้าง Object

ตัวอย่างการสร้าง Method สร้าง Item template  กำหนด รูปแบบโมเดลและ Effect
Code:
int ZPItemDrop::CreateItemTP_X(char * strFilename,char * strTemplateName,bool bLoadtexture,bool bLoadMaterial,bool bHasParticle,char * strParticleFileName,ZP_ITEMEFFECTYPE eItemEffectType)
{
   if(piTemplateCount < ZP_MAX_ITEMDROP_TEMPLATE )
   {
      pstcItemTP[piTemplateCount].ctvItem = new CTVMesh();
      pstcItemTP[piTemplateCount].ctvItem = pctvScene->CreateMeshBuilder("ZPITEM");
      pstcItemTP[piTemplateCount].ctvItem->LoadXFile(strFilename,bLoadtexture,bLoadMaterial);
      pstcItemTP[piTemplateCount].ctvItem->SetShadowCast(false,false);
      pstcItemTP[piTemplateCount].ctvItem->Enable(false);
      pstcItemTP[piTemplateCount].ctvItem->SetScale(20.0f,20.0f,20.0f);
      pstcItemTP[piTemplateCount].ctvItem->SetCullMode(cTV_DOUBLESIDED);
      pstcItemTP[piTemplateCount].iItemDropTemplateID = piTemplateCount;
      pstcItemTP[piTemplateCount].eItemEffectType = eItemEffectType;
      strcpy_s(pstcItemTP[piTemplateCount].strTPName,ZP_MAX_CHARBUFFER64,strTemplateName);
      if(bHasParticle)
      {
         pstcItemTP[piTemplateCount].stcParticle.bHasParticle = true;
         pstcItemTP[piTemplateCount].stcParticle.ctvParticle = new CTVParticleSystem();
         pstcItemTP[piTemplateCount].stcParticle.ctvParticle = pctvScene->CreateParticleSystem("ZPPARTICLE");
         bool bLoadTest = pstcItemTP[piTemplateCount].stcParticle.ctvParticle->Load(strParticleFileName);
         pstcItemTP[piTemplateCount].stcParticle.ctvParticle->Enable(false);
         if(!bLoadTest)
            assert(false);
      }
      else
         pstcItemTP[piTemplateCount].stcParticle.bHasParticle = false;
      piTemplateCount ++;
      return piTemplateCount-1;
   }
   return -1;
}

ตัว Template จะมีการกำหนด Properties เบื้องต้นเอาไว้ เบื้องใช้ในการ Copy ให้ตัวอื่นๆ

ตัวอย่างการใช้งาน
Code:
   clsZPGAME.CreateItemTP_X("GameModel\\item\\HPPotion.X","HPPotion",true,true,true,"GameSFX\\ITEM_EFFECT1.TVP");
   clsZPGAME.CreateItemTP_X("GameModel\\item\\MPPotion.x","MPPotion",true,true,true,"GameSFX\\ITEM_EFFECT1.TVP");
   clsZPGAME.CreateItemTP_TVM("GameModel\\item\\box.TVM","box",true,true,true,"GameSFX\\ITEM_EFFECT3.TVP");
   clsZPGAME.CreateItemTP_X("GameModel\\item\\Vhelm2.X","VHelm2",true,true,true,"GameSFX\\ITEM_EFFECT3.TVP");
   clsZPGAME.CreateItemTP_X("GameModel\\item\\Vhelm3.X","VHelm3",true,true,true,"GameSFX\\ITEM_EFFECT3.TVP");
   clsZPGAME.CreateItemTP_X("GameModel\\item\\VArmor1.X","VArmor1",true,true,true,"GameSFX\\ITEM_EFFECT3.TVP");
   clsZPGAME.CreateItemTP_X("GameModel\\item\\VSword2.X","VSword2",true,true,true,"GameSFX\\ITEM_EFFECT3.TVP");
   clsZPGAME.CreateItemTP_X("GameModel\\item\\VSword1.X","VSword1",true,true,true,"GameSFX\\ITEM_EFFECT3.TVP");
   clsZPGAME.CreateItemTP_X("GameModel\\item\\VShoulder1L.X","VShoulder1L",true,true,true,"GameSFX\\ITEM_EFFECT3.TVP");
   clsZPGAME.CreateItemTP_X("GameModel\\item\\VShoulder1R.X","VShoulder1R",true,true,true,"GameSFX\\ITEM_EFFECT3.TVP");


ซึ่งใน Class หนึ่งๆ อาจจะมี Template หลายๆอันอยู่ในคลาสเดียวกัน ที่มีความสัมพันธ์กัน

เช่นเมื่อเรามี ตัว Template ในการกำหนด รูปแบบโมเดล และ Effect  เราจะต้องมี Template ที่กำหนด คุณสมบัติต่างๆของ Item ด้วย
Code:
int ZPItemDrop::CreateItemDropData(
int iItemDropTemplateID,int iItemID,int iMaxCount,float fDuration,float fReuseDelay,int iHealingTime
,ZP_STC_RGBACOLOR stcNameColor   ,ZP_STATICFREETYPE eSlotTye,ZP_EQUIPMENTPARTTYPE eEquipPartType
,ZP_EQUIPMENTTYPE eEquipType,bool bCanDrag,bool bCanDrop,int iMaxDropNum,int iPercentDrop,int iItemTexture,int iTextureRectW
,int iTextureRectH,char * strItemName,char * strInfoFileName,ZP_STC_MAIN_STATS stcItemStats)
{
   if(piItemDataCount >= 0 && piItemDataCount < ZP_MAX_ITEMDROP_DATA)
   {
      pstcItemData[piItemDataCount].stcItemData.iItemDropTemplateID = iItemDropTemplateID;
      pstcItemData[piItemDataCount].stcItemData.stcProps.lItemFixID = iItemID;
      pstcItemData[piItemDataCount].stcItemData.stcProps.lMaxCount = iMaxCount;
      pstcItemData[piItemDataCount].stcItemData.stcProps.fDuration = fDuration;
      pstcItemData[piItemDataCount].stcItemData.stcProps.fReuseDelay = fReuseDelay;
      pstcItemData[piItemDataCount].stcItemData.stcProps.iHealingTime = iHealingTime;
      pstcItemData[piItemDataCount].stcItemData.stcProps.stcNameColor = stcNameColor;
      pstcItemData[piItemDataCount].stcItemData.eSlotType = eSlotTye;
      pstcItemData[piItemDataCount].stcItemData.stcProps.eEquipPartType = eEquipPartType;
      pstcItemData[piItemDataCount].stcItemData.stcProps.eEquipType = eEquipType;
      pstcItemData[piItemDataCount].stcItemData.bCanDrag = bCanDrag;
      pstcItemData[piItemDataCount].stcItemData.bCanDrop = bCanDrop;
      pstcItemData[piItemDataCount].stcItemData.iMaxDropNum = iMaxDropNum;
      pstcItemData[piItemDataCount].stcItemData.iPercentDrop = iPercentDrop;
      pstcItemData[piItemDataCount].stcItemData.stcProps.lItemTexture = iItemTexture;
      pstcItemData[piItemDataCount].stcItemData.stcProps.stcImgRect.lImageWidth = iTextureRectW;
      pstcItemData[piItemDataCount].stcItemData.stcProps.stcImgRect.lImageHeight = iTextureRectH;
      strcpy_s(pstcItemData[piItemDataCount].stcItemData.stcProps.strItemName,ZP_MAX_CHARBUFFER64,strItemName);
      strcpy_s(pstcItemData[piItemDataCount].stcItemData.stcProps.strInfoFileName,ZP_MAX_CHARBUFFER64,strInfoFileName);
      pstcItemData[piItemDataCount].stcItemData.stcProps.stcStats = stcItemStats;
      pstcItemData[piItemDataCount].stcItemData.bHasData = true;
      pstcItemData[piItemDataCount].stcItemData.bHasTexture = true;
      pstcItemData[piItemDataCount].stcItemData.bWhileDrag = false;
      pstcItemData[piItemDataCount].stcItemData.lSlotIDtoOtherGUI = -1;
      pstcItemData[piItemDataCount].stcItemData.bInUse = false;
      pstcItemData[piItemDataCount].stcItemData.bIsDelay = false;
      pstcItemData[piItemDataCount].stcItemData.stcSlotDelay.fFix = fDuration;
      pstcItemData[piItemDataCount].stcItemData.stcSlotDelay.fCount = 0;
      pstcItemData[piItemDataCount].stcItemData.stcProps.iSkillOwnerID = -1;
      pstcItemData[piItemDataCount].stcItemData.stcProps.lNumber = 1;
      pstcItemData[piItemDataCount].stcItemData.stcProps.lPrice = 5000;
      strcpy_s(pstcItemData[piItemDataCount].stcItemData.stcData64.strData,ZP_MAX_CHARBUFFER64,"");
      strcpy_s(pstcItemData[piItemDataCount].stcItemData.stcData64.strShowData,ZP_MAX_CHARBUFFER64,"");
      piItemDataCount++;
      return piItemDataCount-1;
   }
   return -1;
}


การเรียกใช้
Code:
   ZP_STC_MAIN_STATS stcItemStatsBuff;
//ยาเติมพลัง
   stcItemStatsBuff.stcHP.lReal = 5000;
   clsZPGAME.CreateItemDropData(clsZPGAME.GetItemTPID("HPPotion"),5101,255,0,7000,1,ZP_STC_RGBACOLOR(1.0f,1.0f,1.0f,1.0f),ZP_ITEM_ONETIME,ZP_NONEEQUIP,ZP_NONEFIX
      ,true,true,3,5,ctvGlobal->GetTex("HPPotion"),40,40,"HP Potion S","InfoData\\Item\\HPPotion.txt",stcItemStatsBuff);

//อาวุธ
   clsZPGAME.ResetStats(stcItemStatsBuff,true);
   stcItemStatsBuff.stcSTR.lReal = 30;
   stcItemStatsBuff.stcVIT.lReal = 30;
   stcItemStatsBuff.stcINT.lReal = 30;
   stcItemStatsBuff.stcAGI.lReal = 30;
   stcItemStatsBuff.stcDEX.lReal = 30;
   stcItemStatsBuff.stcLUK.lReal = 30;
   stcItemStatsBuff.stcSPR.lReal = 30;
   stcItemStatsBuff.stcSTR.fPercentAmp = 10;
   stcItemStatsBuff.stcVIT.fPercentAmp = 10;
   stcItemStatsBuff.stcINT.fPercentAmp = 10;
   stcItemStatsBuff.stcAGI.fPercentAmp = 10;
   stcItemStatsBuff.stcDEX.fPercentAmp = 10;
   stcItemStatsBuff.stcLUK.fPercentAmp = 10;
   stcItemStatsBuff.stcSPR.fPercentAmp = 10;
   stcItemStatsBuff.stcATK.lReal = 1900;
   stcItemStatsBuff.stcATK.fPercentAmp = 20;
   stcItemStatsBuff.stcMATK.lReal = 1400;
   stcItemStatsBuff.stcMATK.fPercentAmp = 20;
   stcItemStatsBuff.stcCRI.lReal = 7;
   clsZPGAME.CreateItemDropData(clsZPGAME.GetItemTPID("Sword1"),505,1,0,0,1,ZP_STC_RGBACOLOR(0.0f,1.0f,0.0f,1.0f),ZP_ITEM_EQUIPMENT,ZP_EQUIPWEAPON,ZP_NONEFIX
      ,true,true,1,1,ctvGlobal->GetTex("DragonTooth_Sword"),40,40,"DragonTooth_Sword","InfoData\\Item\\DragonTooth_Sword.txt",stcItemStatsBuff);


วิธีนี้สามารถใช้ได้กับทุกส่วนของ Programmimg Model  อย่างระบบ Monster ระบบ  Stage ต่างๆ
เวลาเราเรียกใช้งานในลูปเกมส์ เราก็เพียงแต่เรียกใช้ด้วย ID ของ Template นั้นๆที่เรากำหนดขึ้นมา

แต่วิธีนี้จะค่อนข้างเปลือง Memory เพราะยิ่ง Template เยอะก็จะยิ่งต้องใช้ Memory เยอะตามไปด้วย

เรื่องของ Template ค่อนข้างมีความยืดหยุ่นในการใช้งาน เพราะ เราสามารถเพิ่มรูปแบบของ Content ได้ง่าย
และมีความเร็วในการทำงานสูง เพราะเราโหลดทุกอย่างมาไว้ในเครื่องแล้ว

แต่ก็สามารถประยุกต์ใช้งานได้ เช่นมีแต่ชื่อไฟล์เอาไว้ แล้วค่อยทำการโหลดไฟล์จริง ระหว่างเกมส์ loop ก็ได้
แล้วแต่สะดวก  แต่ต้องมีการจัดการเรื่อง Memory ให้ดี

ถ้าเปรียบเทียบกับการสร้างเกมส์ Online ตัว Object Template จะเหมือนกับ Table ใน DBMS นั่นเอง
ที่มี fields ต่างๆเป็นตัวกำหนด Properties

จบแล้วครับ


Top 
 Profile  
 
 Post subject: Re: Defend Master Game Design Model
 Post Posted: Sat Mar 19, 2011 8:02 pm 
Offline

Joined: Sat Mar 19, 2011 7:59 pm
Posts: 2
โค้ดสีเขียว ดูแสบตาไปนะผมว่า เพราะพื้นหลังเวปนี้มันสีดำหงะ T^T


Top 
 Profile  
 
 Post subject: Re: Defend Master Game Design Model
 Post Posted: Sun Mar 20, 2011 10:31 pm 
Offline
Site Admin

Joined: Sat Feb 19, 2011 1:33 am
Posts: 15
ครับเอาไว้ เดี๋ยวผมจะดูให้ครับ
พอดีมันเป็นทีมโหลดมา 8-)


Top 
 Profile  
 
 Post subject: Re: Defend Master Game Design Model
 Post Posted: Mon Mar 21, 2011 2:12 pm 
Offline

Joined: Sat Mar 19, 2011 7:59 pm
Posts: 2
คุณผมขอเมล msn ได้ไหมคับ เผื่อมีเรื่งอต้องการปรึกษา ^^

ผมมือใหม่หัดใข้ UDK อะคับ


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

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