项目实战《选老婆》一

根据之前所学的知识:
C#开发跨平台游戏——XNA简介
C#开发跨平台游戏——MONOGAME简介
C#开发跨平台游戏——安装VISUAL STUDIO 2017
C#开发跨平台游戏——VISUAL STUDIO 2017安装XNA
C#开发跨平台游戏——VISUAL STUDIO 2017安装MONOGAME
C#开发跨平台游戏——编写第一个C#游戏
C#开发跨平台游戏——在游戏中使用中文
C#开发跨平台游戏——游戏的全屏窗口及退出
C#开发跨平台游戏——设置游戏的窗口大小及分辨率
C#开发跨平台游戏——在游戏中显示系统默认鼠标及鼠标的基本使用
C#开发跨平台游戏——自定义游戏鼠标光标
C#开发跨平台游戏——游戏中按钮的实现
C#开发跨平台游戏——在游戏中使用背景音乐和按钮音效
C#开发跨平台游戏——游戏中使用多张图片实现动画
今天开始我们来一起做一个小游戏——《选老婆》
首先下载本游戏需要用到的所有素材:SelectWifeContent.zip下载地址:http://www.xnadevelop.com/wp-content/uploads/2020/01/SelectWifeContent.zip
打开Visual Studio 2017,【文件】【新建】【项目】,如下图:

【Visual C#】【Windows Games】,名称输入【SelectWife.XNA】,解决方案名称输入【SelectWife】,框架选择【.NET Framework 4.6】,点击【确定】。如下图:

找到解决方案管理器,选中Game1.cs,右键【重命名】为【GameMain.cs】。如下图:

点击【是】,如下图:

打开GameMain.cs文件,找到【SpriteBatch spriteBatch;】在下方定义游戏的宽度和高度:

找到构造函数,在【Content.RootDirectory = “Content”;】下面输入:

将游戏窗口设置为480×800的尺寸。
游戏场景
选中【SelectWife.XNA】项目,点击鼠标右键【添加】【新建项】【类】

名称输入【GameScence.cs】,点击【添加】。如下图:

打开GameScence.cs文件,将文件的内容修改为:

定义四个基本游戏场景。
打开GameMain.cs文件,在【SpriteBatch spriteBatch;】下方定义当前场景:

找到【LoadContent()】方法,设置最初加载的场景:

找到【Draw(GameTime gameTime)】方法,定义场景绘制方式,将整个Draw方法修改为:

这时候只需要在【Update(GameTime gameTime)】方法中去修改【currentScence = GameScence.GamePlaying;】就可以修改游戏场景。这是最简单也是最容易理解的一种游戏场景切换方式,根据一个枚举类型,来绘制不同的游戏元素,来达到场景切换的效果。
游戏背景
从素材中选中【GameBackground.png】,将它复制到【SelectWife.XNAContent】项目中,选中【GameBackground.png】右键属性,如下图设置:

打开GameMain.cs文件,在【GameScence currentScence;】后面定义游戏背景纹理图和位置大小变量

接着在【LoadContent()】方法中加载背景图纹理和初始化背景位置和大小

绘制游戏背景,找到【Draw(GameTime gameTime)】方法,由于游戏背景绘制在其他游戏元素的最下面一层,而且无论任何场景都一样,所以在【Draw(GameTime gameTime)】方法的【 GraphicsDevice.Clear(Color.CornflowerBlue);】后面,输入

点击【启动】效果如图

游戏标题
拷贝素材中的【GameTitle.png】,将它复制到【SelectWife.XNAContent】项目中,选中【GameTitle.png】右键属性,如下图设置:

打开GameMain.cs文件,定义标题的纹理和位置大小:

接着在【LoadContent()】方法中加载标题纹理和初始化标题位置和大小

【gameTitleTexture2D.Bounds.Width】表示标题图片的实际宽度,(游戏的宽度-标题宽度)/2 就可以让标题居中显示。
绘制游戏标题,找到【Draw(GameTime gameTime)】方法,在方法体中找到【 if (currentScence==GameScence.MainMenu)】,在它的区域中找到【spriteBatch.Begin();和 spriteBatch.End();】在它们之间输入:

点击【启动】,效果如下图:

游戏开始按钮
在素材中找到【PlayNormal.png】,拷贝到【SelectWife.XNAContent】中,属性设置如下图:

打开GameMain.cs文件,找到【Rectangle gameTitleRectangle;】在下面定义开始按钮的纹理和位置大小:

接着在【LoadContent()】方法中加载开始按钮纹理和位置大小

最后绘制开始按钮,找到【Draw(GameTime gameTime)】方法,在方法体中找到【 if (currentScence==GameScence.MainMenu)】,在它的区域中找到【spriteBatch.Begin();和 spriteBatch.End();】在它们之间,游戏标题绘制的下面输入:


音效开关和关于按钮
在素材中找到【SoundOn.png】和【About.png】,拷贝到【SelectWife.XNAContent】中,同时选中这两张图片,右键属性设置如下图:

打开GameMain.cs文件,找到【 Rectangle playNormalRectangle;】在下面定义声效开关和关于按钮的纹理和位置大小:

找到【LoadContent()】方法,加载音效开关按钮纹理和位置大小,加载关于按钮纹理和位置大小

找到【Draw(GameTime gameTime)】方法,在方法体中找到【 if (currentScence==GameScence.MainMenu)】,在它的区域中找到【spriteBatch.Begin();和 spriteBatch.End();】在它们之间,开始按钮绘制的下面输入:

点击【启动】,效果如下图:

自定义鼠标
在素材中找到【MouseCursor.png】,拷贝到【SelectWife.XNAContent】中,属性设置如下图:

打开GameMain.cs文件,找到【 SpriteBatch spriteBatch;】在下面定义鼠标图片纹理和位置大小

找到【LoadContent()】方法,在方法体内加载自定义鼠标纹理图和初始化坐标及大小

绘制鼠标,找到【Draw(GameTime gameTime)】方法,由于鼠标位于最顶层,所以在方法体的最后【base.Draw(gameTime);】之前加入

最后让鼠标纹理图跟随鼠标移动,找到【Update(GameTime gameTime)】方法,在方法体内输入

点击【启动】,运行效果如下图:

关于场景
这是最简单的功能,只需要输出一段文字即可。我们从最简单的场景开始。
选中【SelectWife.XNAContent】项目,点击右键【添加】【新建项】

【Visual C#】选择【Sprite Font】,名称输入【AboutFont.spritefont】,点击【确定】。如下图:

双击打开AboutFont.spritefont文件,找到【<FontName>Segoe UI Mono</FontName>】改为

字体改为

打开MonoGame字符简化工具:https://www.microsoft.com/store/apps/9nvl2gr44t01,将【游戏名称:选老婆\n\r作者:chengcong\n\r版权所有:www.xnadevelop.com】输入到文本框中,点击【转换】【复制到剪贴板】

拷贝到AboutFont.spritefont文件的CharacterRegions节点中,如图红线所示位置:

打开GameMain.cs文件,定义关于场景中用到的文字和位置

找到【ContentLoad()】方法,在方法体内加载关于场景的字体和初始化字体位置

找到【 Draw(GameTime gameTime)】方法,在方法体内找到绘制关于场景的【 else if (currentScence == GameScence.About)】,在【spriteBatch.Begin();】和【spriteBatch.End();】之间输入:

接着实现场景跳转,找到【Update(GameTime gameTime)】方法,在获取鼠标状态之后的【 mouseCursorRectangle.Y = mouseState.Y;】这行代码后面加入:

点击【启动】,效果如下图:

这时候你会发现场景跳转到关于页面以后没办法返回,所有这里需要添加个返回按钮来回到主菜单场景。
拷贝素材中的【Back.png】到【SelectWife.XNAContent】,右键属性。设置如下图:

打开GameMain.cs文件,定义返回按钮纹理图片和坐标

找到【ContentLoad()】方法,在方法体内加载返回按钮的图片纹理和位置大小:

找到【Draw(GameTime gameTime)】方法体内的关于场景部分,在【spriteBatch.DrawString(aboutFont, aboutText, aboutFontPosition, Color.Orange);】后面输入:

来绘制返回按钮。
找到【Update(GameTime gameTime)】方法,在获取鼠标状态的代码之后,输入:

实现点击返回按钮,退回主菜单场景的功能
点击【启动】,效果如下图:

音乐和音效
将素材中的【Music.mp3】和【Click.mp3】拷贝到【SelectWife.XNAContent】项目中,【Music.mp3】右键属性设置如下图:

【Click.mp3】右键属性设置如下图:

打开GameMain.cs文件,定义背景音乐和音效:

找到【LoadContent()】方法,在方法体内加载背景音乐和按钮音效并播放:

找到【Update(GameTime gameTime)】方法,在【 if (currentScence == GameScence.MainMenu)】中括号内输入:

点击【启动】,这时候你会发现虽然点击了关闭音效音乐按钮后确实停止了背景音乐,但按钮的图案还是打开状态,所以这里需要对原来的代码做出修改。
在素材中找到【SoundOff.png】将它拷贝到【SelectWife.XNAContent】项目中,属性如下图设置:

找到【定义声效开关按钮的纹理和位置】的地方,新增一个静音状态的纹理定义

找到【ContentLoad()】方法,加载静音按钮纹理:

找到【Draw(GameTime gameTime)】方法,在方法体内找到主菜单场景的部分【 if (currentScence == GameScence.MainMenu)】在里面找到绘制音效按钮的部分,将【spriteBatch.Draw(soundOnTexture2D, soundOnRectangle, Color.White);】改为:

点击【启动】,效果如下图:

游戏场景
打开GameMain.cs文件,找到【Update(GameTime gameTime)】方法,找到【if (currentScence == GameScence.MainMenu)】,在其内部加入跳转到游戏场景的代码:

点击【启动】,效果如下图:

这时候你会发现游戏场景缺少一个返回按钮返回到主菜单场景,所以需要添加返回按钮。
找到【Draw(GameTime gameTime)】方法中的【else if (currentScence == GameScence.GamePlaying)】,在 【 spriteBatch.Begin();】和【spriteBatch.End();】加入

找到【Update(GameTime gameTime)】方法,在鼠标状态代码后面,加入

点击【启动】,效果如下图:

从素材中拷贝【Wife1.png到Wife11.png】到【SelectWife.XNAContent】 项目中,选中这11个图片,属性如下图设置:

打开GameMain.cs文件,定义一个图片纹理列表和当前图片的索引

在【LoadContent()】方法中用一个循环来加载11张图片,并定义位置

找到【Update(GameTime gameTime)】方法中的绘制游戏场景的【 else if (currentScence == GameScence.GamePlaying)】代码,在里面加入

点击【启动】,这时候显示的只是第一张。

接着让图片动起来,在GameMain.cs文件中定义:

找到【Update(GameTime gameTime)】方法里的【if (currentScence == GameScence.GamePlaying)】输入:

点击【启动】,可以看到老婆们已经蠢蠢欲动了!如下图:

修改timePerFame 的值就可以加快图片,越小越快!当然如果设置成16.6以下,是感觉不出来的,超过了每秒60张
在素材中找到【MarryHer.png】,复制到【SelectWife.XNAContent】中,属性设置如下:

打开GameMain.cs文件,定义选老婆按钮图片的纹理和位置大小:

在【LoadContent()】加载选老婆按钮和初始化位置大小:

找到【Draw(GameTime gameTime)】方法中的【else if (currentScence == GameScence.GamePlaying)】,在【spriteBatch.Begin();】和【spriteBatch.End();】之间输入:


下面来实现选老婆的效果。
首先定义一个开关,来停止图片切换,打开GameMain.cs文件,输入:

找到【Update(GameTime gameTime)】方法中的【 timeLastFrame = timeLastFrame + gameTime.ElapsedGameTime.Milliseconds;】在外层加入一个判断,如下代码:

找到【Update(GameTime gameTime)】方法中的【if (mouseState.LeftButton != ButtonState.Released && playNormalRectangle.Contains(mouseState.X, mouseState.Y))】,在内部加入:

找到【Update(GameTime gameTime)】方法中的【 if (currentScence == GameScence.GamePlaying)】,在里面加入:

点击【启动】,这时候你会看到点击开始按钮进入游戏后,图片就直接停止了,这是因为update方法是一个不停执行的过程,速度过快直接导致主菜单【开始】按钮的点击鼠标传递到了游戏场景中的【选老婆】按钮。

处理方法:打开GameMain.cs文件,在全局位置定义一个鼠标状态:

找到【Update(GameTime gameTime)】方法,在最后【base.Update(gameTime);】之前输入:

然后找到【 if ( mouseState.LeftButton != ButtonState.Released && marryHerRectangle.Contains(mouseState.X, mouseState.Y))】修改为

即

点击【启动】,运行效果如下图:

点击【选老婆】按钮后,需要跳转到游戏结束的场景,在【Update(GameTime gameTime)】方法中找到【 if (mouseState!=prevMouseState&& mouseState.LeftButton != ButtonState.Released && marryHerRectangle.Contains(mouseState.X, mouseState.Y))】在里面加入

效果如下图:

游戏结束
从素材中拷贝【DoubleHappiness.png】【MainMenu.png】【Divorce.png】到【SelectWife.XNAContent】项目中,同时选中三个文件,右键属性。设置如下图:

打开GameMain.cs文件,定义双喜图片、主菜单按钮、离婚按钮的图片纹理和位置大小:

在【ContentLoad()】方法中加载这些图片纹理和位置大小:

在【Draw(GameTime gameTime)】方法中找到【else if (currentScence == GameScence.GameOver)】,在【spriteBatch.Begin();】和【spriteBatch.End();】加入:


