如何将GameState与XNA 4.0中的类文件链接起来

时间:2013-12-15 23:23:44

标签: c# visual-studio-2012 xna xna-4.0

我正在使用XNA 4.0在Visual Studio 2012中的游戏中实现一个菜单系统。我有我的game1类文件中的枚举GameStates mainMenu,Instructions和PlayGame以及所有按钮。如何让游戏使用

我正在运行游戏并希望实现主菜单系统。以下代码是我将在主菜单中使用的代码。我的问题是如何将现有游戏添加到此主菜单代码

using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;

namespace MainMenu
{
/// <summary>
/// This is the main type for your game
/// </summary>
public class Game1 : Microsoft.Xna.Framework.Game
{
    GraphicsDeviceManager graphics;
    SpriteBatch spriteBatch;

    enum GameState
    {
        //which states we which to have
        MainMenu, Instructions, PlayGame,
    }

    //when the game loads, it begins with main menu
    GameState CurrentGameState = GameState.MainMenu;

    //Screen Adjustments
    int screenWidth = 800, screenHeight = 600;

    cButton btnPlay;
    cButton btnInstru;

    public Game1()
    {
        graphics = new GraphicsDeviceManager(this);
        Content.RootDirectory = "Content";
    }

    /// <summary>
    /// Allows the game to perform any initialization it needs to before starting to run.
    /// This is where it can query for any required services and load any non-graphic
    /// related content.  Calling base.Initialize will enumerate through any components
    /// and initialize them as well.
    /// </summary>
    protected override void Initialize()
    {
        // TODO: Add your initialization logic here

        base.Initialize();
    }

    /// <summary>
    /// LoadContent will be called once per game and is the place to load
    /// all of your content.
    /// </summary>
    protected override void LoadContent()
    {
        // Create a new SpriteBatch, which can be used to draw textures.
        spriteBatch = new SpriteBatch(GraphicsDevice);

        //Screen Properties
        graphics.PreferredBackBufferWidth = screenWidth;
        graphics.PreferredBackBufferHeight = screenHeight;
        graphics.ApplyChanges();
        IsMouseVisible = true;

        btnPlay = new cButton(Content.Load<Texture2D>("Button"), graphics.GraphicsDevice);
        btnInstru = new cButton(Content.Load<Texture2D>("Button"), graphics.GraphicsDevice);
        btnPlay.setPosition(new Vector2(350, 300));
        btnInstru.setPosition(new Vector2(350, 350));
    }

    /// <summary>
    /// UnloadContent will be called once per game and is the place to unload
    /// all content.
    /// </summary>
    protected override void UnloadContent()
    {
        // TODO: Unload any non ContentManager content here
    }

    /// <summary>
    /// Allows the game to run logic such as updating the world,
    /// checking for collisions, gathering input, and playing audio.
    /// </summary>
    /// <param name="gameTime">Provides a snapshot of timing values.</param>
    protected override void Update(GameTime gameTime)
    {
        MouseState mouse = Mouse.GetState();

        switch (CurrentGameState)
        {
            case GameState.MainMenu:
                if (btnPlay.isClicked == true)
                {
                    CurrentGameState = GameState.PlayGame;
                }

                if (btnInstru.isClicked == true)
                {
                    CurrentGameState = GameState.Instructions;
                }

                btnPlay.Update(mouse);
                btnInstru.Update(mouse);

                break;

            case GameState.PlayGame:

                break;

            case GameState.Instructions:

                break;

        }

        base.Update(gameTime);
    }

    /// <summary>
    /// This is called when the game should draw itself.
    /// </summary>
    /// <param name="gameTime">Provides a snapshot of timing values.</param>
    protected override void Draw(GameTime gameTime)
    {
        GraphicsDevice.Clear(Color.CornflowerBlue);

        spriteBatch.Begin();

        switch (CurrentGameState)
        {
            case GameState.MainMenu:
                spriteBatch.Draw(Content.Load<Texture2D>("MainMenu"), new Rectangle(0, 0, screenWidth, screenHeight), Color.White);
                btnPlay.Draw(spriteBatch);
                btnInstru.Draw(spriteBatch);
                break;

            case GameState.PlayGame:

                break;

            case GameState.Instructions:

                break;

        }

        spriteBatch.End();


        base.Draw(gameTime);
    }
}

}

2 个答案:

答案 0 :(得分:0)

通常你会把它添加到你的GameState.PlayGame中,好像它不够明显。那就是你要画你的精灵,游戏物品,敌人等等。

此外,如果你打算做一个菜单系统,你可能想要使用类。

答案 1 :(得分:0)

我避免放下任何代码,我只是提出一些关于你可以遵循的指示。如果您自己动手(它的优秀实践),它将允许您思考并添加您可能没有完成的不同功能,如果您刚刚直接使用我的代码。或者你可以更简单的方式继承gamecomponent对象,但它缺乏灵活性imo。

关于你的游戏,这就是我的错误:你将使用一个巨大的开关盒。当你的游戏处于良好的发展阶段时,它最终会变得无法控制。为避免出现这种情况,请立即停止操作,而是为自己创建一个GameState Manager。你想要的是分离游戏的每个元素。您的主循环应始终呼叫经理。并且让我们了解应该在这些经理中绘制什么。让我们称之为GameWindows。

每个管理器都有一个属性,它是一个自定义类列表,它们处理逻辑(WindowsList)。你给那些“Windows”一个ID或一个唯一的名字(在你的情况下是一个GameState)。

在管理器的更新代码中,您迭代抛出WindowsList,并更新所有具有标志“WindowIsActive”的类为true。在绘图代码中,您绘制所有具有“可见”标志的窗口为true。

在GameWindows中,你创建一个函数Erase(windowsName)(你不能只从列表中删除一个窗口,否则它会在迭代中崩溃,你创建第二个列表“WindowsToDelete”并添加你要删除的窗口那里,你在更新阶段处理删除)

现在,您的主要game1课程将更加清洁。你只需要在update方法中使用GameWindows.Update(),在draw方法中使用GameWindows.Draw()。

基本上,这可以让你创建不同的元素和功能(比如一个菜单,可以看不见,并在按键时调用),而不必在每次添加不同的游戏元素时处理越来越大的开关案例。并且它将仅更新/绘制您需要的窗口,允许您“睡眠”您不需要的元素,并允许您保持游戏快速运行。

将所有自定义类“Windows”视为一个单独的元素,您可以为它们中的每一个处理它们的特定Draw()函数。我还在每个“Window”中都有一个TestClick(mousePosition)函数,您可以在GameWindows.Update()中使用它来处理不同的鼠标点击。