XNA之RPG游戏开发教程之三

本节在上一节基础上继续完善该游戏引擎,主要完成以下任务:

(1)完善StartMenuScreen,同时添加一个GamePlayScreen页面

(2)创建一个新的控件,picture box

(3)为ControlManager类添加新的事件处理

首先是给ControlManager类添加新的事件处理,FocusChanged事件;因为要通过LinkLabel实现页面间跳转,控件的聚焦变化后触发该事件,ControlManager类代码修改如下:

#region Event Region
public event EventHandler FocusChanged;//聚焦更改事件
#endregion
public void NextControl()
{
if (Count == 0)
return;
int currentControl = selectedControl;
this[selectedControl].HasFocus = false;
do
 {
 selectedControl++;
if (selectedControl == Count)
 selectedControl = 0;
if (this[selectedControl].TabStop && this[selectedControl].Enabled)
 {
//代码增添部分,当LinkLabel控件聚焦发生改变,触发事件
if (FocusChanged != null) FocusChanged(this[selectedControl], null); break; } } while (currentControl != selectedControl); this[selectedControl].HasFocus = true; }
public void PreviousControl() { if (Count == 0) return; int currentControl = selectedControl; this[selectedControl].HasFocus = false; do { selectedControl--; if (selectedControl < 0) selectedControl = Count - 1; if (this[selectedControl].TabStop && this[selectedControl].Enabled) { if (FocusChanged != null) FocusChanged(this[selectedControl], null); break; } } while (currentControl != selectedControl); this[selectedControl].HasFocus = true; }

添加一个新的游戏页面GamePlayScreen,代码跟上一节的StartMenuScreen的代码相似,只是对BaseGameState的简单继承

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using XRpgLibrary;
namespace EyesOfTheDragon.GameScreens
{
public class GamePlayScreen : BaseGameState
 {
 #region Field Region
 #endregion
 #region Property Region
 #endregion
 #region Constructor Region
public GamePlayScreen(Game game, GameStateManager manager)
 : base(game, manager)
 {
 }
 #endregion #region XNA Method Region
public override void Initialize()
 {
base.Initialize();
 }
protected override void LoadContent()
 {
base.LoadContent();
 }
public override void Update(GameTime gameTime)
 {
base.Update(gameTime);
 }
public override void Draw(GameTime gameTime)
 {
base.Draw(gameTime);
 }
 #endregion
 #region Abstract Method Region
 #endregion
 }
}

将该页面添加到Game1.cs中

public GamePlayScreen GamePlayScreen;//定义一个类级变量
public Game1()
{
 graphics = new GraphicsDeviceManager(this);
 graphics.PreferredBackBufferWidth = screenWidth;
 graphics.PreferredBackBufferHeight = screenHeight;
 ScreenRectangle = new Rectangle(
 0,
 0,
 screenWidth,
 screenHeight);
 Content.RootDirectory = "Content";
 Components.Add(new InputHandler(this));
 stateManager = new GameStateManager(this);
 Components.Add(stateManager);
 TitleScreen = new TitleScreen(this, stateManager);
 StartMenuScreen = new StartMenuScreen(this, stateManager);
 GamePlayScreen = new GamePlayScreen(this, stateManager);//在类中添加对象
 stateManager.ChangeState(TitleScreen);
}

第二件事就是创建一个新的控件:picture box,跟LinkLabel一样

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
namespace XRpgLibrary.Controls
{
public class PictureBox : Control
 {
 #region Field Region
Texture2D image;//控件中加载的图片
Rectangle sourceRect;//图片的长度矩形
Rectangle destRect;//图片在窗体上呈现的矩形
 #endregion
 #region Property Region
public Texture2D Image
 {
get { return image; }
set { image = value; }
 }
public Rectangle SourceRectangle
 {
get { return sourceRect; }
set { sourceRect = value; }
 }
public Rectangle DestinationRectangle
 {
get { return destRect; }
set { destRect = value; }
 }
 #endregion
 #region Constructors构造函数的重载
public PictureBox(Texture2D image, Rectangle destination)
 {
 Image = image;
 DestinationRectangle = destination;
 SourceRectangle = new Rectangle(0, 0, image.Width, image.Height);//原图片大小
 Color = Color.White;
 }
public PictureBox(Texture2D image, Rectangle destination, Rectangle source)
 {
 Image = image;
 DestinationRectangle = destination;
 SourceRectangle = source;
 Color = Color.White;
 }
 #endregion
 #region Abstract Method Region//来自于继承类的方法重载
public override void Update(GameTime gameTime)
 { }
public override void Draw(SpriteBatch spriteBatch)
 {
 spriteBatch.Draw(image, destRect, sourceRect, Color);
 }
public override void HandleInput(PlayerIndex playerIndex)
 {
 }
 #endregion
 #region Picture Box Methods//为新的图片框设定位置
public void SetPosition(Vector2 newPosition)
 {
 destRect = new Rectangle(
 (int)newPosition.X,
 (int)newPosition.Y,
 sourceRect.Width,
 sourceRect.Height);
 }
 #endregion
 }
}

PictureBox控件需要加载图片,在EyesOfTheDragonContent目录下添加一个新的文件夹GUI,将leftarrowUp.png,rightarrowUp.png,StopBar.png三幅图片加入以便用于图片控件的调用

接下来就是最后一个任务,将PictureBox控件添加到StartMenuGreen.cs中来完善该页面,具体代码如下

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Content;
using XRpgLibrary;
using XRpgLibrary.Controls;
namespace EyesOfTheDragon.GameScreens
{
public class StartMenuScreen : BaseGameState
 {
 #region Field region
PictureBox backgroundImage;//页面中的背景图片
PictureBox arrowImage;//页面中的箭头图标
LinkLabel startGame;//三个选项,开始游戏,登陆游戏,结束游戏
LinkLabel loadGame;
LinkLabel exitGame;
float maxItemWidth = 0f;//用来控制箭头图标显示位置
 #endregion
 #region Property Region
 #endregion
 #region Constructor Region
public StartMenuScreen(Game game, GameStateManager manager)
 : base(game, manager)
 {
 }
 #endregion
 #region XNA Method Region
public override void Initialize()
 {
base.Initialize();
 }
protected override void LoadContent()
 {
base.LoadContent();//要先调用基类的登陆函数,这样就实例化了ControlManager对象
ContentManager Content = Game.Content; //
backgroundImage = new PictureBox( Content.Load<Texture2D>(@"Backgrounds\titlescreen"), GameRef.ScreenRectangle);//实例化背景图片框并加入到控件管理对象中 ControlManager.Add(backgroundImage); Texture2D arrowTexture = Content.Load<Texture2D>(@"GUI\leftarrowUp"); arrowImage = new PictureBox( arrowTexture, new Rectangle( 0, 0, arrowTexture.Width, arrowTexture.Height)); ControlManager.Add(arrowImage);//实例化箭头图片框并加入到控件管理对象中 startGame = new LinkLabel(); startGame.Text = "The story begins"; startGame.Size = startGame.SpriteFont.MeasureString(startGame.Text); startGame.Selected +=new EventHandler(menuItem_Selected); ControlManager.Add(startGame); loadGame = new LinkLabel(); loadGame.Text = "The story continues"; loadGame.Size = loadGame.SpriteFont.MeasureString(loadGame.Text); loadGame.Selected += menuItem_Selected; ControlManager.Add(loadGame); exitGame = new LinkLabel(); exitGame.Text = "The story ends"; exitGame.Size = exitGame.SpriteFont.MeasureString(exitGame.Text); exitGame.Selected += menuItem_Selected; ControlManager.Add(exitGame);//在控件管理类中添加三个选择按键 ControlManager.NextControl(); ControlManager.FocusChanged += new EventHandler(ControlManager_FocusChanged);//订阅焦点改变事件 Vector2 position = new Vector2(350, 500);//定义选择按键的起始位置
//遍历控件管理类中的所有控件
foreach (Control c in ControlManager) { if (c is LinkLabel) {
//如果是LinkLabel控件,就在起始位置上向下排列放置
if (c.Size.X > maxItemWidth) maxItemWidth = c.Size.X; c.Position = position; position.Y += c.Size.Y + 5f; } } ControlManager_FocusChanged(startGame, null);//触发事件,起始状态为箭头出现在startGame按键旁 } void ControlManager_FocusChanged(object sender, EventArgs e)//聚焦改变事件,为箭头标记重绘显示位置 { Control control = sender as Control; Vector2 position = new Vector2(control.Position.X + maxItemWidth + 10f, control.Position.Y); arrowImage.SetPosition(position); } private void menuItem_Selected(object sender, EventArgs e) {
//按键选中事件触发,如果选中startGame或者loadGame按键,跳转到GamePlayScreen页面
if (sender == startGame) { StateManager.PushState(GameRef.GamePlayScreen); } if (sender == loadGame) { StateManager.PushState(GameRef.GamePlayScreen); }
//如果选中的是exitGame按键,跳出游戏
if (sender == exitGame) { GameRef.Exit(); } } public override void Update(GameTime gameTime) { ControlManager.Update(gameTime, playerIndexInControl); base.Update(gameTime); } public override void Draw(GameTime gameTime) { GameRef.SpriteBatch.Begin(); base.Draw(gameTime); ControlManager.Draw(GameRef.SpriteBatch); GameRef.SpriteBatch.End(); } #endregion #region Game State Method Region #endregion } }

OK,今天任务结束

原文地址:https://www.cnblogs.com/zcftech/p/2998293.html