天天看點

XNA超級瑪麗

準備工作  在開始之前,你需要一些必備的開發工具:VS和XNA.以下是本文對應的開發環境VS2010Microsoft XNA Game Studio 4.0  VS相信大家都有,至于版本,以下是各個VS對應的XNA版本,如果你不是用的VS2010,那麼你可以下載下傳對應的XNA版本.  XNA Game Studio 2.0(VS2005)  XNA Game Studio 3.0(VS2008)  XNA Game Studio 3.1(VS2008)  XNA Game Studio 4.0(VS2010)  下載下傳連接配接就不貼了,谷哥一下就出來了,我是安裝WP7.1時順帶給我裝上的.Hello Mario  準備工作完成,可以正式開始我們的瑪麗開發曆程了.  打開VS,建立一個項目,選擇C#-XNA Game Studio 中的Windows Game(4.0)模闆,項目名稱為SuperMario,如下圖,點确定這時VS會為我們生成一個名為SuperMario的解決方案,解決方案下面有兩個項目,一個是名為SuperMario的主項目,另一個是名為SuperMarioContent的資源項目.SuperMarioContent項目是專門用來存放一些遊戲資源的,比如圖檔,聲音,地圖什麼的.解決方案如下圖打開Game1.cs,這是我們的主遊戲檔案,類似于建立一個Winform項目時預設建立的Form1.cs,同樣,它的加載由Program.cs完成.我們看到,它有5個重寫的方法,前面三個我們看名字也能猜到大概它們的功能.後面兩個才是我們關注的重點.這裡我簡單介紹下,我想大家肯定知道,電影是怎麼形成的:一張張靜止的圖檔不斷的切換造成視覺上動畫.那麼遊戲其實是一樣的,差別就在電影是已經拍好的圖檔一張張切換,而遊戲則是根據玩家的控制,畫出相應的靜止圖檔,然後不停的切換,形成動畫,也就是說遊戲比電影多了一個畫的步驟,是以玩遊戲比看電影對電腦的配置要求高,因為做的事多了.Game1.cs中的Draw方法就是負責畫畫的.而Update則是根據玩家的輸入和時間的流動更新遊戲中的元素.當遊戲運作時,Update和Draw方法會不停的輪流運作,即時你沒有為遊戲添加任何功能.比如你現在按F5運作時,你看到的是一張靜止的藍色背景視窗,但實際上Update和Draw方法會每秒執行60次.  接下來讓我們的瑪麗出現在遊戲畫面中.在SuperMarioContent項目中添加一個檔案夾,名稱為Image,在該檔案夾種"添加現有項",添加這張圖檔,這是mario的素材圖檔(有點小,大家湊和着用吧.實在找不到更好的了).在Game1.cs中輸入如下代碼 1 Texture2D _marioText; 2 protected override void LoadContent() 3 { 4 spriteBatch = new SpriteBatch(GraphicsDevice); 5 6 _marioText = this.Content.Load(@"Image/mario"); 7 } 8 protected override void Draw(GameTime gameTime) 9 {10 GraphicsDevice.Clear(Color.CornflowerBlue);11 spriteBatch.Begin();12 spriteBatch.Draw(_marioText, new Vector2(100, 100), new Rectangle(0, 0, 16, 16), Color.White, 0, Vector2.Zero, 1.0f, SpriteEffects.None, 0);13 spriteBatch.End();14 base.Draw(gameTime);15 }我們在LoadContent中載入了一張圖檔,然後在Draw方法中,繪制它,繪制的位置是坐标(x:100,y:100),XNA中預設的坐标原點是左上角.繪制時,并有沒有繪制整個圖檔,而是一個小塊,這個小塊在圖檔中的位置是(x:0,y:0)長寬為16.按F5運作.Mario已經出現在遊戲的畫面中了...跑吧 Mario一動不動的Mario怎麼去救公主呢,我們先來解決Mario跑步的問題.既然Mario能移動,說明他的位置是會變的,為它的位置申明一個變量,然後在Update方法中更新他的位置.代碼現在如下 Texture2D _marioText; Vector2 _marioPosition = new Vector2(100, 100); protected override void Update(GameTime gameTime) { if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed) this.Exit(); _marioPosition.X++; base.Update(gameTime); } protected override void Draw(GameTime gameTime) { GraphicsDevice.Clear(Color.CornflowerBlue); spriteBatch.Begin(); spriteBatch.Draw(_marioText, _marioPosition, new Rectangle(0, 0, 16, 16), Color.White, 0, Vector2.Zero, 1.0f, SpriteEffects.None, 0); spriteBatch.End(); base.Draw(gameTime); }按F5運作,怎麼樣,我們的Mario已經會"移動"了吧?不過現在的移動有點像鬼一樣在飄,而且是自動的,不受我們的控制.我們先給他加上控制,一般遊戲都是用"A" "D" 鍵來移動的,一個左移,一個右移.修改Update函數 1 protected override void Update(GameTime gameTime) 2 { 3 if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed) 4 this.Exit(); 5 KeyboardState keyState = Keyboard.GetState(); 6 if (keyState.IsKeyDown(Keys.A)) 7 { 8 _marioPosition.X--; 9 }10 if (keyState.IsKeyDown(Keys.D))11 {12 _marioPosition.X++;13 }14 15 base.Update(gameTime);16 }代碼很好了解,我就不解釋了....現在按F5運作,Mario已經成為我們能控制的遊戲角色了.但Mario還是像鬼一樣在飄,是時候讓它的腳動起來了。剛才提到過,所謂的動畫,就是不斷地切換靜态的圖檔,為了讓我們的Mario動起來,我們讓Mairo在移動的時候不停的切換mario.png圖檔中的第二個和第三個小瑪麗圖檔。這裡我們給圖檔的所有小圖檔的位置編号,從0開始,那麼跑步應該用1号和2号圖檔。先看代碼 int _frmStartIndex=0; int _frmEndIndex = 0; int _frmIndex = 0;//目前畫的圖塊的索引 int _frmChangeTime = 100;//多少毫秒換一次圖檔 int _frmCurrentTime = 0;//距離上次換圖檔過了多少毫秒 protected override void Update(GameTime gameTime) { if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed) this.Exit(); KeyboardState keyState = Keyboard.GetState(); if (keyState.IsKeyDown(Keys.A)) { _marioPosition.X--; _frmStartIndex = 1; _frmEndIndex = 2; } if (keyState.IsKeyDown(Keys.D)) { _marioPosition.X++; _frmStartIndex = 1; _frmEndIndex = 2; } if (keyState.GetPressedKeys().Count() == 0) { _frmStartIndex = 0; _frmEndIndex = 0; } _frmCurrentTime += gameTime.ElapsedGameTime.Milliseconds; if (_frmCurrentTime > _frmChangeTime) { _frmCurrentTime = 0; _frmIndex++; if (_frmIndex > _frmEndIndex) _frmIndex = _frmStartIndex; } base.Update(gameTime); } protected override void Draw(GameTime gameTime) { GraphicsDevice.Clear(Color.CornflowerBlue); spriteBatch.Begin(); spriteBatch.Draw(_marioText, _marioPosition, new Rectangle(_frmIndex * 16, 0, 16, 16), Color.White, 0, Vector2.Zero, 1.0f, SpriteEffects.None, 0); spriteBatch.End(); base.Draw(gameTime); }請注意Draw函數的第二個參數有一些小的更改,在Update函數中,我們通過判斷按鍵情況選擇畫圖時應該選擇的圖檔塊的區域,Mario不動時圖檔塊的索引範圍是0-0,移動時是1-2,并且定義了一個切換圖檔的間隔時間變量_frmChangeTime,在Update函數中不停的累積,當超過100毫秒時,換下一張圖檔。如果沒有這個間隔時間變量,那麼每次Update執行都會換圖檔,那我們的Mario跑起來會瘋了一樣手舞足蹈。按F5運作,Mario移動時會動了吧,我想一定有人會說“為什麼隻有手會動,腳不動”,這純粹是因為我找不到瑪麗移動時應該用哪些圖,不用懷疑現在的代碼,如果你能找到正确的圖檔,就能讓Mario正确的手腳并用跑起來。  處理加速    如果你玩過Mario這個遊戲,你一定知道,Mario移動時是有個加速的過程的,而不是一按下跑步鍵就按固定的速度移動。其實這很容易解決,學過中學實體的我們都知道,加速移動嘛,不就是給個加速度然後運動的時候不停的增加速度。這裡我們隻要在遊戲中通過實體知識模拟真實的運動情況就行了。看代碼float _runAcceleration=0.01F;//跑步加速度 float _runResistance = 0.005F;//... int MAXspeedR = 3;//右移最大速度 int MAXspeedL = -3;//左移最大速度 float _speed = 0;//目前速度 protected override void Update(GameTime gameTime) { if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed) this.Exit(); KeyboardState keyState = Keyboard.GetState(); int frmTime=gameTime.ElapsedGameTime.Milliseconds; if (keyState.IsKeyDown(Keys.A)) { _speed = _speed < MAXspeedL ? MAXspeedL : _speed - _runAcceleration * frmTime; } if (keyState.IsKeyDown(Keys.D)) { _speed = _speed > MAXspeedR ? MAXspeedR : _speed + _runAcceleration * frmTime; } if (keyState.GetPressedKeys().Count() == 0) { if (_speed > 0) { _speed -= _runResistance * frmTime; if (_speed < 0) _speed = 0; } if (_speed < 0) { _speed += _runResistance * frmTime; if (_speed >0) _speed = 0; } } if (_speed == 0) { _frmStartIndex = 0; _frmEndIndex = 0; } else { _frmStartIndex = 1; _frmEndIndex = 2; } this._marioPosition.X += _speed; _frmCurrentTime += frmTime; if (_frmCurrentTime > _frmChangeTime) { _frmCurrentTime = 0; _frmIndex++; if (_frmIndex > _frmEndIndex) _frmIndex = _frmStartIndex; } base.Update(gameTime); }Update函數現在可以分為2部分,第一部分根據使用者的鍵盤輸入處理Mario速度,用時間乘以加速度得到速度,當使用者不再按任何鍵時,處理減速。第二部分為根據Mario的速度來處理圖檔索引範圍,現在當Mario的速度不為0時,顯示跑步圖檔。這裡this._marioPosition.X += _speed;何解呢?因為我們算出的速度是這一幀内的速度,可以了解為機關速度,距離等于速度乘以時間,時間為1,相當于距離等于速度。最後我們按F5運作,怎麼樣,此時的Mario已經有點感覺了吧。  目前Mario不管左移還是右移,身體都是朝右邊的,往左移動時應該面朝左,這個不難處理,圖檔已經有了,有興趣的可以自己試試。