我想创建什么
所以我正在使用Monogame构建2D冒险游戏,在游戏开始时,我想使用显示之前故事情节的 3张图片,有点像介绍切割场景,所以每张图片都显示了导致故事在游戏中开始的地方的不同快照。
我希望它如何运作
我希望它只是显示1个图像,然后被第二个图像重叠,然后是第三个图像,每个图像之间有一个约3秒的暂停(根本没有关注过渡)。
我向所有读者提出的问题
我想知道,实现这一目标的最佳方法是什么,以便在游戏开始时开始?我正在考虑在像Pro Pro这样的场景上制作剪辑场景,它只是一个播放的视频,但是我不确定是否有更好的选择。 我只想知道实现此类目标的最简单方法。
答案 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
功能,以便了解您当前所处的游戏状态,这样您就知道了什么更新。你在上面的代码中有这样的例子,但我没有写过这个,这就是这个编辑的原因。