分享我的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不管左移还是右移,身体都是朝右边的,往左移动时应该面朝左,这个不难处理,图片已经有了,有兴趣的可以自己试试。


结束

第一篇就先介绍到这里,我们的超级玛丽还远远没有完成,剩下的以后慢慢来。希望对大家有帮助。

下雪天的写个伯克不容易,给个好评阿,亲.....

源码:https://files.cnblogs.com/xxfss2/SuperMario1.rar

posted @ 2013-01-03 18:05  xxfss2  阅读(4549)  评论(16编辑  收藏  举报