我的第一個xna程式!

摘要:我的第一個xna程式!

我們先從簡單的2D遊戲開始學起,首先就先來研究如何在畫面上貼圖。

下面是產生新專案後所生出的程式碼,若我們直接按F5編譯程式的話,會跑出一個藍色背景的視窗。

01 namespace WindowsGame1 {
02
03     public class Game1 : Microsoft.Xna.Framework.Game {
04         GraphicsDeviceManager graphics;
05         SpriteBatch spriteBatch;
06
07         public Game1() {
08             graphics = new GraphicsDeviceManager(this);
09             Content.RootDirectory = "Content";
10         }

11
12         protected override void Initialize() {
13             // TODO: Add your initialization logic here
14
15             base.Initialize();
16         }

17
18         protected override void LoadContent() {
19             // Create a new SpriteBatch, which can be used to draw textures.
20             spriteBatch = new SpriteBatch(GraphicsDevice);
21
22             // TODO: use this.Content to load your game content here
23         }

24
25
26         protected override void UnloadContent() {
27             // TODO: Unload any non ContentManager content here
28         }

29
30
31         protected override void Update(GameTime gameTime) {
32             // Allows the game to exit
33             if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
34                 this.Exit();
35
36             // TODO: Add your update logic here
37
38             base.Update(gameTime);
39         }

40
41
42         protected override void Draw(GameTime gameTime) {
43             GraphicsDevice.Clear(Color.CornflowerBlue);
44
45             // TODO: Add your drawing code here
46
47             base.Draw(gameTime);
48         }

49     }

50 }

第7行是建構子,他首先取得繪圖裝置,以後要畫圖的話就是透過此裝置,而xna已經將比較底層的工作都幫你做好了,所以不像以前直接用DX9那樣還要自己註冊。另外第9行是設定Content的目錄位置,原則上我們會把遊戲需要用到的圖形、模型、聲音等資源放在Content目錄內,因此幾乎用不著改他。

接著第12行是遊戲的初始化,非圖形的物件或資料通常在這裡載入,而呼叫base.Initialize()函式會呼叫component的初始化函式,關於component這裡還用不到,以後再說!

第18行就是用來載入圖形或模型等資料的地方,而第26行就是把這些載入的資源釋放掉。

31行和42行可以說是遊戲最重要的兩的函式,Update用來作邏輯處理,像是物體的移動、碰撞、改變狀態、輸入控制等事情都在這裡做,而Draw函式就是負責把圖畫出來。

預設的xna專案會是60FPS的,也就是一秒鐘畫面更新60次,電腦會固定在1/60秒呼叫一次draw和update,若是draw在1/60秒無法處理完成,會優先再度叫用update,讓時間趕上之後再呼叫draw,

這樣畫面會出現延遲,但是不會變成慢動作,一秒鐘該走的距離還是一樣,xna也有可能會自動將fps降到30。但若是update來不及,那就很慘了,雖然不會都不呼叫draw,但是你應該會玩不下去。

介紹完這五個主要的函式後,讓我們是著在畫面貼上我們的圖,首先在Content目錄加入我們想要顯示的圖(如下圖)

 

這裡我加入一個圖形名稱為msd_a01.jpg,基本上我們常用的圖檔格式xna都支援像是jpg、bmp、png。加好圖形後,我們在圖形上按右鍵選擇Properties,會出現下面的屬性選單

第一個選項表示xna會把這張圖編碼成xnb檔,第二個表示不會將jpg圖複製到專案編譯後的目錄內,第三、四個是圖檔的名稱及路徑。

Asset Name是個重點,他表示xna將圖編譯成xnb檔之後的名稱,在LoadContent載入此圖時就要用這個名稱,此名稱在整個專案中不能重複。最後兩個就是編譯的方式,目前不要改他。

將圖案加入專案後,讓我們來看看程式要怎麼寫

01 private Texture2D myImage;
02
03 protected override void LoadContent() {
04     spriteBatch = new SpriteBatch(GraphicsDevice);
05     myImage = Content.Load<Texture2D>("msn_a01");
06 }

07
08 protected override void UnloadContent() {
09     myImage.Dispose(); //釋放物件
10 }

11
12 protected override void Draw(GameTime gameTime) {
13     GraphicsDevice.Clear(Color.CornflowerBlue);
14
15     spriteBatch.Begin();
16     spriteBatch.Draw(myImage, Vector2.Zero, Color.White);
17     spriteBatch.End();
18
19     base.Draw(gameTime);
20 }

在原本的專案中加入第一行的物件,此Texture2D物件是2d的圖形物件,這裡用來存放我們將要載入的圖片。

而在LoadContent 內,第四行是用繪圖裝置產生一個SpriteBatch,這個物件負責一些畫圖的設定、畫法等功能,加入第五行程式碼,Content物件是用來載入我們放在Content目錄下的東西,其Load是一個泛型函式,角括號是要載入的物件型態,我們的圖片是2D的圖,所以用Texture2D。載入後的圖將會設定給myImage。

最後我們在Draw函式中將此圖畫出來,第13行是將繪圖裝置用一種顏色清空,目前的繪圖裝置當然就是只螢幕囉,所以一開始執行專案時,螢幕才會是藍色。

我們要真正繪圖時,必須將SpriteBatch.Draw函式用SpriteBatch.Begin和SpriteBatch.End包起來,他有幾種多載,這裡先用最簡單的,之後在中間的Draw函式將此圖畫出來,第一個參數是要畫的圖,第二個是顯示的位置,是一個二維座標,最後是顏色遮照,不想讓他變色的話就用白的!

下面是執行程式後的畫面

 在電腦螢幕的座標系和一般我們數學教的座標方向有點不一樣,螢幕的座標左上角是(0,0),x軸往右為正,y軸往下為正,一般而言原點都是左上角,我們第二個參數是呼叫Vector2.Zero,他是產生一個(0,0)的向量,所以此圖形會長在畫面的左上角。

你可以改變此向量,例如改成new Vector2(150,100),他就會將圖形畫在距離視窗左上角右邊150像素、往下100像素的地方。

既然如此,我們就知道要如何讓圖形移動了,先在Game1內加上一Vector2 position ,接著在update函式內加上移動的方式

然後將draw函式的位置參數改成position,程式如下:

 

01 Vector2 position = new Vector2();
02 int stepX = 1;
03
04 protected override void Update(GameTime gameTime) {
05
06     if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
07         this.Exit();
08     if (position.X + myImage.Width > Window.ClientBounds.Width || position.X < 0) {
09         stepX *= -1;
10     }

11     position.X += stepX;
12
13     base.Update(gameTime);
14 }

15
16 protected override void Draw(GameTime gameTime) {
17     GraphicsDevice.Clear(Color.CornflowerBlue);
18     spriteBatch.Begin();
19     spriteBatch.Draw(myImage, position, Color.White);
20     spriteBatch.End();
21
22     base.Draw(gameTime);
23 }

此範例會移動圖片,到畫面右邊之後會反彈。

最後是此demo的專案檔!WindowsGame1.rar