【用C#写游戏-XNA游戏编程】坦克大战(一) 初探XNA

来源:互联网 发布:罗技游戏鼠标推荐 知乎 编辑:程序博客网 时间:2024/05/17 23:49

    从初涉编程到学习C#也一年有余了,从今天开始就借一个《坦克大战》来对自己以前学过的知识进行一次汇总和尝试开始写博客,好了,废话不多说,开篇。


    XNA中的X表示能够在WindowsXbox和合作伙伴之间达到跨平台的强大的软件工具。N表示“下一代(Next-generation)”,A表示“架构(Architecture)”。XNA是基于DirectX的游戏开发环境,是微软对于 Managed DirectX 的修正及扩充版本。


    以上抄自百度百科,XNA现在确实比较少人用,微软貌似也不打算更新了,XNA现在的最高版本依旧还是4.0,但这个没关系,反正用XNA的目的只是为了巩固下自己的基础知识而已,所有用XNA来写在适合不过了,其中原因有几点:

    1.还是依旧熟悉的C#语言 (这完全废话不解释 = =

    2.可以对一个游戏的编写有一个系统的了解,用unity开发估计会简单很多、但不有利于知识的汇总

    3.毕竟下来要写的是我们儿时经常玩的《小坦克大战》,XNA搞2d还是很方便的

 

    如果是单纯想学习游戏开发希望能找份好工作的话就不推荐搞这个了,压根就没人用、工作岗位太少了,当然我的本意也只是为了巩固下知识,和初步了解下看看究竟这个"游戏开发”到底是个什么玩意; (当然游戏开发还是大大推荐Unity,无论是做2d还是3d,这个游戏引擎都是非常方便和好用!


    好,现在开始看看XNA的项目模板都有些什么东西吧! (要安装XNA Game Studio后才能找到XNA的项目模板

    新建一个名为TankeWar的WIndows游戏项目

   


    vs自动帮我们多创建了一个名为"TankeWarContent“的内容项目,这个项目就是专门用来放游戏资源的,例如一些游戏贴图、音乐什么的,现在看下Gmae1.cs里面都有些什么吧。

using System;using System.Collections.Generic;using System.Linq;using Microsoft.Xna.Framework;using Microsoft.Xna.Framework.Audio;using Microsoft.Xna.Framework.Content;using Microsoft.Xna.Framework.GamerServices;using Microsoft.Xna.Framework.Graphics;using Microsoft.Xna.Framework.Input;using Microsoft.Xna.Framework.Media;namespace TankeWar{    /// <summary>    /// 这是游戏的主类型    /// </summary>    public class Game1 : Microsoft.Xna.Framework.Game    {        GraphicsDeviceManager graphics;        SpriteBatch spriteBatch;        public Game1()        {            graphics = new GraphicsDeviceManager(this);            Content.RootDirectory = "Content";        }        /// <summary>        /// 允许游戏在开始运行之前执行其所需的任何初始化。        /// 游戏能够在此时查询任何所需服务并加载任何非图形        /// 相关的内容。调用 base.Initialize 将枚举所有组件        /// 并对其进行初始化。         /// </summary>        protected override void Initialize()        {            // TODO: 在此处添加初始化逻辑            base.Initialize();        }        /// <summary>        /// 对于每个游戏会调用一次 LoadContent,        /// 用于加载所有内容。        /// </summary>        protected override void LoadContent()        {            // 创建新的 SpriteBatch,可将其用于绘制纹理。            spriteBatch = new SpriteBatch(GraphicsDevice);            // TODO: 在此处使用 this.Content 加载游戏内容        }        /// <summary>        /// 对于每个游戏会调用一次 UnloadContent,        /// 用于取消加载所有内容。        /// </summary>        protected override void UnloadContent()        {            // TODO: 在此处取消加载任何非 ContentManager 内容        }        /// <summary>        /// 允许游戏运行逻辑,例如更新全部内容、        /// 检查冲突、收集输入信息以及播放音频。        /// </summary>        /// <param name="gameTime">提供计时值的快照。</param>        protected override void Update(GameTime gameTime)        {            // 允许游戏退出            if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)                this.Exit();            // TODO: 在此处添加更新逻辑            base.Update(gameTime);        }        /// <summary>        /// 当游戏该进行自我绘制时调用此项。        /// </summary>        /// <param name="gameTime">提供计时值的快照。</param>        protected override void Draw(GameTime gameTime)        {            GraphicsDevice.Clear(Color.CornflowerBlue);            // TODO: 在此处添加绘图代码            base.Draw(gameTime);        }    }}

    模板帮咱们生成好的代码已经有很详细的注释了,详细也不用我废话什么了,但它们的生命周期还是要说一下:游戏开始后会先Initialize()方法、然后到LoadContent()方法加载游戏资源、然后就到Update()和Draw()这两个主要的游戏循环,但这两个也有先后顺序的,先Update()后Draw()、最后游戏收到退出指令后执行UnloadContent()释放所有游戏资源;

    好勒,既然对XNA的结构有了大致的了解后,咱就开搞了、先试试让咱们的小坦克在游戏里面动起来!

    既然是坦克大战、没坦克还玩个鸟,咱先到网上搜罗几张坦克大战的游戏贴图回来先,然后把贴图添加到TankeWarContent项目里面,像这样:

   

    好了,现在素材也有了,开始敲代码吧

    先定义一个小坦克的纹理对象:

        GraphicsDeviceManager graphics;        SpriteBatch spriteBatch;        Texture2D TankeTexture2D;   //定义一个小坦克的2D纹理对象        public Game1()        {            graphics = new GraphicsDeviceManager(this);            Content.RootDirectory = "Content";        }

    然后在LoadContent()资源加载方法内把图片给加载到TankeTexture2D对象里面去:

        protected override void LoadContent()        {            // 创建新的 SpriteBatch,可将其用于绘制纹理。            spriteBatch = new SpriteBatch(GraphicsDevice);            TankeTexture2D = Content.Load<Texture2D>("p1tank0");    //加载图片资源            // TODO: 在此处使用 this.Content 加载游戏内容        }

    最后把纹理对象画到屏幕里面:

        protected override void Draw(GameTime gameTime)        {            GraphicsDevice.Clear(Color.CornflowerBlue);            // TODO: 在此处添加绘图代码                        //把小坦克画到游戏屏幕上面            spriteBatch.Begin();            spriteBatch.Draw(TankeTexture2D, Vector2.Zero, Color.White);                spriteBatch.End();            base.Draw(gameTime);        }

    按下F5,不出意外的话应该能看到咱们的小坦克出现在屏幕上了,但这个时候按什么按键小坦克都不会动,没关系,继续写代码:

    在添加多两个变量,一个是坦克的坐标和坦克移动速度:

        GraphicsDeviceManager graphics;        SpriteBatch spriteBatch;        Texture2D TankeTexture2D;   //定义一个小坦克的2D纹理对象        Vector2 TankePos;           //定义一个小坦克的坐标        int MoveSpeed = 5;          //定义小坦克移动的速度,默认值为5        public Game1()        {            graphics = new GraphicsDeviceManager(this);            Content.RootDirectory = "Content";        }

    Update()方法里面也添加检测键盘的状态:

        protected override void Update(GameTime gameTime)        {            // 允许游戏退出            if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)                this.Exit();            if (Keyboard.GetState().IsKeyDown(Keys.W))                TankePos.Y -= MoveSpeed;            if (Keyboard.GetState().IsKeyDown(Keys.S))                TankePos.Y += MoveSpeed;            if (Keyboard.GetState().IsKeyDown(Keys.A))                TankePos.X -= MoveSpeed;            if (Keyboard.GetState().IsKeyDown(Keys.D))                TankePos.X += MoveSpeed;            // TODO: 在此处添加更新逻辑            base.Update(gameTime);        }

   Draw()也改一改,把出现的固定坐标换成TankePos:

        protected override void Draw(GameTime gameTime)        {            GraphicsDevice.Clear(Color.CornflowerBlue);            // TODO: 在此处添加绘图代码                        //把小坦克画到游戏屏幕上面            spriteBatch.Begin();            //spriteBatch.Draw(TankeTexture2D, Vector2.Zero, Color.White);            spriteBatch.Draw(TankeTexture2D, TankePos, Color.White);            spriteBatch.End();            base.Draw(gameTime);        }

    再按下F5,按WSAD,哈哈,小坦克是不是会动啦!!    等等,你TM在逗我!? 不管怎么移动,坦克的炮管为毛都是向上!?

    额....... 其实这个也不难解决的,spriteBatch.Draw()有多个重载,其中就有改变贴图的角度的,但最简单的方法就是有4张贴图、4个纹理对象,按照不同的方向把不同的纹理画到屏幕上就是了;不过这个以后再说吧,今就到这,往后再慢慢写。 (今总算是把这坑给开了 = =!

原创粉丝点击