FullScreen Mode : Switch (Part 2)

posted on 14 Oct 2008 16:28 by ninetales in XNA

จากตอนที่แล้ว เราพบกับปัญหาเนื่องจาก
เราต้องการ สั่งให้ทำงานเพียงครั้งเดียวเมื่อมีการกดปุ่ม
แต่เกมขยันเช็คทุก loop ว่าเรา "กำลังกดอยู่" (ตอนนี้กด)
เพราะฉะนั้น...เราจะต้องเปลี่ยนไปเช็คว่า
"พึ่งจะเริ่มกด" (ก่อนหน้านี้ไม่กด แต่ตอนนี้กด)
หรือ "กดเสร็จแล้ว" (ก่อนหน้านี้กดอยู่ แต่ตอนนี้เลิกกดแล้ว)
ถ้าก่อนหน้านี้กดอยู่ แล้วตอนนี้ก็กดอยู่ ไม่ทำ!

ให้ประกาศในส่วนของ Globalดังนี้

        KeyboardState currentKeyBoard;
        KeyboardState previousKeyBoard;
เราจะใช้  KeyboardState2ตัว ในการเช็ค การกดในรอบนี้ และรอบก่อนหน้านี้

 

         protected override void Update(GameTime gameTime)
        {
            //GetState เพื่อเช็คปุ่มที่กำลังกดอยู่
           currentKeyBoard = Keyboard.GetState();      

            if (
currentKeyBoard .IsKeyDown(Keys.Escape))
            {
                Exit();
            }

            //ถ้ารอบนี้กดF10 และ รอบก่อนหน้านี้ไม่ได้กด
            if (currentKeyBoard.IsKeyDown(Keys.F10) && !previousKeyBoard.IsKeyDown(Keys.F10))
            {
                graphics.ToggleFullScreen();
            }

            //GetState การกดของรอบนี้ไว้ท้ายสุด เพื่อนำไปเช็คเป็นการกดของรอบที่แล้ว ในloopหน้า
          
currentKeyBoard = Keyboard.GetState();      


            base.Update(gameTime);
        }

 เท่านี้ ลองปักนิ้วลงไปบนปุ่ม F10 ดู โปรแกรมก็จะทำการ Toggle FulScreen 1ครั้ง แม้จะกดค้างไว้ก็ตาม

ลองอีกแบบหนึ่งบ้าง เปลี่ยนการเช็คปุ่ม F10 เป็น

             if (!currentKeyBoard.IsKeyDown(Keys.F10) && previousKeyBoard.IsKeyDown(Keys.F10))

แค่สลับเครื่องหมาย ! ให้เป็น  ก่อนหน้านี้กด แต่ตอนนี้ไม่กด
ลองใหม่ เสียบนิ้วลงไปบน F10ค้างไว้.... นิ่ง ไม่เกิดอะไรขึ้น
ดึงนิ้วออก! Toggle FulScreen ทันที!

edit @ 14 Oct 2008 17:18:28 by 『Ninetales』

FullScreen Mode : Switch (Part 1)

posted on 12 Oct 2008 02:02 by ninetales in XNA

FullScreen Mode Switching หรือ Toggle FullScreen
คำสั่งจริงๆเพียงแค่ บรรทัดเดียวอีกแล้ว

graphics.ToggleFullScreen();

ไม่ว่าจะอยู่ส่วนใหนของเกม
เจอคำสั่งนี้เข้าไป จาก FullScreen จะกลายเป็น Windows
จาก Windows จะกลายเป็น FullScreen

ทีนี้ มาลองยัด Code ใส่เข้าไปในโปรแกรมกันดีกว่า
ตรง Update ผมให้กด F10 เป็น ToggleFullScreen ละกันครับ

        protected override void Update(GameTime gameTime)
        {

            if (Keyboard.GetState().IsKeyDown(Keys.Escape))
            {
                Exit();
            }

            if (Keyboard.GetState().IsKeyDown(Keys.F10))
            {
                graphics.ToggleFullScreen();
            }


            base.Update(gameTime);
        }

ทีนี้กด F5 Run ดู แล้วลองกด F10 ***อย่ากดแช่นานระวังแฮงค์***
สำหรับบางเครื่อง กด(ไวๆ) แล้วปล่อย อาจจะดูไม่มีปัญหาอะไร
แต่บางเครื่องจะพบว่า มัน "วูบวาบ"

Why?
เพราะว่า XNA ทำการเช็คทุกรอบนั่นเอง ว่า เราได้ทำการ "กดอยู่" รึเปล่า
เพราะฉะนั้นในการกด 1 ครั้งของเรา เกมก็อาจจะ run ไปหลาย loop แล้ว
เครื่องจึงอาจจะพยายามทำการ ToggleFullScreen หลายครั้งใน1 วินาที!!!

Why? ทำไม Exit() ทำได้? ทั้งๆที่เขียน code คล้ายๆกัน
ก็ ออกแล้วมันออกเลยนี่ครับ
กดไปแล้ว มันไม่กลับมาเช็คว่า เราจะออกอีกหรือเปล่า เพราะเกมเรา จบ แล้ว...

...ต่อตอนต่อไป

edit @ 13 Oct 2008 17:19:47 by 『Ninetales』

FullScreen Mode : Set

posted on 12 Oct 2008 01:36 by ninetales in XNA

 สั้นๆ เพียงบรรทัดเดียว

graphics.IsFullScreen = true;

 set ให้เป็น true เมื่อต้องการให้ FullScreen (FullScreen Mode)
 set ให้เป็น false เมื่อไม่ต้องการให้ FullScreen (Window Mode)

เรื่องต่อไปจะพูดถึงการทำการ switch ระหว่าง Windows Mode และ FullScreen Mode

edit @ 13 Oct 2008 16:41:01 by 『Ninetales』

Screen Resolution

posted on 12 Oct 2008 00:37 by ninetales in XNA

การปรับขนาดหน้าจอของเกม
คำสั่งที่จำเป็น อีกชุดหนึ่ง ในการทำเกม

GraphicsDeviceManager.PreferredBackBufferWidth และ
GraphicsDeviceManager.PreferredBackBufferHeight

แต่เนื่องจากในส่วนของ Global นั้น XNA ได้ประกาศ
GraphicsDeviceManager graphics;

และ
graphics = new GraphicsDeviceManager(this);
ในส่วนของ Constructor มาแล้ว

ดังนั้น Code จึงเหลือ แค่
            graphics.PreferredBackBufferWidth
            graphics.PreferredBackBufferHeigh

Example :

  graphics.PreferredBackBufferWidth = 320;
  graphics.PreferredBackBufferHeight = 240;

*หากประกาศใน Initialize() หรือ Update() จะไม่มีการเปลี่ยนแปลงค่าใดๆจนกว่าจะเรียกคำสั่ง

graphics.ApplyChanges();

  แต่ถ้าให้ประกาศใน Constructor ไม่ต้องใช้ ApplyChanges()

edit @ 13 Oct 2008 16:41:29 by 『Ninetales』

Keyboard : ย่อ Code ให้สั้นลง

posted on 11 Oct 2008 23:29 by ninetales in XNA

จากเดิมที่เราต้องเขียนซะยืดยาวว่า

            if (Keyboard.GetState().IsKeyDown(Keys.Escape))

 ซึ่งอีกเดี๋ยวเราจะต้องเขียนคล้ายๆแบบนี้อีกหลายบรรทัด
เพราะฉะนั้นเขียนให้สั้นจึงดีที่สุด ยิ่งเขียนสั้นยิ่งเอาเวลาไปคิดเรื่องตัวเกมได้มาก

 ดังนั้นเราจะย่อ Keyboard.GetState() เหลือแค่ keyboard
(จำไว้ว่า ตัวแปรในภาษา C# ตัวเล็กใหญ่มีผลถือว่าเป็นคนละตัวกัน)

ดึง Keyboard.GetState(); ออกมา
เอา keyboard ยัดลงไปแทน
ก็จะกลายเป็น

 keyboard = Keyboard.GetState();
if (keyboard.IsKeyDown(Keys.Escape))

สั้นลงแล้ว แต่ยังใช้ไม่ได้ เพราะ ต้องมีการประกาศทุกๆตัวแปรที่ใช้ และ  keyboard จัดเป็นตัวแปรตัวหนึ่ง
ดังนั้น keyboard ต้องเป็นตัวแปร "อะไรสักอย่าง" ที่มารับค่าของ Keyboard.GetState(); ได้

???  keyboard = Keyboard.GetState();
if (keyboard.IsKeyDown(Keys.Escape))

ใน XNA นั้น Keyboard.GetState(); มีค่าเป็น object ประเภท KeyboardState
Code จึงต้องเขียนเป็น

        protected override void Update(GameTime gameTime)
        {

            KeyboardState keyboard = Keyboard.GetState();
            if (keyboard.IsKeyDown(Keys.Escape))
            {

                Exit();
            }

            base.Update(gameTime);
         }

เพียงแค่นี้ ก็ run ได้ ใช้งานได้แล้ว
ไม่ต้องมาเขียน Keyboard.GetState() ทุกบรรทัดที่เช็ค keyboard
ถึงแม้จะอยู่ใน loop ของ Update แต่สามารถประกาศตัวแปรไว้ได้ ไม่เป็นปัญหา
เพราะ C# อนุญาตให้ประกาศทับได้
แต่เอาออกไปประกาศ รอบเดียวดีกว่าใหม?
งั้นเราแยก การประกาศ ออกมาดีกว่า

        protected override void Update(GameTime gameTime)
        {
            KeyboardState keyboard;
            keyboard = Keyboard.GetState();
            if (keyboard.IsKeyDown(Keys.Escape))
            {

                Exit();
            }

            base.Update(gameTime); 

         }

Keyboard.GetState();จำเป็นต้องมีการUpdateทุกรอบ เพราะต้องคอยเช็ค Keyboard ตลอดเวลา
จึงต้องอยู่ใน Update()

จากนั้น ยก  KeyboardState keyboard; ออกไปไว้ข้างนอก ตรง Global (เหนื่อ Game1( ) )
ก็เป็นอันเสร็จสมบูรณ์

edit @ 13 Oct 2008 16:41:43 by 『Ninetales』

『Ninetales』 View my profile