VerticalMenu也是一个可重用的类,也可以添加到Engine项目中。菜单还需要添加按钮的方法和一个Render方法。
using System; using System.Collections.Generic; using System.Linq; using System.Text; using Engine.Input; // Input needs to be added for gamepad input. using System.Windows.Forms; // Used for keyboard input namespace Engine { public class VerticalMenu { Vector _position = new Vector(); Input.Input _input; List_buttons = new List(); public double Spacing { get; set; } public VerticalMenu(double x, double y, Input.Input input) { _input = input; _position = new Vector(x, y, 0); Spacing = 50; } public void AddButton(Button button) { double _currentY = _position.Y; if (_buttons.Count != 0) { _currentY = _buttons.Last().Position.Y; _currentY -= Spacing; } else { // It's the first button added it should have // focus button.OnGainFocus(); } button.Position = new Vector(_position.X, _currentY, 0); _buttons.Add(button); } public void Render(Renderer renderer) { _buttons.ForEach(x => x.Render(renderer)); } } }
按钮的位置被自动处理。每次添加按钮时,会把新按钮添加到Y轴上其他按钮的下方。Spacing成员决定了按钮之间的距离,默认为50像素。菜单本身也有一个位置,允许把按钮作为一个整体四处移动。这个位置只在构造函数中进行设置。在构造VerticalMenu后,其位置不能改变,因为这需要一个额外的方法在新位置重新排列所有的按钮。这种功能很不错,但是却不是必须具有的。Render方法使用C#新增的lambda操作符来渲染所有按钮。
菜单类还不处理用户输入,但是在添加处理输入的代码之前,首先将菜单与StartMenuState关联起来,以便测试菜单和按钮是否可以正确工作。按钮上的标签将使用与标题文本不同的字体。从本书的配套光盘上找到general_font.fnt和general_font.tga,把它们添加到项目中。然后需要在Form.cs文件中设置这个新字体。
// In form.cs private void InitializeTextures() { // Init DevIl Il.ilInit(); Ilu.iluInit(); Ilut.ilutInit(); Ilut.ilutRenderer(Ilut.ILUT_OPENGL); // Textures are loaded here. _textureManager.LoadTexture("title_font", "title_font.tga"); _textureManager.LoadTexture("general_font", "general_font.tga"); } Engine.Font _generalFont; Engine.Font _titleFont; private void InitializeFonts() { // Fonts are loaded here. _titleFont = new Engine.Font(_textureManager.Get("title_font"), FontParser.Parse("title_font.fnt")); _generalFont = new Engine.Font(_textureManager.Get("general_font"), FontParser.Parse("general_font.fnt")); }
这个新的通用字体可以传递给构造函数中的StartMenuState,以构造垂直菜单。此时也会传递Input类,所以需要把using Engine.Input语句添加到StartMenuState.cs文件顶部。
Engine.Font _generalFont; Input _input; VerticalMenu _menu; public StartMenuState(Engine.Font titleFont, Engine.Font generalFont, Input = input) { _input = input; _generalFont = generalFont; InitializeMenu();
实际的菜单创建工作是在InitializeMenu函数中完成的,这样可以避免StartMenuState构造函数变得拥挤。StartMenuState创建了一个在X轴居中、在Y轴上方150像素位置的垂直菜单。这会在标题文本下方以比较整洁的方式放置菜单。