2010年11月24日

XNA 程式設計入門

XNA遊戲迴圈

基本上就是一個迴圈不斷執行,直到使用者結束遊戲。

1.啟始化並載入資源
   1.1 Initialize()
   1.2 LoadGraphicsContent()
2.迴圈開始
   2.1. Update()  //處理遊戲邏輯
   2.2. Draw()     //處理繪圖
3.迴圈結束
4.釋放資源 UnloadGraphicsContent()


遊戲迴圈的計時(Game Loop Timing)

計時方式有兩種,固定(預設)和變動間隔。計時模式會影響Update呼叫的頻率。
固定間隔
設定Game.IsFixedTimeStep為True,此方式會在指定的時間間隔TargetElapsedTime 呼叫Update。 一個新的XNA project會預設為固定間隔TargetElapsedTime 1/60秒。呼叫完Update之後若還沒到下次Update時,遊戲物件呼叫Draw。呼叫完Draw之後若時間還沒到下次Update時,遊戲閒置等待,直到呼叫Update的時間來到。
若Update 花了太久的時間,遊戲物件會設立IsRunningSlowly 旗標為True,然後再次呼叫Update,忽略中間的呼叫Draw。相當於遊戲物件丟掉中間的畫面,來追上遊戲更新速度。這樣能保證Update會被如預期的次數呼叫,當遊戲速度追上時。當你想偵測是否更新速度過慢時,我們可以在Update時檢查 IsRunningSlowly 旗標,適度地調整Update程序。
變動間隔
設定Game.IsFixedTimeStep為False,此方式會忽略TargetElapsedTime設定,連續呼叫U迴圈中的pdate和Draw。
動畫需要精確的計時,不能忽快忽慢。使用固定間隔可以讓Update會在TargetElapsedTime到時呼叫一次,而變動間隔則需要調整遊戲的更新速度。因為是連續呼叫Update和Draw,所以兩個畫面間的間隔可能是任意時間長度。 兩次Update呼叫間的時間間隔,存放在Update 函數的gameTime 參數。 所以當使用變動間隔時,我們必須將移動距離以速度比率表示之。然後乘以此gameTime來得到應該的移動距離。如此一來才能保持移動的平順,不會忽快忽慢。

圖精靈(Sprites)簡介
直接繪製在顯示目的區的二維點陣圖形(Bitmap)。圖精靈在螢幕上用座標來定位。螢幕的寬和高和back buffer一樣大。X-軸表示螢幕的寬,Y-軸表示螢幕的高。Y-軸從螢幕上方往下遞增,而X-軸從螢幕左方往右方遞增。
想要繪製一個圖精靈,首先產生一個SpriteBatch物件,呼叫Begin初始化,然後對每一個圖精靈呼叫Draw。圖精靈的點陣資料從一個Texture2D物件而來。此物件可包含透明度(alpha channel)資訊,使得部分物體透明或半透明。你可以用Draw來渲染,旋轉或縮放圖精靈,也可以只繪製某部分在螢幕上。在對一個圖精靈呼叫Draw之後,在呼叫Present之前,須先呼叫End結束繪製。


定義一個myGame遊戲物件,覆寫 Update 負責遊戲邏輯部分、Draw 負責繪製每次的圖形(frame) 和 Initialize LoadContent 啟始部分,並定義圖精靈批次作業和圖形裝置。

public class myGame : Microsoft.Xna.Framework.Game {
    GraphicsDeviceManager graphics;  //圖形裝置

    SpriteBatch spriteBatch;                 //圖精靈批次作業
    private Texture2D SpriteTexture;    //

    public Game1(){
              graphics = new GraphicsDeviceManager(this);  //啟始一個圖形裝置
              Content.RootDirectory = "Content";
    }
    protected override void Initialize(){ base.Initialize();}

   // 每一個遊戲物件會呼叫LoadContent一次,此處用來載入你的所有內容
    protected override void LoadContent(){
             spriteBatch = new SpriteBatch(GraphicsDevice);   //啟始一個圖精靈批次作業
             SpriteTexture = Content.Load("ship");  //載入圖精靈的紋理資訊
             TitleSafe = GetTitleSafeArea(.8f);
    }

    protected override void Update(GameTime gameTime){
    // Allows the default game to exit on Xbox 360 and Windows.
             if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
                 this.Exit();
             if (Keyboard.GetState().IsKeyDown(Keys.Escape))
                 this.Exit();
             base.Update(gameTime);
    }

    protected override void Draw(GameTime gameTime){
             graphics.GraphicsDevice.Clear(Color.CornflowerBlue);
             spriteBatch.Begin();
             Vector2 pos = new Vector2(TitleSafe.Left, TitleSafe.Top); //此圖精靈的位置
             spriteBatch.Draw(SpriteTexture, pos, Color.White); // 白色表不改變原來紋理
             spriteBatch.End();
             base.Draw(gameTime);
    }
}

圖精靈的原點(Origin)
當你繪製圖精靈時,原點是個重要的概念。原點預設為圖精靈的左上方角落 ,記作(0,0)。Draw 會在你指定的螢幕位置繪製圖精靈的原點。例如,如果你在位置(400,200)繪製一個沒有指定原點的 50×50像素的圖精靈時,此圖精靈的左上角會在(400,200)。
當旋轉圖精靈時,是以原點為中心。

圖精靈深度(Depth)
深度為0到1之間的浮點數,深度0表示最上面,深度1被覆蓋在最底下。

圖精靈取樣(Sampling)
圖精靈基本上是一個 Texture2D 物件即點陣圖。呼叫 Draw 來繪製整個或部分的圖形。使用來源矩形(sourceRectangle) 參數來指定所要繪製的部分。

圖精靈縮放(Scaling)
Draw 提供3個縮放方式。
1.使用一個一致的縮放參數:一個浮點數同時乘以圖精靈的X和Y軸,維持原來的長寬比。
2.使用一個非一致的縮放參數 :一個二維向量Vector2結構,可以將X和Y軸以不同大小縮放。
3.使用一個來源矩形和目的矩形(destination rectangle)。目的矩形使用螢幕座標,來源矩形使用相對圖精靈原點座標。Draw將來源矩形內對應的畫素,延伸貼滿到目的矩形。

圖精靈變形矩陣(Transformation Matrices)
我們也可以指定一個變形矩陣,讓圖精靈批次作業(SpriteBatch)在繪製前,先套用到每一個圖精靈。變形矩陣包含任何組合的位移、旋轉和縮放矩陣的相乘。
Rotating a Group of Sprites for an example of matrix rotation and
Scaling Sprites Based On Screen Size for an example of matrix scaling.

圖精靈字型(Fonts)
使用SpriteBatchDrawString 繪製文字。此方法接受位置、顏色、旋轉、原點、縮放等參數。額外需要一個 SpriteFont 物件。
See Sprite Font XML Schema Reference for a list of Sprite Font tags.
You can use the content pipeline to determine your character regions automatically. For more information, see How to: Extend the Font Description Processor to Support Additional Characters.

圖精靈批次作業(Sprite Batching)
在一般情形時,SpriteBatch 物件在呼叫End之前不會改變繪圖狀態,稱為延遲模式(Deferred mode)。此時SpriteBatch 儲存每一個Draw 呼叫的資訊,直到呼叫 End 為止。
若你呼叫 Begin 時,指定SpriteSortMode.Immediate,則變成立即模式(Immediate mode)。在立即模式時,每一個呼叫 Draw 會立刻使用目前的裝置設定,繪製圖精靈。此時當你在某一個SpriteBatch物件上呼叫Begin後,在呼叫End 之前,就不能又在其他的 SpriteBatch 物件上呼叫Begin。延遲模式比立即模式慢,但是它可以允許多個SpriteBatch 同時呼叫 BeginDraw ,而不會互相干擾。

沒有留言: