zoukankan      html  css  js  c++  java
  • 分享我的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

  • 相关阅读:
    安装jar包到本地仓库和远程仓库
    服务之间的资源权限校验
    函数指针
    malloc分配内存
    cuda_vs_报错无法解析的外部错误
    c语言读写文件
    C++使用using namespace std报错分析与解决方案
    MPI环境配置
    c语言学习
    openMP
  • 原文地址:https://www.cnblogs.com/xxfss2/p/2843192.html
Copyright © 2011-2022 走看看