XNA之RPG游戏开发教程之六
本节的任务有两点:1、创建一个新控件,实现角色的选择;具体操作要求是按左键,呈现上一个角色信息,按右键呈现下一个角色信息;2、创建一个角色选择页面,将新控件添加进去
首先开始第一个任务,前面已经创建了控件基类Control类和控件管理类ControlManager类,新的控件要继承基类,并在页面实例化后要添加进管理类中便于操作管理。新控件LeftRightSelector,一个向左向右可选择控件的代码实现如下
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 LeftRightSelector : Control { #region Event Region public event EventHandler SelectionChanged;//控件选择更改事件 #endregion #region Field Region List<string> items = new List<string>();//控件中呈现字符串集合 Texture2D leftTexture;//表示向左,向右,尽头终止的图片 Texture2D rightTexture; Texture2D stopTexture; Color selectedColor = Color.Red;//被选字符串呈现红色 int maxItemWidth;//字符串项的最大宽度 int selectedItem;//被选择的项索引 #endregion #region Property Region public Color SelectedColor { get { return selectedColor; } set { selectedColor = value; } }
public int SelectedIndex { get { return selectedItem; } set { selectedItem = (int)MathHelper.Clamp(value, 0f, items.Count); } } public string SelectedItem { get { return Items[selectedItem]; } } public List<string> Items { get { return items; } } #endregion #region Constructor Region public LeftRightSelector(Texture2D leftArrow, Texture2D rightArrow, Texture2D stop) { leftTexture = leftArrow; rightTexture = rightArrow; stopTexture = stop; TabStop = true; Color = Color.White; } #endregion #region Method Region为字符串序列和字符串最大宽度赋值 public void SetItems(string[] items, int maxWidth) { this.items.Clear(); foreach (string s in items) this.items.Add(s); maxItemWidth = maxWidth; }
//事件触发函数 protected void OnSelectionChanged() { if (SelectionChanged != null) { SelectionChanged(this, null); } } #endregion #region Abstract Method Region public override void Update(GameTime gameTime) { } public override void Draw(SpriteBatch spriteBatch) { Vector2 drawTo = position; if (selectedItem != 0) spriteBatch.Draw(leftTexture, drawTo, Color.White); else spriteBatch.Draw(stopTexture, drawTo, Color.White); drawTo.X += leftTexture.Width + 5f;
float itemWidth = spriteFont.MeasureString(items[selectedItem]).X; float offset = (maxItemWidth - itemWidth) / 2; drawTo.X += offset; if (hasFocus) spriteBatch.DrawString(spriteFont, items[selectedItem], drawTo, selectedColor); else spriteBatch.DrawString(spriteFont, items[selectedItem], drawTo, Color); drawTo.X += -1 * offset + maxItemWidth + 5f; if (selectedItem != items.Count - 1) spriteBatch.Draw(rightTexture, drawTo, Color.White); else spriteBatch.Draw(stopTexture, drawTo, Color.White); } public override void HandleInput(PlayerIndex playerIndex) { if (items.Count == 0) return; if (InputHandler.ButtonReleased(Buttons.LeftThumbstickLeft, playerIndex) || InputHandler.ButtonReleased(Buttons.DPadLeft, playerIndex) || InputHandler.KeyReleased(Keys.Left)) { selectedItem--; if (selectedItem < 0) selectedItem = 0; OnSelectionChanged();//触发事件 } if (InputHandler.ButtonReleased(Buttons.LeftThumbstickRight, playerIndex) || InputHandler.ButtonReleased(Buttons.DPadRight, playerIndex) || InputHandler.KeyReleased(Keys.Right)) { selectedItem++; if (selectedItem >= items.Count) selectedItem = items.Count - 1; OnSelectionChanged(); } } #endregion } }
接着就是添加一个新的游戏页面,用来选取角色信息,具体代码如下
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; using XRpgLibrary.Controls; namespace EyesOfTheDragon.GameScreens { public class CharacterGeneratorScreen : BaseGameState { #region Field Region LeftRightSelector genderSelector;//关于角色性别的selector控件 LeftRightSelector classSelector;//关于角色类型的selector控件 PictureBox backgroundImage;//游戏背景图片框 string[] genderItems = { "Male", "Female" };//用于初始化性别selector控件的字符串集 string[] classItems = { "Fighter", "Wizard", "Rogue", "Priest" }; #endregion #region Property Region #endregion #region Constructor Region public CharacterGeneratorScreen(Game game, GameStateManager stateManager) : base(game, stateManager) { } #endregion #region XNA Method Region public override void Initialize() { base.Initialize(); } protected override void LoadContent() { base.LoadContent(); CreateControls(); } public override void Update(GameTime gameTime) { ControlManager.Update(gameTime, PlayerIndex.One);//对ControlManager进行更新,在其中会触发对页面上所有控件的更新 base.Update(gameTime); } public override void Draw(GameTime gameTime) { GameRef.SpriteBatch.Begin(); base.Draw(gameTime); ControlManager.Draw(GameRef.SpriteBatch);//ControlManager的绘制,在其中可以对页面上所有控件进行绘制 GameRef.SpriteBatch.End(); } #endregion #region Method Region
private void CreateControls() { Texture2D leftTexture = Game.Content.Load<Texture2D>(@"GUI\leftarrowUp"); Texture2D rightTexture = Game.Content.Load<Texture2D>(@"GUI\rightarrowUp"); Texture2D stopTexture = Game.Content.Load<Texture2D>(@"GUI\StopBar"); backgroundImage = new PictureBox( Game.Content.Load<Texture2D>(@"Backgrounds\titlescreen"), GameRef.ScreenRectangle); ControlManager.Add(backgroundImage);//实例化背景控件,并加入到控件管理类中 Label label1 = new Label(); label1.Text = "Who will search for the Eyes of the Dragon?"; label1.Size = label1.SpriteFont.MeasureString(label1.Text); label1.Position = new Vector2((GameRef.Window.ClientBounds.Width - label1.Size.X) / 2, 150); ControlManager.Add(label1);//实例化标题label,并加入到控件管理类中 genderSelector = new LeftRightSelector(leftTexture, rightTexture, stopTexture); genderSelector.SetItems(genderItems, 125); genderSelector.Position = new Vector2(label1.Position.X, 200); ControlManager.Add(genderSelector);//实例化性别selector,加入管理类 classSelector = new LeftRightSelector(leftTexture, rightTexture, stopTexture); classSelector.SetItems(classItems, 125); classSelector.Position = new Vector2(label1.Position.X, 250); ControlManager.Add(classSelector);//实例化类型selector,加入管理类 LinkLabel linkLabel1 = new LinkLabel(); linkLabel1.Text = "Accept this character."; linkLabel1.Position = new Vector2(label1.Position.X, 300); linkLabel1.Selected += new EventHandler(linkLabel1_Selected); ControlManager.Add(linkLabel1);//实例化接受LinkLabel对象,加入管理类 ControlManager.NextControl();//执行NextControl,使得当前呈现选项为被选中状态 } void linkLabel1_Selected(object sender, EventArgs e) { InputHandler.Flush(); StateManager.PopState(); StateManager.PushState(GameRef.GamePlayScreen);//呈现游戏页面 } #endregion } }
接下来就是讲新的角色选择页面添加到Game1类中,代码如下
public CharacterGeneratorScreen CharacterGeneratorScreen; 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); CharacterGeneratorScreen = new CharacterGeneratorScreen(this, stateManager);//添加新的页面 stateManager.ChangeState(TitleScreen); }
同时在StartMenuScreen页面中修改menuItem_Selected方法,使得选择startgame选项时候,跳转到新建的角色选择页面
private void menuItem_Selected(object sender, EventArgs e) { if (sender == startGame) { StateManager.PushState(GameRef.CharacterGeneratorScreen); } if (sender == loadGame) { StateManager.PushState(GameRef.GamePlayScreen); } if (sender == exitGame) { GameRef.Exit(); } }
OK,本节任务结束