在前文(圓我一個游戲夢,XNA版超級瑪麗)中提到本人最近因學習WP開發時,因需要學習XNA,遂產生了嘗試開發一個小時候玩過無數遍的游戲"超級瑪麗"的想法.
這兩天終於完成了游戲的雛形.從本文開始,我將一步步分享開發的歷程.由於我沒有系統的學習過游戲開發,所以文章中提到的內容也許並不是游戲開發正規的做法,但如果您從未接觸過游戲開發,並對此感興趣,我想我的文章還是能給你帶來幫助的.
准備工作
在開始之前,你需要一些必備的開發工具:VS和XNA.以下是本文對應的開發環境
- VS2010
- Microsoft 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<Texture2D>(@"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不管左移還是右移,身體都是朝右邊的,往左移動時應該面朝左,這個不難處理,圖片已經有了,有興趣的可以自己試試。
結束
第一篇就先介紹到這里,我們的超級瑪麗還遠遠沒有完成,剩下的以后慢慢來。希望對大家有幫助。
下雪天的寫個伯克不容易,給個好評阿,親.....