XNA4.0 RPG游戏开发教程(六)
2016-03-10 10:43
281 查看
这个系列教程适合有一定C#和XNA4.0基础的朋友,如果没有学习过C#,那么《C#高级编程(第7版)》是一本不错的入门书籍,在http://pan.baidu.com/s/1sko1FnJ可以找到PDF版本,如果你从未接触过XNA4.0,那么《XNA4.0学习指南》是一本不错的入门书籍,在http://pan.baidu.com/s/1baJbWE可以找到PDF版本和随书源代码。
翻译国外的系列教程,一步步讲述如何用XNA4.0开发RPG游戏,是XNA4.0游戏开发为数不多的具有实战意义的教程。
原文地址:http://xnagpa.net/xna4rpg.php
作者非常耐心,每一步操作都讲的很详细,每一课都附有源代码。
我在翻译的过程中,根据作者的教程,又重新把每一课的源代码写一遍,目的是为了验证作者的源代码。
我重写的每一课源代码下载:http://pan.baidu.com/s/1c1tB2Sw
在这个系列教程的前几课,为了照顾初学者,我会加入操作截图,后续的课程我将假定你使用XNA4.0框架已经比较熟练了,所以不会再添加截图。
六、角色生成
我正在写一些XNA4.0框架的教程,这些教程如果按照顺序阅读将会起到更好的效果。
这是这个系列教程(XNA4.0 RPG游戏开发)的第六部分,在这一课我将添加一个新的screen来创建一个角色。首先我要添加一个新的控件,一个左右选择器,当选中这个控件,并按下左、右方向键的时候会在一个字符串集合中循环。右键点击“Controls”文件夹,选择“添加”——“新建项”——“类”,名字输入“LeftRightSelector”。代码如下
items字段表示可选项的列表,有3个Texture2D对象,分别表示左箭头、右箭头、结束符(向左或向右翻到达尽头),再次感谢Tuckbone为我制作这些图片,selectedColor表示选中项的颜色,maxItemWidth表示所有选项的最大宽度,selectedIndex表示当前选中项在选择器的序号。
SetItems方法将用一个新的选项集合重置当前控件的选项集合,OnSelectionChanged是事件处理函数。
Draw方法绘制控件,控件的左边,如果选中项的序号为0(向左翻到了尽头),则显示结束符,否则显示左箭头;控件的中间,如果当前控件被选中,则按指定的颜色绘制当前选中项文字,否则按默认颜色绘制当前选中项文字;控件的右边,如果当前选中项的序号为总数-1(向右翻到了尽头),则显示结束符,否则显示右箭头。
HandleInput方法处理键盘和游戏手柄输入,当玩家按下左方向键,当前选中项序号-1,判断向左翻动是否到了尽头,然后触发OnSelectionChanged事件,当玩家按下右方向键则相反。
现在我们来添加一个新的screen,右键点击“GameScreens”文件夹,选择“添加”——“新建项”——“类”,名字输入“CharacterGeneratorScreen”。代码如下
本课教程就到这里吧,我尽量让每课教程保持一个合理的长度,这样不会让你一下子面对太多内容。
祝你在游戏开发之旅好运。
Jamie McMahon
翻译:阿斌
翻译国外的系列教程,一步步讲述如何用XNA4.0开发RPG游戏,是XNA4.0游戏开发为数不多的具有实战意义的教程。
原文地址:http://xnagpa.net/xna4rpg.php
作者非常耐心,每一步操作都讲的很详细,每一课都附有源代码。
我在翻译的过程中,根据作者的教程,又重新把每一课的源代码写一遍,目的是为了验证作者的源代码。
我重写的每一课源代码下载:http://pan.baidu.com/s/1c1tB2Sw
在这个系列教程的前几课,为了照顾初学者,我会加入操作截图,后续的课程我将假定你使用XNA4.0框架已经比较熟练了,所以不会再添加截图。
六、角色生成
我正在写一些XNA4.0框架的教程,这些教程如果按照顺序阅读将会起到更好的效果。
这是这个系列教程(XNA4.0 RPG游戏开发)的第六部分,在这一课我将添加一个新的screen来创建一个角色。首先我要添加一个新的控件,一个左右选择器,当选中这个控件,并按下左、右方向键的时候会在一个字符串集合中循环。右键点击“Controls”文件夹,选择“添加”——“新建项”——“类”,名字输入“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 } }这个类有一个SelectionChanged事件,当选择发生变化时将会触发这个事件。
items字段表示可选项的列表,有3个Texture2D对象,分别表示左箭头、右箭头、结束符(向左或向右翻到达尽头),再次感谢Tuckbone为我制作这些图片,selectedColor表示选中项的颜色,maxItemWidth表示所有选项的最大宽度,selectedIndex表示当前选中项在选择器的序号。
SetItems方法将用一个新的选项集合重置当前控件的选项集合,OnSelectionChanged是事件处理函数。
Draw方法绘制控件,控件的左边,如果选中项的序号为0(向左翻到了尽头),则显示结束符,否则显示左箭头;控件的中间,如果当前控件被选中,则按指定的颜色绘制当前选中项文字,否则按默认颜色绘制当前选中项文字;控件的右边,如果当前选中项的序号为总数-1(向右翻到了尽头),则显示结束符,否则显示右箭头。
HandleInput方法处理键盘和游戏手柄输入,当玩家按下左方向键,当前选中项序号-1,判断向左翻动是否到了尽头,然后触发OnSelectionChanged事件,当玩家按下右方向键则相反。
现在我们来添加一个新的screen,右键点击“GameScreens”文件夹,选择“添加”——“新建项”——“类”,名字输入“CharacterGeneratorScreen”。代码如下
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; LeftRightSelector classSelector; PictureBox backgroundImage; string[] genderItems = { "Male", "Female" }; 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); base.Update(gameTime); } public override void Draw(GameTime gameTime) { GameRef.SpriteBatch.Begin(); base.Draw(gameTime); ControlManager.Draw(GameRef.SpriteBatch); 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); genderSelector = new LeftRightSelector(leftTexture, rightTexture, stopTexture); genderSelector.SetItems(genderItems, 125); genderSelector.Position = new Vector2(label1.Position.X, 200); ControlManager.Add(genderSelector); classSelector = new LeftRightSelector(leftTexture, rightTexture, stopTexture); classSelector.SetItems(classItems, 125); classSelector.Position = new Vector2(label1.Position.X, 250); ControlManager.Add(classSelector); 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); ControlManager.NextControl(); } void linkLabel1_Selected(object sender, EventArgs e) { InputHandler.Flush(); StateManager.PopState(); StateManager.PushState(GameRef.GamePlayScreen); } #endregion } }接下来把这个screen添加到游戏中,打开Game1.cs,在Game State Region区添加一个CharacterGeneratorScreen对象,并且在构造函数中初始化它,代码如下
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.cs,修改它的menuItem_Selected事件处理函数,在选择开始游戏之后,应该是进入CharacterGeneratorScreen,而不是GamePlayScreen。代码如下
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(); } }
本课教程就到这里吧,我尽量让每课教程保持一个合理的长度,这样不会让你一下子面对太多内容。
祝你在游戏开发之旅好运。
Jamie McMahon
翻译:阿斌
相关文章推荐
- XNA学习笔记1
- XNA学习笔记3 鼠标响应
- ContentPipeline
- 显示文字与输入
- 物體在二維空間中的移動
- 了解 XNA 的遊戲架構。
- 遊戲畫面管理與切換控制
- 圖形特效與文字顯示
- 2 維動畫與碰撞偵測
- 進階音效控制與管理
- XNA 互動式遊戲設計
- XNA Framework 常用的類別
- VS 2012、VS 2013安装XNA扩展
- XNA4.0 RPG游戏开发教程(一)
- XNA4.0 RPG游戏开发教程(二)
- XNA4.0 RPG游戏开发教程(三)
- XNA4.0 RPG游戏开发教程(四)
- XNA4.0 RPG游戏开发教程(五)
- 浅谈AVG游戏中的脚本
- Xna3.1中的2D绘图与AlphaBlend(编辑中)