วันอังคารที่ 15 กุมภาพันธ์ พ.ศ. 2554

Final



ต่อจากนี้จะเป็นการอธิบาย Code 
CDXSprite *jet;
CDXSprite *bg;
CDXSprite *logo;
CDXSnd* g_snd; 

POINT pos;
int score = 0;
int game_stage = 1;
int live = 3;

ประกาศตัวแปร CDXSprite ไว้เก็บพวกภาพ sprite ต่าง ๆ
CDXSnd ไว้เก็บค่าเสียง
POINT เก็บค่าตำแหน่งของตัวละคร
score คือ คะแนน
game_stage ใช้เก็บว่าตอนนี้อยู่หน้าไหน
live คือ จำนวนชีวิตของเรา

typedef struct 
{
 CDXSprite *missile;
 POINT pos, di, vel;
}Missile_info;
irr::core::array mlist;
irr::core::array elist;

bool AddMis( char* name, const POINT& pos, const POINT& di, const POINT& vel );
void UpdateMis(void);
void RemoveMis(void);

สร้าง โครงสร้างของตัวแปะชื่อ Missile_info
ต่อมาก็สร้าง Missile_info ชื่อ mlist ใช้กับกระสุนและ elist ใช้กับศัตรู

ประกาศชื่อ function ไว้ใช้ก่อน

bool AddMis( char* name, const POINT& pos, const POINT& di, const POINT& vel )
{
 Missile_info* minfo = new Missile_info( );
 minfo->missile = new CDXSprite( );
 minfo->missile->Create( name, 1 );
 minfo->pos = pos;
 minfo->di = di;
 minfo->vel = vel;
 mlist.push_back( minfo );
 return true;
}
สร้างฟังชั่นชื่อ AddMis ใช้เพื่อเรียกกระสุนออกมา (รายละเอียดดูใน WP2)

void UpdateMis(void)
{
 for( irr::u32 i = 0; i != mlist.size(); i++ )
 {
  mlist[i]->pos.x += mlist[i]->di.x * mlist[i]->vel.x;
  mlist[i]->pos.y += mlist[i]->di.y * mlist[i]->vel.y;
  mlist[i]->missile->SetPos( mlist[i]->pos.x, mlist[i]->pos.y );
  mlist[i]->missile->Draw( Screen->GetBack(), 0, 0, CDXBLT_TRANS );
  
 }
}
สร้างฟังชั่น UpdateMis ไว้ใช้สำหรับทำให้กระสุนขยับโดยเราสามารถกำหนดที่หลังได้ว่าต้องการให้ไปทางไหน

bool AddEnemy( char* name, const POINT& pos, const POINT& di, const POINT& vel )
{
 Missile_info* enemy = new Missile_info( );
 enemy->missile = new CDXSprite( );
 enemy->missile->Create( name, 1 );
 enemy->pos = pos;
 enemy->di = di;
 enemy->vel = vel;
 elist.push_back( enemy );
 return true;
}

สร้างฟังชั่น AddEnemy เพื่อใช้เรียกสร้าง ศตรูเจ้ามาในเกม


void insterEnemy(void)
{
 POINT di = { 0, 1 };
 POINT vel = { 0, rand() % 5+3 };
 POINT pos = { rand() % 400 + 40,rand() % 150*-1};
 AddEnemy( "boss.png", pos, di, vel );

}

สำหรับฟังชั่นนี้จะเป็นการสร้างศัตรูออกมาโดยที่จะสุ่มทั้งความเร็วและ ตำแหน่งของศัตรู

void inEnemy(void)
{
 for(int i = 0;i < rand() % 3+1;i ++)
 {
  insterEnemy();
 }
}
จะเป็นการสั่งให้ฟังชั่น insterEnemy ทำงานโดยจำนวนรอบที่ทำงานนั้นจะเกิดจากการสุ่ม
void UpdateEnemy(void)
{
 for( irr::u32 i = 0; i != elist.size(); i++ )
 {
  elist[i]->pos.x += elist[i]->di.x * elist[i]->vel.x;
  elist[i]->pos.y += elist[i]->di.y * elist[i]->vel.y;
  elist[i]->missile->SetPos( elist[i]->pos.x, elist[i]->pos.y );
  elist[i]->missile->Draw( Screen->GetBack(), 0, 0, CDXBLT_TRANS );
  
 }
}
สั่งให้ศัตรูขยับ
void RemoveMis(void)
{
 for( irr::u32 i = 0; i != mlist.size(); ++i )
 {
  if( mlist[i]->pos.x < 0 ||
   mlist[i]->pos.x > 480 || 
   mlist[i]->pos.y < 0 ||
   mlist[i]->pos.y > 272 )
  {
   SAFEDELETE( mlist[i]->missile );
   SAFEDELETE( mlist[i] );
   mlist.erase( i );
   --i;
   continue;
  }

  
 for( irr::u32 q = 0; q != elist.size(); ++q )
 {
  if(mlist[i]->missile->SpriteHit(elist[q]->missile) )
  {
   score += 100;
   
   SAFEDELETE( mlist[i]->missile );
   SAFEDELETE( mlist[i] );
   mlist.erase( i );
   --i;
   
   SAFEDELETE( elist[q]->missile );
   SAFEDELETE( elist[q] );
   elist.erase( q );
   --q;

   break;
  }
  if(elist.size() < 3)
  {
   inEnemy();
  }
 }
  
 }

 for( irr::u32 i = 0; i != elist.size(); ++i )
 {
  if( elist[i]->pos.x < 0 ||
   elist[i]->pos.x > 480 || 
   elist[i]->pos.y < -150 ||
   elist[i]->pos.y > 272 )
  {
   SAFEDELETE( elist[i]->missile );
   SAFEDELETE( elist[i] );
   elist.erase( i );
   --i;
   inEnemy();
   continue;
  }

  if(elist[i]->missile->SpriteHit(jet) )
  {
   SAFEDELETE( elist[i]->missile );
   SAFEDELETE( elist[i] );
   elist.erase( i );
   --i;
   inEnemy();
   pos.x = 200;
   pos.y = 200;
   live -=1;
   continue;
  }

 }
}
สำหรับอันนี้จะขอแยกออกเป็นส่วนๆ
for( irr::u32 i = 0; i != mlist.size(); ++i )
 {
  if( mlist[i]->pos.x < 0 ||
   mlist[i]->pos.x > 480 || 
   mlist[i]->pos.y < 0 ||
   mlist[i]->pos.y > 272 )
  {
   SAFEDELETE( mlist[i]->missile );
   SAFEDELETE( mlist[i] );
   mlist.erase( i );
   --i;
   continue;
  }

  
 for( irr::u32 q = 0; q != elist.size(); ++q )
 {
  if(mlist[i]->missile->SpriteHit(elist[q]->missile) )
  {
   score += 100;
   
   SAFEDELETE( mlist[i]->missile );
   SAFEDELETE( mlist[i] );
   mlist.erase( i );
   --i;
   
   SAFEDELETE( elist[q]->missile );
   SAFEDELETE( elist[q] );
   elist.erase( q );
   --q;

   break;
  }
  if(elist.size() < 3)
  {
   inEnemy();
  }
 }
  
 }

สำหรับ if แรกจะเป็นการบอกว่าถ้ากระุสุนเกินหน้าจอออกไปก็ให้ ลบ กระสุ่นนั้นๆออกไป และสำหรับ if ที่ 2 จะเป็นการเช็คว่ากระสุนชนกับศัตรูหรือยัง ถ้าชนแล้วก็ บวกคะแนนเข้าไป 100 และสั่งลบทั้งกระสุนและศัตรูออกไป และสั่ง break เนื่องจากในตอนแรกนั้นใช้ continue แต่ตัว code นั้นไม่ทำงานเพราะมันไปอ้างอิงกับตำแหน่งที่ถูกลบไปแล้ว และสำหรับ if สุดท้ายนั้นจะเป็นการเช็กว่ามีจำนวนศัตรูอยู่ในเกมมากกว่า 3 ตัวหรือไม่ ถ้าไม่ก็จะไปส่งให้ศัตรูเกิดออกมาอีก
for( irr::u32 i = 0; i != elist.size(); ++i )
 {
  if( elist[i]->pos.x < 0 ||
   elist[i]->pos.x > 480 || 
   elist[i]->pos.y < -150 ||
   elist[i]->pos.y > 272 )
  {
   SAFEDELETE( elist[i]->missile );
   SAFEDELETE( elist[i] );
   elist.erase( i );
   --i;
   inEnemy();
   continue;
  }

  if(elist[i]->missile->SpriteHit(jet) )
  {
   SAFEDELETE( elist[i]->missile );
   SAFEDELETE( elist[i] );
   elist.erase( i );
   --i;
   inEnemy();
   pos.x = 200;
   pos.y = 200;
   live -=1;
   continue;
  }

 }
สำหรับส่วนนี้จะเป็นส่่วนของศัตรูทั้งหมด โดย if แรกจะเช็คว่าศัตรูนั้นออกไปนอกจอหรือยังถ้าออกไปแล้วก็สั่งลบ ส่วน if ที่ 2 จะเช็กว่าศัตรูได้ชนกับตัวผู้เล่้นหรือไม่ ถ้าชนก็จะลบออกไปเช่นกัน แต่จะลบจำนวนชีวิตไป 1 และย้ายตำแหน่งของผู้เล่นไปไว้ที่ x = 200 y = 200
g_snd = new CDXSnd( );
g_snd->Create( );

 
jet = new CDXSprite( );
jet->Create( "me.png", 1 );

bg = new CDXSprite( );
bg->Create( "bg.png", 1 );

logo = new CDXSprite( );
logo->Create( "logo.png", 1 );

 
pos.x = 200;
pos.y = 200;

insterEnemy();
อยู่ใน BOOL cdx_Init() เป็นการโหลดภาพฉากหลัง ตัวผู้เล่น โลโก้ และเสียงเข้ามาในเกม กำหนดจุดเกิดของผู้เล่นพร้อมทั้ง สั่งให้ศัตรูชุดแรกเกิด
for( irr::u32 i = 0; i != mlist.size(); ++i )
 {
  SAFEDELETE( mlist[i]->missile );
  SAFEDELETE( mlist[i] );
  mlist.erase( i );
  --i;
 }

 for( irr::u32 i = 0; i != elist.size(); ++i )
 {
  SAFEDELETE( elist[i]->missile );
  SAFEDELETE( elist[i] );
  elist.erase( i );
  --i;
 }

 SAFEDELETE( jet );
 SAFEDELETE( bg );
 SAFEDELETE( logo );
 SAFEDELETE( Fps );
 SAFEDELETE( Input );
 SAFEDELETE( Screen );
 SAFEDELETE( g_snd ); 

สั่งคืนค่าตัวแปรของทั้งหมดในเกม อยู่ใน void cdx_DeInit( void ) ส่วน void cdx_DoFrame()
if(game_stage == 1)
 {
  if( Input->GetKeyState(SDLK_SPACE) == CDXKEY_PRESS ||
  Input->GetKeyState(CDXKEY_JOYBUTN11) == CDXKEY_PRESS )
  game_stage = 2;

  logo->SetPos( 0,50 );
  logo->Draw( Screen->GetBack(), 0, 0, CDXBLT_TRANS );
 }
แสดงภาพของ Logo และเมื่อกดที่ space bar หรือ start ใน psp แล้วจะเป็นกาีรเปลี่ยนไปเป็นหน้า start game
if(game_stage == 2)
 { 
  TextXY( Screen->GetBack(), 20, 150, 233, 227, 66, 255, ETA_CENTER ,"Start Game" );
  if( Input->GetKeyState(SDLK_RETURN)||
  Input->GetKeyState(CDXKEY_JOYBUTN3))
  game_stage = 3;


 }
เป็นหน้า start game ที่ แสดงคำว่า Start Game ให้กด enter หรือ ปุ่มสี่เหลี่ยมเพื่อเข้าเกม
if(game_stage == 3)
 {
 if( (Input->GetKeyState(SDLK_RIGHT)||Input->GetKeyState(CDXKEY_JOYBUTN9)) && (pos.x < 438))
  pos.x += 8;
 if( (Input->GetKeyState(SDLK_LEFT)|| Input->GetKeyState(CDXKEY_JOYBUTN7))&&(pos.x > 5))
  pos.x -= 8;
 if( (Input->GetKeyState(SDLK_UP)||Input->GetKeyState(CDXKEY_JOYBUTN8)) && (pos.y > 0))
  pos.y -= 8;
 if( (Input->GetKeyState(SDLK_DOWN)||Input->GetKeyState(CDXKEY_JOYBUTN6)) && (pos.y < 200))
  pos.y += 8;
เนื่อจากในส่วนนี้เยอะจึงจะแยกเป็นส่วนๆ ในส่วนนี้จะเป็นการควบคุมตัวละครโดยใช้ปุ่มลูกศร
bg->SetPos( 0,0 );
bg->Draw( Screen->GetBack(), 0, 0, CDXBLT_TRANS );

jet->SetPos( pos.x, pos.y );
jet->Draw( Screen->GetBack(), 0, 0, CDXBLT_TRANS );

 
TextXY( Screen->GetBack(), 390, 20, 233, 227, 66, 255  ,"Score : " );
TextXY( Screen->GetBack(), 20, 20, 233, 227, 66, 255,  ETA_RIGHT ,"%d", score );
TextXY( Screen->GetBack(), 20, 150, 233, 227, 66, 255,  ETA_RIGHT ,"%d", live );
 
แสดงภาพฉากหลัง ตัวละคร และตัวอักษรต่างๆ ในที่นี้คือ คะแนน และ จำนวนชีวิต
POINT di = { 0, -1 };
 POINT vel = { 0, 10 };
 if( Input->GetKeyState(SDLK_SPACE) == CDXKEY_PRESS ||Input->GetKeyState(CDXKEY_JOYBUTN3) == CDXKEY_PRESS )
 {
  AddMis( "shot_me.png", pos, di, vel );
  g_snd->Play( "missile.wav" ); 

 }
กด space เป็นการยิงโดยโหลดเสียงด้วย
if((score < 5000) || (live > 1))
 {
  UpdateMis( );
  RemoveMis( );
  UpdateEnemy();
 }
กำหนดว่าถ้าคะแนนน้อยกว่า 500 หรือ จำนวนชีวิตมากกว่า 1 แล้ว สั่งให้ ฟังชั่นเหล่านี้ทำงาน
if(score >= 5000)
 {
  TextXY( Screen->GetBack(), 20, 150, 233, 227, 66, 255, ETA_CENTER ,"You Win" );

  if( Input->GetKeyState(SDLK_SPACE) == CDXKEY_PRESS ||
   Input->GetKeyState(CDXKEY_JOYBUTN11) == CDXKEY_PRESS )
  {
   score = 0;
   live = 3;
   game_stage = 1;
  }
 }

ถ้าคะแนนเกิน 5000 แล้วขึ้นว่า You Win และถ้ากด space bar แล้วจะกำหนดถ้า คะแนนเป็น 0 จำนวนชีวิตเป็น 3 และ กลับไปหน้า โลโก้
if(live <= 0)
 {
  TextXY( Screen->GetBack(), 20, 150, 233, 227, 66, 255, ETA_CENTER ,"Game Over" );

  if( Input->GetKeyState(SDLK_SPACE) == CDXKEY_PRESS ||
   Input->GetKeyState(CDXKEY_JOYBUTN11) == CDXKEY_PRESS )
  {
   score = 0;
   live = 3;
   game_stage = 1;
  }
 }

ถ้าจำนวนชีวิตเหลือ 0 แล้วให้ขึ้น Game Over และถ้ากด space bar แล้วจะกำหนดถ้า คะแนนเป็น 0 จำนวนชีวิตเป็น 3 และ กลับไปหน้า โลโก้

Game Play

ไม่มีความคิดเห็น:

แสดงความคิดเห็น