Monogame - 剪切场景方法?

时间:2016-05-05 09:28:14

标签: c# .net visual-studio xna monogame

我想创建什么

所以我正在使用Monogame构建2D冒险游戏,在游戏开始时,我想使用显示之前故事情节的 3张图片,有点像介绍切割场景,所以每张图片都显示了导致故事在游戏中开始的地方的不同快照。

我希望它如何运作

我希望它只是显示1个图像,然后被第二个图像重叠,然后是第三个图像,每个图像之间有一个约3秒的暂停(根本没有关注过渡)。

我向所有读者提出的问题

我想知道,实现这一目标的最佳方法是什么,以便在游戏开始时开始?我正在考虑在像Pro Pro这样的场景上制作剪辑场景,它只是一个播放的视频,但是我不确定是否有更好的选择。 我只想知道实现此类目标的最简单方法。

1 个答案:

答案 0 :(得分:1)

最好在一两句话中定义你想要的内容,这样你就可以用简单的方式对其进行编码。我个人将过场动画定义为:“从黑色屏幕淡入的图像列表,保持一点,然后淡入黑色。您可以通过按一个键盘按钮(如空格键)跳过一个图像。”这意味着我将包括计时器和图像。通过这种方式,我知道每张图像以及整个幻灯片的完整播放时间。

我有一些可能对您有帮助的旧代码。此代码显示要显示的图像列表,淡入淡出时间,停留时间和淡出时间。通过将淡入/淡出效果切换为淡入淡出效果,可以轻松将其转换为您想要的效果。

首先,这是单屏类:

using System;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework;

namespace F.U.N
{
    public class SplashScreen
    {
        public enum Status
        {
            Ready,
            FadingIn,
            Waiting,
            FadingOut,
            NotReady
        }
        private Status currentStatus;
        public Status CurrentStatus { get { return currentStatus; } }

        private Texture2D image;
        private Color color;
        private byte fade;
        private float timer,
            fadeInTime,
            waitTime,
            fadeOutTime;

        private float startToWaitTime { get { return fadeInTime; } }
        private float startToFadeOutTime { get { return fadeInTime + waitTime; } }
        private float startToEndTime { get { return fadeInTime + waitTime + fadeOutTime; } }

        public SplashScreen(Texture2D image, float fadeInTime, float waitTime, float fadeOutTime)
        {
            float min = 0.1f;
            this.image = image;
            this.fadeInTime = Math.Max(fadeInTime, min);
            this.waitTime = Math.Max(waitTime, min);
            this.fadeOutTime = Math.Max(fadeOutTime, min);
            Prepare();
        }

        public void Prepare()
        {
            fade = 0;
            timer = 0;
            color = new Color(fade, fade, fade);
            currentStatus = Status.Ready;
        }

        public void Update(GameTime gt)
        {
            //CALCULATE ALPHA & status
            if (timer < startToWaitTime)
            {
                fade = (byte)((byte.MaxValue * timer) / startToWaitTime);
                if (currentStatus != Status.FadingIn) currentStatus = Status.FadingIn;
            }
            else if (timer < startToFadeOutTime)
            {
                if (color.A < byte.MaxValue) color.A = byte.MaxValue;
                if (currentStatus != Status.Waiting) currentStatus = Status.Waiting;
            }
            else if (timer < startToEndTime)
            {
                fade = (byte)(byte.MaxValue - ((byte.MaxValue * (timer - startToFadeOutTime)) / fadeOutTime));
                if (currentStatus != Status.FadingOut) currentStatus = Status.FadingOut;
            }
            else
            {
                fade = byte.MinValue;
                if (currentStatus != Status.NotReady) currentStatus = Status.NotReady;
            }

            //UPDATE COLOR AND TIME
            color = new Color(fade, fade, fade);
            timer += (float)gt.ElapsedGameTime.TotalSeconds;
        }

        public void Draw(SpriteBatch sp)
        {
            sp.Draw(image, new Vector2(), color);
        }

        public void End()
        {
            currentStatus = Status.NotReady;
        }

    }
}

现在,这是创建一系列SpalshScreens的管理器或“父”类:

using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

namespace F.U.N
{
    public class SplashScreenManager
    {
        private List<SplashScreen> screens;
        private Keys skipButton;
        public bool Running
        {
            get
            {
                foreach (SplashScreen s in screens)
                    if (s.CurrentStatus != SplashScreen.Status.NotReady)
                        return true;
                return false;
            }
        }

        public SplashScreenManager() : this(new List<SplashScreen>(), Keys.None) { }
        public SplashScreenManager(List<SplashScreen> screens, Keys skipButton)
        {
            this.screens = screens;
            this.skipButton = skipButton;
            Prepare();
        }
        public SplashScreenManager(string path, float fadeIn, float wait, float fadeOut, Keys skipButton)
        {
            List<Texture2D> images = GContent.Textures(path);
            screens = new List<SplashScreen>();
            foreach (Texture2D t in images)
                screens.Add(new SplashScreen(t, fadeIn, wait, fadeOut));
            this.skipButton = skipButton;
        }

        public void Prepare()
        {
            foreach (SplashScreen s in screens)
                s.Prepare();
        }

        public void Update(GameTime gt)
        {
            for (int i = 0; i < screens.Count(); i++)
            {
                if (screens[i].CurrentStatus != SplashScreen.Status.NotReady)
                {
                    screens[i].Update(gt);
                    if (KState.Clicked(skipButton)) screens[i].End();
                    break;
                }
            }
        }

        public void Draw(SpriteBatch sp)
        {
            for (int i = 0; i < screens.Count(); i++)
            {
                if (screens[i].CurrentStatus != SplashScreen.Status.NotReady)
                {
                    screens[i].Draw(sp);
                    break;
                }
            }
        }
    }
}

使用方法:

protected override void LoadContent()
        {
            //SPLASH SCREEN
            ssm = new SplashScreenManager(@"Splash\Pictures", 3, 1, 3, Keys.Space);
        }

protected override void Update(GameTime gameTime)
        {
            if (currentGameState == GameState.Initialize)
            {
                ssm.Update(gameTime);
                if (!ssm.Running)
                    currentGameState = GameState.Menu;
            }
        }

protected override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Color.DeepSkyBlue);

            switch (currentGameState)
            {
                case GameState.Initialize:
                    spriteBatch.Begin();
                    ssm.Draw(spriteBatch);
                    spriteBatch.End();
                    break;
            }
        }

SplashScreenManager构造函数的注释:GContent.Textures(path);的目标是尝试加载该文件夹中的所有图像。此功能如下所示:

public static           List<Texture2D>     Textures(string folderPath)
{
    if (!folderPath.StartsWith(@"\")) folderPath = @"\" + folderPath;
    List<string> paths = Directory.GetFiles(Help.RootDir(Content.RootDirectory) + folderPath).ToList();
    List<Texture2D> images = new List<Texture2D>();
    foreach (string s in paths)
    {
        if (s.EndsWith(".xnb"))
            images.Add(Texture(s.Replace(Content.RootDirectory, "").Replace(".xnb", "")));
    }
    return images;
}

同样,Help.RootDir只返回根目录,如下所示:

public static string RootDir(string s)
{
    return s.Substring(0, s.LastIndexOf(@"\"));
}

这样您就可以将所有启动图像放在一个文件夹中。 Offcorse,由您决定如何管理资源。这是一个非常简单的方法,具有一些很棒的功能。尝试在后台使用旧的sony play station声音进行测试,并将这些参数用于SSM:ssm = new SplashScreenManager(your list of splash images, 3, 1, 3)。看起来和听起来很棒。竖起大拇指,如果这对你有所帮助!

编辑:

我没有告诉你如何在比赛开始时玩这个。使用枚举来定义您的游戏状态,使用单个变量来存储该信息,如下所示:

public enum GameState
{
    Initialize,
    Menu,
    Level,
    MapMaker
}
public GameState currentGameState = GameState.Initialize;

在游戏开始时,设置currentGameState = GameState.Initialize;,加载ssm,并在更新中检查ssm(启动画面管理器)是否已结束播放。如果有,请将currentGameState更改为GameState.Menu,并在switch方法中使用Update功能,以便了解您当前所处的游戏状态,这样您就知道了什么更新。你在上面的代码中有这样的例子,但我没有写过这个,这就是这个编辑的原因。