分享我的XNA版超級瑪麗(1)


  在前文(圓我一個游戲夢,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不管左移還是右移,身體都是朝右邊的,往左移動時應該面朝左,這個不難處理,圖片已經有了,有興趣的可以自己試試。


結束

第一篇就先介紹到這里,我們的超級瑪麗還遠遠沒有完成,剩下的以后慢慢來。希望對大家有幫助。

下雪天的寫個伯克不容易,給個好評阿,親.....

源碼:http://files.cnblogs.com/xxfss2/SuperMario1.rar


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM