在AndroidGameActivity中运行LoadContent时启动/加载屏幕

时间:2013-11-23 18:58:53

标签: c# android mono monogame

首先,我想说一般来说我对C#和Monogame都很陌生。

我的问题是显示屏幕。 我有一个名为loadingsplash.xml的布局资源,并希望在Game活动运行时显示它LoadContent();

流程图是: Main.xml:按下按钮> LoadContent期间的ProgressDialog> GameActivity

我想要的流程图: Main.xml:按下按钮>在LoadContent>期间显示loadingsplash.xml GameActivity

MainMenu.cs

[Activity( Label = "theApp", Theme = "@android:style/Theme.NoTitleBar.Fullscreen", MainLauncher=true, ScreenOrientation=Android.Content.PM.ScreenOrientation.Landscape)]

public class MainMenu : Activity, IDialogInterfaceOnClickListener
{
......
void GoButton_Click(object sender, EventArgs e)
{
    Intent theActivity = new Intent(this, typeof(GameActivity));
    StartActivity(theActivity);
}

theActivity.cs

namespace theApp
{
    [Activity(Theme = "@android:style/Theme.NoTitleBar.Fullscreen", Label = "theApp", Icon = "@drawable/icon", ScreenOrientation = Android.Content.PM.ScreenOrientation.Landscape, ConfigurationChanges = ConfigChanges.Orientation | ConfigChanges.Keyboard | ConfigChanges.KeyboardHidden)]

    public class GameActivity : Microsoft.Xna.Framework.AndroidGameActivity, IDialogInterfaceOnClickListener
    {
        myGame game = null;
        static GameBundle gameBundle = null;
        ProgressDialog dialog;
        const int WindowID = 10001;

        protected override void OnCreate(Bundle bundle)
        {
            loadedOnce = true;
//this works
//
//dialog = new ProgressDialog(this);
//dialog.SetMessage("Loading...");
//dialog.Show();
//

//Loading Splash screen invocation code goes here?

    if (game == null)
       {
         myGame.Activity = this;
         base.OnCreate (bundle);
         game = new myGame();
         game.NativeCommand = ProcessCommand;
         game.Window.GraphicsMode = new AndroidGraphicsMode(0, 4, 0, 0, 0, false);
         game.Window.Id = WindowID;

                if (gameBundle == null)
                {
                    game.Run();
                }
                else
                {
                    if (gameBundle != null)
                    {
                        resumeGame.Show();
                    }
                }
            }
            SetContentView(game.Window);
        }

myGame.cs

public class myGame : Microsoft.Xna.Framework.Game
{

public myGame()
    {
        graphics = new GraphicsDeviceManager(this);
        Content.RootDirectory = "Resources/Drawable";
        unloading = false;
        graphics.PreferMultiSampling = true;
        graphics.IsFullScreen = true;
        graphics.SupportedOrientations = DisplayOrientation.LandscapeLeft;
    }

    protected override void Initialize()
    {
        graphics.SynchronizeWithVerticalRetrace = true;
        graphics.PreferredBackBufferWidth =  800;
        graphics.PreferredBackBufferHeight = 480;
        screenManager = new ScreenManager(this, 800, 480);
        base.Initialize();
    }

    bool loaded = false;
    protected override void LoadContent()
    {
        spriteBatch = new SpriteBatch(this.GraphicsDevice);
        font = Content.Load<SpriteFont>("Arial");
        GraphicsDevice.Clear(Color.Black);
        ThreadPool.QueueUserWorkItem(state =>
            {
                            ...
                            loaded = true;
            });

如果我使用setContentView(Resource.Layout.LoadingSplash)调用LoadingSplash;在base.OnCreate(bundle)之前我得到一个异常,必须调用requestFeature。

2 个答案:

答案 0 :(得分:1)

我使用以下实现。我计划在不久的将来在NuGet中公开此软件包,以便您可以在https://github.com/AzuxirenLeadGuy/Azuxiren.MG的存储库中进行检查 (请为我的存储库加注星标)

无论如何,我已经在代码中做到了。

首先,我已定义接口IScreen,如下所示:

public interface IScreen
{
    void LoadContent();
    void Update(GameTime gt);
    void Draw(GameTime gt);
}

接下来,我将游戏类定义如下:

public abstract class AMGC<StartScreen,LoadScreen> : Game where StartScreen:IScreen,new() where LoadScreen:IScreen,new()
{
    public GraphicsDeviceManager graphics;
    internal bool isLoading;
    internal IScreen CurrentScreen,LoadingScreen;
    public AMGC()
    {
        graphics = new GraphicsDeviceManager(this);
        isLoading = false;
    }
    protected override void Initialize()
    {
        CurrentScreen = new StartScreen();
        LoadingScreen = new LoadScreen();
        base.Initialize();
    }
    protected override void LoadContent()
    {
        CurrentScreen.LoadContent();
        LoadingScreen.LoadContent();
        base.LoadContent();
    }
    protected override void Draw(GameTime gt)
    {
        if (isLoading) LoadingScreen.Draw(gt);
        else CurrentScreen.Draw(gt);
        base.Draw(gt);
    }
    protected override void Update(GameTime gameTime)
    {
        if (isLoading) LoadingScreen.Update(gameTime);
        else CurrentScreen.Update(gameTime);
        base.Update(gameTime);
    }
    public void ScreenLoad<T>() where T : IScreen, new()
    {
        isLoading = true;
        Task.Run(() =>
            {
                var screen = new T();
                screen.LoadContent();
                CurrentScreen = screen;
                isLoading = false;
            }
        );
    }
}

现在有了该代码,您就可以开始了。现在,您的游戏是在IScreen实例中设计的。假设您制作了一个LogoScreen(游戏开始时显示游戏徽标),MenuScreen(游戏主菜单)和SplashScreen(您想要的通用飞溅屏幕,显示游戏的“正在加载...”)。

您的游戏对象将像这样创建:

AMGC game=new AMGC<LogoScreen, SplashScreen>();

在LogoScreen中,当您必须从LogoScreen更改为MenuScreen时,必须在屏幕切换逻辑中使用它。

game.ScreenLoad<MenuScreen>();

请注意,为此,游戏实例必须是全局的,以便可以从LogoScreen内部进行访问。

答案 1 :(得分:0)

对于仍在寻找此问题答案的人,我建议您不要通过使用不同的xml文件使用单独的屏幕,而应在Monogame本身中对其进行操作。

请看一下我在这篇文章中的回答:https://stackoverflow.com/a/55667101/8594783