Loading screen between world setup and the game scene
World generation (WorldScene.OnLoad: terrain, atlases, spawn) runs synchronously and blocks the frame; previously only a blank fade covered it, with no feedback. New WorldLoadingScene shows a "Generating world" label, lets it draw, then switches to WorldScene WITHOUT a transition so its last drawn frame (the label) stays on screen during the blocking generation. Both New World and Load Game route through it. Localized loading.world ru/en. Build + --check-content clean. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
282ec018f7
commit
6ec70cab91
@@ -92,6 +92,7 @@
|
|||||||
"menu.settings": "Settings",
|
"menu.settings": "Settings",
|
||||||
"menu.credits": "Credits",
|
"menu.credits": "Credits",
|
||||||
"menu.quit": "Quit",
|
"menu.quit": "Quit",
|
||||||
|
"loading.world": "Generating world",
|
||||||
"newworld.title": "New World",
|
"newworld.title": "New World",
|
||||||
"newworld.name": "Name",
|
"newworld.name": "Name",
|
||||||
"newworld.defaultname": "New World",
|
"newworld.defaultname": "New World",
|
||||||
|
|||||||
@@ -92,6 +92,7 @@
|
|||||||
"menu.settings": "Настройки",
|
"menu.settings": "Настройки",
|
||||||
"menu.credits": "Авторы",
|
"menu.credits": "Авторы",
|
||||||
"menu.quit": "Выход",
|
"menu.quit": "Выход",
|
||||||
|
"loading.world": "Создание мира",
|
||||||
"newworld.title": "Новый мир",
|
"newworld.title": "Новый мир",
|
||||||
"newworld.name": "Название",
|
"newworld.name": "Название",
|
||||||
"newworld.defaultname": "Новый мир",
|
"newworld.defaultname": "Новый мир",
|
||||||
|
|||||||
@@ -73,7 +73,7 @@ public sealed class LoadGameScene : Scene
|
|||||||
if (!Context.Scenes.IsTransitioning)
|
if (!Context.Scenes.IsTransitioning)
|
||||||
{
|
{
|
||||||
Context.Scenes.Switch(
|
Context.Scenes.Switch(
|
||||||
new WorldScene(save.ToConfig(), save),
|
new WorldLoadingScene(save.ToConfig(), save),
|
||||||
Transitions.Fade(0.6f)
|
Transitions.Fade(0.6f)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -154,7 +154,7 @@ public sealed class NewWorldScene : Scene
|
|||||||
Seed = seed,
|
Seed = seed,
|
||||||
SmoothPasses = _smoothing,
|
SmoothPasses = _smoothing,
|
||||||
};
|
};
|
||||||
Context.Scenes.Switch(new WorldScene(config), Transitions.Fade(0.6f));
|
Context.Scenes.Switch(new WorldLoadingScene(config), Transitions.Fade(0.6f));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Back()
|
private void Back()
|
||||||
|
|||||||
@@ -0,0 +1,63 @@
|
|||||||
|
using LittleSim.App;
|
||||||
|
using LittleSim.Content;
|
||||||
|
using LittleSim.UI;
|
||||||
|
using MrGameEng.Core;
|
||||||
|
using MrGameEng.UI;
|
||||||
|
using Myra.Graphics2D.UI;
|
||||||
|
|
||||||
|
namespace LittleSim.Scenes;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Экран загрузки между окном создания/выбора мира и игровой сценой. Генерация мира
|
||||||
|
/// (<see cref="WorldScene.OnLoad"/>: рельеф, атласы, спавн) идёт синхронно и блокирует кадр; раньше под
|
||||||
|
/// ней был лишь сплошной фейд без индикатора. Эта сцена рисует надпись «Создание мира…», даёт ей
|
||||||
|
/// прорисоваться, затем переключается на <see cref="WorldScene"/> БЕЗ перехода — её последний кадр
|
||||||
|
/// (надпись) и остаётся на экране, пока идёт генерация, давая игроку понятную обратную связь.
|
||||||
|
/// </summary>
|
||||||
|
public sealed class WorldLoadingScene : Scene
|
||||||
|
{
|
||||||
|
private readonly WorldConfig _config;
|
||||||
|
private readonly WorldSave? _save;
|
||||||
|
private GameSettings _settings = new();
|
||||||
|
private Label _label = null!;
|
||||||
|
private int _frames;
|
||||||
|
|
||||||
|
/// <summary>Новый мир (<paramref name="save"/> = null) или загрузка сохранения.</summary>
|
||||||
|
public WorldLoadingScene(WorldConfig config, WorldSave? save = null)
|
||||||
|
{
|
||||||
|
_config = config;
|
||||||
|
_save = save;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnLoad()
|
||||||
|
{
|
||||||
|
_settings = GameSettingsStore.Load();
|
||||||
|
var desktop = this.UseScaledUI(); // ставит MyraEnvironment.Game до создания виджетов
|
||||||
|
_label = new Label
|
||||||
|
{
|
||||||
|
TextColor = Ui.Accent,
|
||||||
|
HorizontalAlignment = HorizontalAlignment.Center,
|
||||||
|
VerticalAlignment = VerticalAlignment.Center,
|
||||||
|
};
|
||||||
|
desktop.Root = Ui.Screen(_label);
|
||||||
|
UpdateSystems.Add(new CallbackSystem(Tick));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Tick()
|
||||||
|
{
|
||||||
|
var content = Context.Services.Get<GameContent>();
|
||||||
|
var word = content.Languages.Get("loading.world");
|
||||||
|
var dots = new string('.', (int)(Context.Clock.UnscaledTotalTime * 2) % 4);
|
||||||
|
_label.Text = word + dots;
|
||||||
|
|
||||||
|
// Дождаться, пока надпись точно прорисована (переход въезда завершён + пара кадров), затем
|
||||||
|
// мгновенно переключиться: блокирующий WorldScene.OnLoad оставит на экране кадр с надписью.
|
||||||
|
_frames++;
|
||||||
|
if (Context.Scenes.IsTransitioning || _frames < 2)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Context.Scenes.Switch(new WorldScene(_config, _save));
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user