zoukankan      html  css  js  c++  java
  • 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,今天任务结束

  • 相关阅读:
    FrameBuffer系列 之 一点资源
    FrameBuffer系列 之 显示图片
    FrameBuffer系列 之 相关结构与结构体
    FrameBuffer系列 之 介绍
    FrameBuffer系列 之 简单编程
    程序员五大层次,你属于哪一层?
    提高编程效率的14件事
    GTK简单了解记录
    __read_mostly变量含义
    [系统启动]Printk与sched_clock_init的一点分析
  • 原文地址:https://www.cnblogs.com/zcftech/p/2998293.html
Copyright © 2011-2022 走看看