pptx - Game Programming And Development

Download Report

Transcript pptx - Game Programming And Development

Game State และ
Game Component
Suphot Sawattiwong
[email protected]
1
GameComponent ใน XNA
• ใน XNA มีการสร้ าง Component เพื่อเรี ยกใช้ ในเกม ใน Class
Game Component โดยใน Class ดังกล่าวมีโครงสร้ างในการ
แยก logic ในการใช้ งานออกจากตัว Class Game หลักได้ และ
สามารถเพิ่ม class GameComponent ใส่ไว้ ใน project
อื่นๆ ได้ ด้วยเช่นกัน
• แต่ GameComponent มีแค่ Method Update เท่านัน้
หากต้ องการให้ มีการควบคุมการ Draw ด้ วยให้ ใช้
DrawableGameComponent
2
GameComponent ใน XNA
• ใน XNA มีการสร้ าง Component เพื่อเรี ยกใช้ ในเกม ใน Class
Game Component โดยใน Class ดังกล่าวมีโครงสร้ างในการ
แยก logic ในการใช้ งานออกจากตัว Class Game หลักได้ และ
สามารถเพิ่ม class GameComponent ใส่ไว้ ใน project
อื่นๆ ได้ ด้วยเช่นกัน
• แต่ GameComponent มีแค่ Method Update เท่านัน้
3
การใช้งาน Game Component
• Game Component เป็ น Class พิเศษของ XNA ที่ทางาน
โดยต้ องทาการ Add เข้ า Component Collection ซึง่ ทาได้
ดังนี ้
1. ประกาศตัวแปร GameComponent
GameComponent1 gameComp;
2. ทาการประกาศ Instance ใน Method Initialize
gameComp = new GameComponent1(this);
3. ทาการ Add เข้ า Component Collection ใน Method
Initialize
Components.Add(gameComp);
4
การทางานของ Game Component
• ดูใน Project
Ex10_GameComponentGameLoop1
5
การทางานของ Game Component
Main Before Game1 game = new Game1()
===================Game1 Constructor
Before game.Run();
===================Initialize
===================Before new GameComponent1(this)
-------------------------------------------GameComponent1 Constructor
===================After new GameComponent1(this)
===================Before Components.Add(gameComp)
===================After Components.Add(gameComp)
===================Initialize Before Base.Initialize
-------------------------------------------GameComponent1 Initialize() Before base.Initialize()
-------------------------------------------GameComponent1 Initialize() After base.Initialize()
===================LoadContent
===================Initialize Afer Base.Initialize
===================Update Before Base.Update
-------------------------------------------GameComponent1 Update() Before base.Update()
-------------------------------------------GameComponent1 Update() After base.Update()
===================Update After Base.Update
===================Draw Before Base.Draw
===================Draw After Base.Draw
6
การทางานของ Game Component
===================Update Before Base.Update
-------------------------------------------GameComponent1
Update() Before base.Update()
-------------------------------------------GameComponent1
Update() After base.Update()
===================Update After Base.Update
===================Draw Before Base.Draw
===================Draw After Base.Draw
After game.Run();
===================UnloadContent
7
การทางานของ Game Component 2 อัน
Main Before Game1 game = new Game1()
===================Game1 Constructor
Before game.Run();
===================Initialize
===================Before new GameComponent1(this)
-------------------------------------------GameComponent1 Constructor
===================After new GameComponent1(this)
===================Before Components.Add(gameComp)
===================After Components.Add(gameComp)
===================Before new GameComponent2(this)
______________________GameComponent2 Constructor
===================After new GameComponent2(this)
===================Before Components.Add(gameComp2)
===================After Components.Add(gameComp2)
ดูใน Ex11_GameComponentGameLoop2
8
การทางานของ Game Component 2 อัน
===================Initialize Before Base.Initialize
-------------------------------------------GameComponent1 Initialize() Before base.Initialize()
-------------------------------------------GameComponent1 Initialize() After base.Initialize()
______________________GameComponent2 Initialize() Before base.Initialize()
______________________GameComponent2 Initialize() After base.Initialize()
===================LoadContent
===================Initialize Afer Base.Initialize
===================Update Before Base.Update
-------------------------------------------GameComponent1 Update() Before base.Update()
-------------------------------------------GameComponent1 Update() After base.Update()
______________________GameComponent2 Update() Before base.Update()
______________________GameComponent2 Update() After base.Update()
===================Update After Base.Update
9
การทางานของ Game Component 2 อัน
===================Update Before Base.Update
-------------------------------------------GameComponent1 Update() Before base.Update()
-------------------------------------------GameComponent1 Update() After base.Update()
______________________GameComponent2 Update() Before base.Update()
______________________GameComponent2 Update() After base.Update()
===================Update After Base.Update
===================Draw Before Base.Draw
===================Draw After Base.Draw
===================Update Before Base.Update
-------------------------------------------GameComponent1 Update() Before base.Update()
-------------------------------------------GameComponent1 Update() After base.Update()
______________________GameComponent2 Update() Before base.Update()
______________________GameComponent2 Update() After base.Update()
===================Update After Base.Update
10
การทางานของ Game Component 2 อัน
===================Update Before Base.Update
-------------------------------------------GameComponent1 Update() Before base.Update()
-------------------------------------------GameComponent1 Update() After base.Update()
______________________GameComponent2 Update() Before base.Update()
______________________GameComponent2 Update() After base.Update()
===================Update After Base.Update
===================Draw Before Base.Draw
===================Draw After Base.Draw
After game.Run();
===================UnloadContent
11
คาสัง่ ที่ใช้ในการลบ Game Component
• หากมี Game Component อันไหน ที่ไม่ได้ ใช้ หากต้ องการทา
การลบ ให้ ใช้ คาสัง่
• เช่น
Components.Remove(<ชื่อ Component>);
Components.Remove(gameComp2);
12
DrawableGameComponent
• GameComponent มีแต่ Method Update ดังนัน้
• หากต้ องการให้ มีการควบคุมการ Draw ด้ วย ทางทีมพัฒนา
DrawableGameComponent
13
DrawableGameComponent
• จากก่อนหน้ านี ้ ได้ มีการใช้ วิธีคานวณ fps ตอนนี ้มาทา fps
DrawableGameComponent ขึ ้นมา
• เริ่มแรกสร้ าง Project ที่ชื่อ Ex12_FPSDrawable
• กด Add New Item โดยการ click ขวา ใน Solution
Explorer
• เลือก GameComponent แล้ วตังชื
้ ่อว่า FPS
14
ตัวอย่างการเปลี่ยน GameComponent เป็ น
DrawableGameComponent
จาก
public class
FPS : Microsoft.Xna.Framework.GameComponent
เป็ น
public class FPS :
Microsoft.Xna.Framework.DrawableGameComponent
ให้ ดใู น Project ที่ชื่อว่า FPSDrawable
15
ตัวอย่างการ add GameComponent ลงใน
Game1.cs
• ประกาศตัวแปร ที่เป็ นชื่อของ GameComponent นัน้ เช่นในที่นี ้
private FPS fps;
เพิ่ม code ในส่วนของ Initialize หรื อ Method ที่เหมาะสม
แล้ วแต่กรณี ให้ มีการเรี ยก instance แล้ วทาการ add เข้ าไป
เช่น
fps = new FPS(this, true, true,
this.TargetElapsedTime);
Components.Add(fps);
16
การเพิ่ม Library เข้า Project
• ให้ click ขวา ตามรูป
• แล้ วเลือก add ไปที่ Existing project ดังภาพ
• เลือก Folder Project Library ที่ต้องการแล้ วกด ok
17
การเพิ่ม Library เข้า Project
• ให้ click ขวา ตามรูปแล้ วเลือก
add Reference…
18
การเพิ่ม Library เข้า Project
• เลือก Library ที่ต้องการ ตามรูป แล้ วกด ok
19
การเพิ่ม Library เข้า Project
• จากนันให้
้ ทาการพิมพ์ข้อความเพื่อขอใช้ Library โดยการพิมพ์
using ตามด้ วยชื่อ NameSpace เช่น
using PhotXNALibrary;
• จากนันสามารถใช้
้
งานได้ ตามปกติตอ่ ไป ลองดูตามตัวอย่างต่อไปใน
เรื่ องของ SpriteAnimation
20
Parallax Scrolling
Suphot Sawattiwong
[email protected]
21
Parallax Scrolling
• การทา Parallax Background คือการวาด Background
ต่อเนื่องกันไป ให้ ดเู หมือนกับว่า มี Background ที่ยาวมากแบบไร้
ชอบเขต โดยหลักการจะมีการDraw Background 2 รอบเพื่อ
ทาให้ ตอ่ เนื่องกันไป
22
วิธีการใช้งาน Parallax Scrolling
• ก่อนอื่นให้ ทาการ ประกาศตัวแปรดังต่อไปนี ้
ScrollingBackground ตัวแปร BG;
เช่ น ScrollingBackground scBg;
• ดูใน Ex13_ParallaxBackground
• ทำกำรประกำศ Constructor ดังต่ อไปนี ้
scBg = new ScrollingBackground(this);
• ทาการ Add Component ดังต่อไปนี ้
Components.Add(scBg);
23
การ Load BG
• ตัวแปร ParallaxBG.Load(ชื่อไฟล์, ควำมกว้ ำง, ควำมยำว,
ควำมเร็ว, FPS); โดย Load ที่ LoadContent
• เช่ น
scBg.Load("SlideBG_01_1",
graphics.PreferredBackBufferWidth,
graphics.PreferredBackBufferHeight, 1, 45);
24
การวาด Parallax Background
• การวาด BG ทาได้ ใน Method Draw ดังนี ้
ตัวแปร.Draw(เวลาในเกม หรื อ GameTime, ตัวแปร
SpriteBatch);
เช่น scBg.Draw(gameTime, spriteBatch);
25
Game State
• เกมมีการทางานหลายส่วน
และหลายหน้ าจอ อย่างเช่นดัง
ตัวอย่าง
• การจัดการหน้ าจอ เหล่านี ้
จาเป็ นต้ องแยก state ออก
จากกันเพื่อให้ สะดวกในการ
เขียน และ debug
26
Game State
• วิธีการแบ่ง GameState มีหลายวิธี
• การทาGameState แบบที่ง่ายที่สดุ คือการใช้ if else หรื อ
switch case ในการแยก state โดยจะทาทังในส่
้ วน Method
Draw และ Update
• ทดลองทา GameState แบบง่ายๆ โดยเปิ ด
Ex14_GameStateAndMenu
27
การทา GameState
• ก่อนอื่น สร้ าง enum GameState ใน game1.cs เหนือ
Class Game1 ดังนี ้
enum GameState
{
MENU=0,
PLAY,
GAMEOVER,
OPTION
}
28
การทา GameState
• ประกาศตัวแปร ดังต่อไปนี ้ ใน Class Game1
GameState currentGameState;
• ใน Method Initialize() ให้ ทาการกาหนดดังต่อไปนี ้
currentGameState = GameState.MENU;
เพื่อกาหนดให้ เกมเริ่มต้ นที่ หน้ า Menu
29
การทา GameState
• ในส่วน Method Update ให้ เพิ่มดังต่อไปนี ้
switch (currentGameState)
{
case GameState.MENU:
UpdateMenu(gameTime);
break;
case GameState.PLAY:
UpdatePlay(gameTime);
break;
}
ในส่วนนี ้บอกว่าหาก currentGameState เป็ น Menu ก็จะเข้ า
ไปทาการ updateในส่วน UpdateMenu เป็ นต้ น
30
การทา GameState
• สร้ าง Method UpdateMenu และ UpdatePlay ดังนี ้
private void
gameTime)
{
// TODO:
}
private void
gameTime)
{
// TODO:
}
UpdateMenu(GameTime
เพิม่ ส่ วนการ Update หน้า Menu
UpdatePlay(GameTime
เพิม่ ส่ วนการ Update หน้า Play
31
การทา GameState
• เช่นกันให้ ทาแบบเดียวกันกับ Draw Method
switch (currentGameState)
{
case GameState.MENU:
DrawMenu(gameTime);
break;
case GameState.PLAY:
DrawPlay(gameTime);
break;
}
32
การทา GameState
• สร้ าง Method DrawMenu และ DrawPlay ดังนี ้
private void
gameTime)
{
// TODO:
}
private void
gameTime)
{
// TODO:
}
DrawMenu(GameTime
เพิ่มส่ วนการ Draw หน้า Menu
DrawPlay(GameTime
เพิ่มส่ วนการ Draw หน้า Play
33
Game State
• จากวิธีข้างต้ น เห็นได้ ชดั ว่าค่อนข้ างยุง่ ยากและทาให้ Code ค่อนข้ าง
ซับซ้ อน และในทุก Loop Update กับ Draw ต้ องเช็คค่า
currentState เพื่อเลือกทา Method ที่ถกู ต้ อง มันทาให้
เสียเวลา
• วิธีการทา GameState ที่น่าสนใจที่ควรลองไปศึกษาและทาความ
เข้ าใจ หากมีพื ้นฐาน Programming ที่ดี
http://creators.xna.com/en-US/samples/gamestatemanagement
34
Lab7:เกมจับคู่ Card ต่างๆ ต่อไปนี้
1. Card ในที่นี ้ ผมให้ ใช้ Card จานวนทังหมด
้
10 ใบ โดยจะ
เหมือนกัน 5 คู่
2. Random ตาแหน่งของ Card แต่ละใบ โดยเริ่มแรกให้ คว่าไพ่ไว้
ก่อน
3. ให้ ใช้ Mouse เลือกจับคู่ Card โดยหากจับได้ การ์ ดที่ไม่ตรงกัน
ให้ จดั การคว่าหน้ า Card เหมือนเดิม และทาการลบคะแนนไป 100
หากจับคูไ่ ด้ ไม่ต้องวาดการ์ ดคูน่ นอี
ั ้ ก และทาการบวกคะแนนให้ 200
35
Matching Game
36
Matching Game
• สถานะของ Card ควรจะมีดงั ต่อไปนี ้
– None กรณี ไม่วาด Card
– Close กรณีคว่า Card
– Open กรณีเปิ ด Card
enum CardStatus
{
NONE,
CLOSE,
OPEN
}
37
แนวคิดการทาเกมไพ่
Suphot Sawattiwong
38
จากโจทย์การทาเกมไพ่จบั คู่
• สิ่งที่เรารู้แน่ๆ ว่าต้ องทาคือ
1. ต้ องวาดไพ่ 10 ใบ บนหน้ าจอ
2. ไพ่ มี 5 แบบ
3. แบบละ 2 ใบ ถ้ าเกินจะจับคูไ่ ม่ได้
39
การวาดภาพไพ่
• เนื่องจากเกมนี ้เป็ นเกมไพ่ ควรที่จะเริ่มจากการวาดไพ่ก่อนสิ่งที่จาเป็ น
กับการวาดไพ่มีอะไรบ้ าง
– ตาแหน่งของไพ่ทงั ้ 10 ใบ
เมื่อลองได้ แค่นี ้ ให้ ทดลองประกาศ Class Card ออกมาดังนี ้
class Card
{
public Vector2 pos;
public Card(Vector2 pos)
{
this.pos = pos;
}
}
40
การวาดภาพไพ่
• เมื่อได้ Class แล้ วกลับมาที่ Game1.cs เพื่อประกาศการใช้
Array ดังนี ้
Card [] card=new Card[10];
• ทาการประกาศตัวแปร Texture2D สาหรับการทาหลังไพ่ดงั นี ้
Texture2D backCardTexture;
• จัดการLoad ภาพใน LoadContentดังนี ้
backCardTexture = Content.Load<Texture2D>(@"backcover");
41
การวาดไพ่
• การวาดภาพไพ่ที่เป็ น array ทาได้ โดยดังนี ้
1. กาหนดตาแหน่งให้ Card แต่ละใบก่อน
2. ทาการวาด Draw Method
42
กาหนดตาแหน่งให้ Card แต่ละใบก่อน
• เนื่องจาก Card ที่กาหนดขึ ้นเป็ นเพียงแค่จองสมาชิก Array เท่านัน้
มันไม่มีคา่ หรื อเป็ น null อยูน่ นั่ เองจาเป็ นต้ องประกาศ instance
เพื่อให้ มีคา่ ใน LoadContent ดังต่อไปนี ้
card[0] = new Card(new Vector2(130, 30));
card[1] = new Card(new Vector2(260, 30));
card[2] = new Card(new Vector2(390, 30));
card[3] = new Card(new Vector2(520, 30));
card[4] = new Card(new Vector2(650, 30));
card[5] = new Card(new Vector2(130, 230));
card[6] = new Card(new Vector2(260, 230));
card[7] = new Card(new Vector2(390, 230));
card[8] = new Card(new Vector2(520, 230));
card[9] = new Card(new Vector2(650, 230));
43
ทาการวาด Draw Method
• ให้ ทาการวาดภาพที่ Draw Method ดังนี ้
spriteBatch.Begin();
for(int i=0;i<10;i++)
{
spriteBatch.Draw(backCardTexture, card[i].pos,
Color.White);
}
spriteBatch.End();
44
จะได้ดงั ภาพ
45
ชนิดของไพ่
• ในโจทย์เรามีไพ่ทงหมด
ั้
5 แบบ ซึง่ ต้ อง สุม่ เข้ ามาในไพ่ 10 ใบ โดยให้ ซ ้า
กันแค่อย่างละ 1 คู่
• ก่อนอื่นให้ ทาการกาหนดชนิดไพ่ก่อนประกาศ Class Card ดังนี ้
public enum CardType
{
TYPE1 = 0,
TYPE2,
TYPE3,
TYPE4,
TYPE5
};
46
ชนิดของไพ่
• แล้ วให้ ทาการเพิ่มและทับบรรทัดต่อไปนี ้ในส่วน Constructor
{
}
public Vector2 pos;
public CardType cardType;
public Card(Vector2 pos, CardType cardType)
this.pos = pos;
this.cardType = cardType;
47
ทาการ Load หน้าไพ่ท้ งั 5แบบใน LoadContent
• ก่อนอื่นให้ ทาการประกาศตัวแปรใน Class Game1 เป็ น
Texture2D[5] ดังนี ้
Texture2D[] cardTexture= new Texture2D[5];
• ทาการ LoadContent ดังนี ้
for (int i = 0; i < 5; i++)
{
cardTexture[i] = Content.Load<Texture2D>(@"card0" + (i + 1));
}
48
ทาการแก้ไขการกาหนดค่าใน LoadContent ดังนี้
• เริ่มแก้ ไขการประกาศ Instance ก่อนหน้ า
card[0] = new Card(new Vector2(130, 30), CardType.TYPE1);
card[1] = new Card(new Vector2(260, 30), CardType.TYPE1);
card[2] = new Card(new Vector2(390, 30), CardType.TYPE2);
card[3] = new Card(new Vector2(520, 30), CardType.TYPE2);
card[4] = new Card(new Vector2(650, 30), CardType.TYPE3);
card[5] = new Card(new Vector2(130, 230), CardType.TYPE3);
card[6] = new Card(new Vector2(260, 230), CardType.TYPE4);
card[7] = new Card(new Vector2(390, 230), CardType.TYPE4);
card[8] = new Card(new Vector2(520, 230), CardType.TYPE5);
card[9] = new Card(new Vector2(650, 230), CardType.TYPE5);
49
ปรับเปลี่ยนใน Draw Method
• ให้ ทาการปรับเปลี่ยนดังนี ้
spriteBatch.Begin();
for(int i=0;i<10;i++)
{
spriteBatch.Draw(cardTexture[(int)card[i].cardType], card[i].pos, Color.White);
}
spriteBatch.End();
50
จะได้ภาพดังนี้
51
การสุ่ มไพ่
• เหตุที่ต้องนาไพ่มาเรี ยงกันเนื่องจาก เราจาเป็ นต้ องสุม่ โดยที่ไพ่ที่ได้ นนั ้
ต้ องมี 1 คู่ แน่นอน และครบทัง้ 5 คู่ หากไม่จดั เรี ยงหน้ าไพ่ก่อนจะทาได้
ลาบาก
• โดยการสุม่ ทาได้ ดงั นี ้
1.
2.
3.
4.
ให้ ทาการวนลูปตามจานวนสมาชิก
ภายในลูปให้ สมุ่ ตัวเลขไม่เกินเลข index ของสมาชิก
เมื่อได้ เลขมา ให้ ทาการสลับค่า cardType ระหว่าง card ทัง้ 2 ใบ
วนกลับไปจนกว่าจะครบจานวนสมาชิก
52
การสุ่ มไพ่
• ทาการเขียน Method ในการสุม่ ไพ่ใน Game1.cs ดังนี ้
protected void randomCard()
{
for (int i = 0; i < 10; i++)
{
int r = rand.Next(10);
if (i != r)
{
CardType t;
t = card[i].cardType;
card[i].cardType = card[r].cardType;
card[r].cardType = t;
}
}
}
53
ภาพที่ได้จะออกมาดังนี้
54