510 likes | 703 Views
2D Basic Programming for XNA. Suphot Sawattiwong tohpus@hotmail.com. Display Resolution.
E N D
2D Basic Programming for XNA SuphotSawattiwongtohpus@hotmail.com
Display Resolution • Display Resolution เป็นเรื่องที่ต้องทำความเข้าใจกันก่อน โดยปกติ Resolution ของ PC จะขึ้นอยู่กับ Computer ที่ใช้ โดยมาตรฐานปัจจุบัน อยู่ที่ 1024x768 แต่ถ้าหากเป็น WideScreen ก็จะมีจุดที่แตกต่างกันออกไปตาม ratio ที่เปลี่ยนไป • สำหรับ XBOX360 เนื่องจากเครื่องเกมได้ถูกใช้มาตรฐาน HD(High Definition) ซึ่งจะมีตั้งแต่ 480i, 480p, 720i,720p จนถึง 1080p • การที่เราทำเกมเราอาจจะต้องระวังเรื่อง Resolution ไว้ด้วยเช่นกัน
ความกว้างxยาวของจอภาพใน XNA • ความกว้างยาวของจอภาพ แบ่งเป็น 3 ลักษณะดังนี้ – Display Mode เป็นขอบเขตของหน้าจอของระบบ ซึ่งแตกต่างกับหน้าจอ หน้าต่างของเกม – Back Buffer เป็นขอบเขตเฉพาะในการแสดงผล ซึ่งใช้ในการคำนวณ next render โดยใน Windows Back Buffer จะมีค่าเดียวกับหน้าจอของเกม แต่สำหรับใน XBOX360 ถูกสร้างตาม User กำหนด และเมื่อ Fullscreen Mode บน Windows Back Buffer จะเป็นไปตาม Display Modeทันที – ViewPortเป็นหน้าจอที่ใช้แสดงผล เป็นลักษณะของกล้อง ซึ่งความกว้าง และ ความยาว เป็นความกว้างความยาวของกล้องด้วยเช่นกัน โดย viewport ไม่มีความเกี่ยวข้องกับ ขนาดของ Game Windows แต่ viewport สัมพันธ์กับค่า Display Mode
การทำงานกับ GraphicsDevice ใน XNA • การตั้งค่าหน้าจอ Windows graphics.PreferredBackBufferWidth = <ความกว้าง>; graphics.PreferredBackBufferHeight = <ความยาว>; • การทำให้ Windows เป็น โหมด Full Screen graphics.IsFullScreen = <true|false>; • การสลับโหมด Windows จาก Windows เป็น Full Screen หรือ Full Screen เป็น Windows Mode graphics.ToggleFullScreen(); • ดูตัวอย่างใน Project ScreenWidthHeight
Resouceที่ใช้ในเกม • File รูปภาพ ใน XNA สามารถอนุญาตให้ใช้รูปภาพเป็น jpg, gif, และ png ก็ได้ โดยปกติ เพื่อความสะดวกเราจะใช้ format pngในการทาภาพในเกม เนื่องจากว่าสะดวกในการเจาะ Transparent • Sound ที่ใช้ Support มี wav, aifและaiffแต่หากจะนามาใช้ต้องผ่าน tools ที่ชื่อว่า Microsoft Cross-Platform Audio Creation Tool (XACT)
Content Pipeline • โดยปกติ Game Resource จะถูก Load เก็บมาไว้ใน memory ก่อนที่จะทำการใช้งาน โดยที่ Content Pipeline จะเป็นตัวช่วยในการ load เข้ามา ซึ่งเป็นการนำ File ที่มีคุณสมบัติต่างกัน ไม่ว่าจะเป็น รูปภาพ หรือว่าเสียงจะถูกเก็บใน format ที่ง่ายต่อการโหลดเพื่อมาใช้ในเกมเมื่อเกม start • ขั้นแรกรู้จักตัวแปร ที่ชื่อ “Content” ใน Content.RootDirectory = "Content"; • เป็นตัวแปรที่ XNA กำหนดมาใน Class game ของ XNA เพื่อให้สะดวกต่อการใช้งาน • Content.RootDirectoryเป็นการบอกว่า Folder ที่ Content อยู่นั้น อยู่ใน Folder “Content” นั่นเอง
การนำภาพเข้า Project • Click ที่ Folder Content ใน Solution Explorer • เลือก Add>Add Exist Item แล้วไปยัง Folder ที่เรา Save ไฟล์ ภาพไว้ (ในแผ่น DVD Folder “Resource Example”)Fileภาพจะถูก copy เข้ามาไว้ใน Content ทันที
การวาดภาพใน XNA • ก่อนอื่นมาทำความเข้าใจของคำว่า Sprite คือรูปภาพนั่นเอง XNA ทำการอ้างถึงรูปภาพผ่านทาง Texture2D Object ซึ่งเราจะทำการวาดภาพเหล่านี้ลงบนหน้าจอโดยตรง • การวาดภาพใน XNA ต้องทำความรู้จักกับระบบ 2D Coordinate เสียก่อน เพื่อเข้าใจในตำแหน่งการวางภาพแบบ 2D • โดยในโลกของ 2D จะมีแค่ แกน x,yเท่านั้น ซึ่งต่างจาก 3D ที่ใช้ x, y, และ z • origin ของ XNA อยู่บนซ้ายสุดของหน้าจอ (0,0) คือ x= 0 และ y= 0
จอภาพ x+ Origin(0,0) y+ 2D Coordinate System
2D Coordinate System • จะเห็นได้ว่า หากหน้าจอมี Resolution 1024x768 จุดจะเริ่มจาก 0-1023 ในแนวแกน x และ 0-767 ในแนวแกน y และมุมขวาล่างสุดจะมีจุด (1023, 767) • ซึ่งใน XNA จะเก็บค่าตำแหน่งเหล่านี้ในตัวแปร Vector2 และตัวแปรแกน xและ y ในรูปแบบ int
จอภาพ Origin(0,0) Vector(100,60) y-offset=60 Position(100,60) x-offset=100 ตัวอย่างการวาดภาพในตำแหน่งที่ (100,60)
2D Transformation • ในโลก 2D นั้นนอกจากตำแหน่งของภาพแล้ว ยังสามารถทำการย้ายตำแหน่งของภาพได้ รวมถึง ย่อ/ขยาย และ หมุนภาพได้ สิ่งเหล่านี้เรียกรวมๆ ว่า “2D Transformation”
หากต้องการเลื่อนจากจุดเดิมไปอีก 120, 40 จุด
การหมุน (Rotate) • ใน XNA มีการสร้างจุด Origin ของ Sprite เพื่ออำนวย ความสะดวกใน Rotate หากเราใช้จุดเดิมในการหมุนจะออกมาเป็น แบบนี้
การใช้จุดOrigin ของ Sprite เพื่อใช้ในการหมุน • ใน XNA สามารถกำหนดจุด Origin ของ Sprite ได้ว่าต้องการให้อยู่ในจุดใดของภาพเพื่อสะดวกในการหมุน
การย่อ/ขยาย(scale) • การทำให้ Sprite มีขนาดใหญ่ขึ้นในการวาด ซึ่งใช้จุด origin ในการขยายเช่นกัน
Vector2 • Vector2 เป็นตัวแปรที่เก็บค่า 2 ตัว เรามักใช้กับการเก็บตำแหน่ง มี parameter ดังต่อไปนี้ Vector2 <ชื่อตัวแปร> = new Vector2(<จุดPositionX>,<จุด PositionY>);
Rectangle • เป็นตัวแปรที่เก็บขนาด สี่เหลี่ยม โดยมี parameter ใน Constructor ดังนี้ Rectangle <ชื่อตัวแปร> = new Rectangle(<จุดPosition X>, <จุด Position Y>, <กว้าง>,<สูง>);
SpriteBatch • ในเกมในปัจจุบันมีการใช้รูปภาพหลายรูปในหลายๆ ตำแหน่งของหน้าจอ มันเป็นเรื่องที่ยุ่งยากในการส่งผ่านข้อมูลของตำแหน่งและจัดการภาพเหล่านี้ให้มีประสิทธิภาพ • โดย XNA มี Class พิเศษสำหรับจัดการนี้โดยตรงนั่นคือ SpriteBatch • กำหนด SpriteBatch ไว้ใน Class Game ดังนี้ <private|public> SpriteBatch <ชื่อตัวแปร>; เช่น private SpriteBatch spriteBatch; • วางใน LoadContent ก็ได้ ให้ใส่การกำหนดค่าลงไปดังนี้ <ชื่อตัวแปร> = new SpriteBatch(<ตัวแปรGraphics>.GraphicsDevice); เช่น spriteBatch = new SpriteBatch(GraphicsDevice);
SpriteBatch • การทำงานของ Method SpriteBatch ในส่วนการ Draw ใน Draw Method นั้นแบ่งเป็นหลาย Method ดังนี้ • Begin() เป็นการบอกจุดเริ่มต้นของ SpriteBatch และยังมีการ set ค่าต่างๆ เช่น SpriteBlendMode, SpriteSortMode • Draw() ไว้สำหรับ Draw ภาพปกติโดยใช้ Texture2D • DrawString() ไว้สำหรับ Draw ข้อความที่ใช้ในเกม • End() เป็นการบอกจุดสิ้นสุดของ SpriteBatch
SpriteEffects • เป็น Effects ของ Sprite ที่ทำได้ในคำสั่ง Draw มีดังต่อไปนี้ • SpriteEffects.FlipHorizontallyไว้พลิกด้านแนวนอน • SpriteEffects.FlipVerticallyไว้พลิกด้านแนวตั้ง • SpriteEffects.Noneไม่มี Effect
Ex2: การวาดภาพBackground • สร้าง Project ชื่อ DrawBackgroundขึ้นมา • นำภาพ Background ใดก็ได้ไปใส่ใน โดยทำตามวิธีการนำไฟล์เข้า Project • พิมพ์ Code ในส่วนต่อไปนี้ประกาศตัวแปรใน Class Game1 ดังต่อไปนี้ GraphicsDeviceManagergraphics; SpriteBatchspriteBatch; Rectangle bgRect;//เป็นการประกาศตัวแปรที่เก็บตำแหน่งและขนาดของ Background Texture2D bgTexture;//ตัวแปรภาพที่เราใช้เป็นพื้นหลัง
ใน Constructor Game1 public Game1() { graphics = new GraphicsDeviceManager(this); graphics.PreferredBackBufferWidth =1024;// เป็นการกำหนดความกว้างของหน้าจอ graphics.PreferredBackBufferHeight =768;// เป็นการกำหนดความยาวของหน้าจอ Content.RootDirectory ="Content"; }
ใน Method Initialize protected override void Initialize() { bgRect = new Rectangle(0, 0, graphics.GraphicsDevice.Viewport.Width, graphics.GraphicsDevice.Viewport.Height); //graphics.GraphicsDevice.Viewport.Widthเป็นค่าความกว้างของ ViewPortหรือหน้าจอ //graphics.GraphicsDevice.Viewport.Heightเป็นค่าความยาวของ ViewPortหรือหน้าจอ base.Initialize(); }
ใน Method LoadContent protected override void LoadContent() { // Create a new SpriteBatch, which can be used to draw textures. spriteBatch = new SpriteBatch(GraphicsDevice); bgTexture =Content.Load<Texture2D>("Matching_bg"); //การเรียกใช้ Background }
ใน Method Draw protected override void Draw(GameTimegameTime) { GraphicsDevice.Clear(Color.CornflowerBlue); //การเติมสี Background spriteBatch.Begin(); // เริ่มการใช้ spriteBatch spriteBatch.Draw(bgTexture, bgRect, Color.White); // ทำการวาดรูป Background spriteBatch.End(); // จบการใช้ spriteBatch base.Draw(gameTime); }
Lab1: 2D Transformation และ Fade • ให้เขียนโปรแกรม และเคลื่อนที่ภาพจากซ้ายไปขวา หากมีการชนขอบจอให้มีการเด้งไปมาในจอภาพ • ให้ทดลองการวาดภาพโดยให้มีการหมุนภาพ • ลองวาดภาพให้มีการค่อยๆ ขยายจากเล็กไปใหญ่ • ให้มีการวาดภาพโดยการทำให้ภาพปกติ แล้วค่อยๆ ทำให้จางหายไป
Lab2: Tile • จงนำภาพที่ให้มา มาทำการต่อภาพให้เต็มจออย่างในภาพตัวอย่างต่อไปนี้
Lab3: Reflection • จงทำการวาดภาพที่ให้มาให้ออกมาในรูปแบบดังต่อไปนี้ โดยไม่มีการแก้ภาพที่ให้ใน Photoshop และ ภาพต้องอยู่ตรงกลางจอด้วย
การใช้ SpriteFont ในXNA • ใน XNA มีวิธีการแนบ Font จาก Windows เข้ามาในเกมได้เลย โดยสามารถใช้ TrueType Font ในเกม • การ Add SpriteFont เข้ามายัง project ก่อนมีขั้นตอนดังนี้ • Click ขวาที่ Folder Content ใน Solution Explorer • เลือกที่Add> Add New Item เลือก SpriteFont แล้วตั้งชื่อให้ตรงกับfont แต่ไม่ควรมี space แล้วตามด้วย Size เช่น Angsana14 • จากนั้นให้เปิด sprite font แล้วดูที่บรรทัดตรงที่เขียนว่า<FontName> <FontName>ชื่อFont</FontName> เช่น <FontName>AngsanaUPC</FontName> • จากนั้น ให้ดู บรรทัด <Size>ขนาด</Size> แก้ขนาดตามต้องการ
การใช้ SpriteFont ในXNA • สร้างตัวแปร SpriteFont ไว้ใน Class Game1 ดังนี้ private SpriteFont font; • ให้ใส่ Code ลงใน Method LoadContent font = Content.Load<SpriteFont>(@"AngsanaUPC14");
การใช้ภาษาไทยใน XNA • หากต้องการใช้ภาษาไทยให้เพิ่มข้อความในกรอบเหล่านี้ลงไปในไฟล์ของ SpriteFont เพื่อเป็นการเพิ่มช่วงของภาษาไทยลงไป <CharacterRegions> <CharacterRegion> <Start> </Start> <End>~</End> </CharacterRegion> </CharacterRegions> <CharacterRegion> <Start>฀</Start> <End>๿</End> </CharacterRegion>
Ex3: การวาด Font • ให้ทำการสร้างโปรเจค เพื่อวาดตัวหนังสือขึ้นมาเป็นคำต่างๆ ดังต่อไปนี้ “Game Design”, “Game Development”, “Graphic Design”, “Technical Design”, “Game Asset”, “Asset List” • โดยให้มีการใช้สีแบบต่างๆ โดยการใช้คำสั่ง Random ซึ่งมีตัวอย่างให้ในหน้าถัดไป และ ให้มีการ random ตำแหน่งของตัวหนังสือหลายๆ แบบด้วย และยังต้องหันองศาแบบ randomด้วยเช่นกัน
การสุ่มหรือ Random • ให้ประกาศตัวแปรแบบ Random ขึ้นมา ใน Class โดยมีรูปแบบดังนี้ Random <ชื่อตัวแปร>; เช่น Random random; • ให้จัดการ new Random(); ที่ Initialize() หรือที่ Construtor เช่น random = new Random(); • ส่วนวิธีใช้ inta= random.Next(<MaxValue>); • เช่น inta= random.Next(9); จะมีค่าสูงสุด แค่ 0-8
Lab4: การวาด Font • ให้คิดหาวิธีทำการวาดตัวหนังสือให้ได้ดังภาพต่อไปนี้
Game Performance SuphotSawattiwong tohpus@hotmail.com
Performance • ประสิทธิภาพในการทำงาน • เราจะรู้ได้อย่างไรว่าเกมที่เราทำมีประสิทธิภาพที่ดี • เกมมี graphic ที่สวยงาม ? • ใช้เนื้อที่น้อย ? • เกมเล่นแล้วภาพกระตุก • ใช้ Memory น้อย? • เกมเล่นแล้วสนุกสุดยอด ? • โหลดเกม โหลดฉากได้เร็ว เป็นเรื่องคุณภาพ เป็นเรื่องประสิทธิภาพ เป็นเรื่องประสิทธิภาพ เป็นเรื่องประสิทธิภาพ เป็นเรื่องคุณภาพ เป็นเรื่องประสิทธิภาพ
Measurement • คือการวัดค่าประสิทธิภาพต่างๆ • ในเกมเราวัดได้จาก..... • ความเร็วการวาดใน 1 หน้าจอ • จำนวนหน้าจอที่ทำการวาดใน 1 วินาที • Running Time • การใช้งาน Memory • จำนวนความจุของ HDDที่ใช้ในเกม • LOD (Lines of Code) • อื่นๆ
Benchmark • เป็นกระบวนการวัดและเปรียบเทียบการทำงานในเกม กับเกมหรือกลุ่มตัวอย่างอื่นๆ เพื่อนำผลของการเปรียบเทียบมาใช้ในการปรับปรุงประสิทธิภาพในเกม • ตัวอย่างเช่น • เกมที่ทำ เปรียบเทียบกับเครื่องคอมพิวเตอร์ที่ spec ต่างกันความเร็วการวาดเท่ากันหรือไม่ • เกมที่เราทำ ในเครื่องspec ต่ำ สามารถเล่นเกมเราในความเร็วที่เรากำหนดได้หรือไม่
Frames Per Second(fps) • Frames Per Second คือจำนวนภาพที่วาดต่อ 1 วินาที • การวัดค่าจาก FPS นั้นสามารถวัดอะไรได้บ้าง • วัดความเร็วในการวาดภาพใน 1 วินาที โดยเกมโดยทั่วไป หากเป็นเกม 2 มิติ FPS ควรจะวิ่งอยู่ที่ 60 FPS • สามารถรู้ได้ว่าในหน้าจอในแต่ละเหตุการณ์กินประสิทธภาพเครื่องต่างกันมากน้อยเพียงใด • สาเหตุการกระตุกเกิดจากการวาด หรือการคำนวณจากจุดอื่นๆ • เป็นต้น โดย FPS นั้นสามารถดูตัวอย่างการเขียนได้ที่ Ex4_FPSTest
Algorithm ในการคำนวณ FPS • ทำการวัดช่วงเวลาในตอนเข้าทำงาน (elapsed) ในส่วนของ Draw Method • ให้ทำการเพิ่มค่าจำนวนภาพ(framecount) ทุกๆ ครั้งที่มีการวาด หรือการใช้ Draw Method • ทำการบวกช่วงเวลาที่ได้ (elapsed) เข้าไปในเวลาในการเปรียบเทียบครั้งล่าสุด (timeSinceLastUpdate) • นำระยะเวลาในการเปรียบเทียบครั้งล่าสุด (timeSinceLastUpdate) มาทำการเปรียบเทียบกับเวลาในเปรียบเทียบ (updateInterval) หรือ 1 วินาที หากเวลาในการเปรียบเทียบครั้งล่าสุดมากกว่าให้กระทำต่อในขั้นที่ 5 หากน้อยกว่าให้ทำการวาดภาพตามปกติใน Draw Method
Algorithm ในการคำนวณ FPS (ต่อ) • นำค่าที่ได้มาทำการคำนวณ FPS ดังสูตรต่อไปนี้ fps = framecount / timeSinceLastUpdate • ทำการreset ค่าจำนวนภาพ (framecount) ให้มีค่าเป็น 0 เพื่อเริ่มนับใหม่ • ทำการ reset ค่าเวลาในการเปรียบเทียบครั้งล่าสุด (timeSinceLastUpdate) โดยการนำเวลาที่ใช้เปรียบเทียบ (updateInterval) ลบด้วยเวลาในการเปรียบเทียบครั้งล่าสุด
คำสั่งที่ช่วยในการคิด FPS ใน XNA • graphics.SynchronizeWithVerticalRetrace = true หรือ false • ยอมให้มีการ Sync Draw Method กับการทำ Vertical Retrace ในกระบวนการ refresh rate ของ Monitor หรือไม่ • IsFixedTimeStep = true หรือ false • ยอมให้มีการfixed rate ให้อยู่ที่ 60 fps หรือ ทำให้ fps เป็นอิสระ • gameTime.ElapsedRealTimeเป็น ช่วงเวลาของการ Draw Method • gameTime.ElapsedGameTimeเป็น ช่วงเวลาของการ UpdateMethod