// Copyright (c) .NET Foundation and Contributors (https://dotnetfoundation.org/ & https://stride3d.net) and Silicon Studio Corp. (https://www.siliconstudio.co.jp)
// Distributed under the MIT license. See the LICENSE.md file in the project root for more information.
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Stride.Core.Mathematics;
using Stride.Engine;
using Stride.Graphics;
using Stride.Rendering.Sprites;
using Stride.UI;
using Stride.UI.Controls;
using Stride.UI.Panels;
namespace GameMenu
{
///
/// Script controller for the main scene.
///
public class MainScript : UISceneBase
{
///
/// Default player name.
///
private const string DefaultName = "John Doe";
private const int MaximumStar = 3;
private static readonly List ShipNameList = new List
{
"red_ship", "green_ship", "blue_ship", "blue_ship", "yellow_ship", "yellow_ship", "cyan_ship"
};
private readonly List shipList = new List();
private int money;
private int bonus;
private int lifeStatus;
private int powerStatus;
private int controlStatus;
private int speedStatus;
private int activeShipIndex; // Current SpaceShip of the character
private readonly List starSpriteIndices = new List();
private readonly List borderStarSpriteIndices = new List();
#region Visuals
private UIPage page;
private ModalElement shipSelectPopup; // Root of SpaceShip select popup
private ModalElement welcomePopup; // Root of welcome popup
// Life gauge
private RectangleF gaugeBarRegion;
private Grid lifebarGrid;
private Sprite lifebarGaugeImage;
// Counters
private TextBlock bonusCounter;
private TextBlock lifeCounter;
private TextBlock moneyCounter;
// Name of the character
private TextBlock nameTextBlock;
private ImageElement currentShipImage;
// Status stars
private ImageElement controlStatusStar;
private ImageElement powerStatusStar;
private ImageElement speedStatusStar;
#endregion // Visuals
///
/// Spritesheet containing the sprites of the main scene.
///
public SpriteSheet MainSceneImages { get; set; }
///
/// UI library containing the modal popups and the ship button template.
///
public UILibrary UILibrary { get; set; }
private int Bonus
{
set
{
bonus = value;
bonusCounter.Text = CreateBonusCountText();
}
get { return bonus; }
}
private int ControlStatus
{
get { return controlStatus; }
set
{
if (value > MaximumStar) return;
controlStatus = value;
((SpriteFromSheet)controlStatusStar.Source).CurrentFrame = starSpriteIndices[controlStatus];
shipList[activeShipIndex].Control = controlStatus;
}
}
private int LifeStatus
{
get { return lifeStatus; }
set
{
lifeStatus = value;
lifeCounter.Text = CreateLifeCountText();
}
}
private int PowerStatus
{
get { return powerStatus; }
set
{
if (value > MaximumStar) return;
powerStatus = value;
((SpriteFromSheet)powerStatusStar.Source).CurrentFrame = starSpriteIndices[powerStatus];
shipList[activeShipIndex].Power = powerStatus;
}
}
private int SpeedStatus
{
get { return speedStatus; }
set
{
if (value > MaximumStar) return;
speedStatus = value;
((SpriteFromSheet)speedStatusStar.Source).CurrentFrame = starSpriteIndices[speedStatus];
shipList[activeShipIndex].Speed = speedStatus;
}
}
private int Money
{
get { return money; }
set
{
money = value;
moneyCounter.Text = CreateMoneyCountText();
}
}
public override void Start()
{
base.Start();
ShowWelcomePopup();
}
protected override void LoadScene()
{
// Preload stars
starSpriteIndices.Add(MainSceneImages.FindImageIndex("star0"));
starSpriteIndices.Add(MainSceneImages.FindImageIndex("star1"));
starSpriteIndices.Add(MainSceneImages.FindImageIndex("star2"));
starSpriteIndices.Add(MainSceneImages.FindImageIndex("star3"));
borderStarSpriteIndices.Add(MainSceneImages.FindImageIndex("bstar0"));
borderStarSpriteIndices.Add(MainSceneImages.FindImageIndex("bstar1"));
borderStarSpriteIndices.Add(MainSceneImages.FindImageIndex("bstar2"));
borderStarSpriteIndices.Add(MainSceneImages.FindImageIndex("bstar3"));
// Create space ships
var random = new Random();
for (var i = 0; i < ShipNameList.Count; i++)
{
shipList.Add(new SpaceShip
{
Name = ShipNameList[i],
Power = random.Next(MaximumStar + 1),
Control = random.Next(MaximumStar + 1),
Speed = random.Next(MaximumStar + 1),
IsLocked = (i % 3) == 2,
});
}
// Initialize UI
page = Entity.Get().Page;
InitializeMainPage();
InitializeShipSelectionPopup();
InitializeWelcomePopup();
// Add pop-ups to the overlay
var overlay = (UniformGrid) page.RootElement;
overlay.Children.Add(shipSelectPopup);
overlay.Children.Add(welcomePopup);
Script.AddTask(FillLifeBar);
}
private async Task FillLifeBar()
{
var gaugePercentage = 0.15f;
while (gaugePercentage < 1f)
{
await Script.NextFrame();
gaugePercentage = Math.Min(1f, gaugePercentage + (float)Game.UpdateTime.Elapsed.TotalSeconds * 0.02f);
var gaugeCurrentRegion = lifebarGaugeImage.Region;
gaugeCurrentRegion.Width = gaugePercentage * gaugeBarRegion.Width;
lifebarGaugeImage.Region = gaugeCurrentRegion;
lifebarGrid.ColumnDefinitions[1].SizeValue = gaugeCurrentRegion.Width / gaugeBarRegion.Width;
lifebarGrid.ColumnDefinitions[2].SizeValue = 1 - lifebarGrid.ColumnDefinitions[1].SizeValue;
}
}
private bool CanPurchase(int requireMoney, int requireBonus)
{
return Money >= requireMoney && Bonus >= requireBonus;
}
private void CloseShipSelectPopup()
{
shipSelectPopup.Visibility = Visibility.Collapsed;
}
private void CloseWelcomePopup()
{
welcomePopup.Visibility = Visibility.Collapsed;
}
private string CreateBonusCountText()
{
return bonus.ToString("D3");
}
private string CreateLifeCountText()
{
return "x" + lifeStatus;
}
private string CreateMoneyCountText()
{
return money.ToString("D3");
}
private UIElement CreateShipSelectionItem(SpaceShip spaceShip)
{
var shipPanel = UILibrary.InstantiateElement("ShipButton");
var shipButton = shipPanel.FindVisualChildOfType("shipButton");
var shipImage = shipButton.FindVisualChildOfType("shipImage");
// Update spaceship
spaceShip.PowerImageElement = shipButton.FindVisualChildOfType("powerImage");
spaceShip.ControlImageElement = shipButton.FindVisualChildOfType("controlImage");
spaceShip.SpeedImageElement = shipButton.FindVisualChildOfType("speedImage");
var shipIndex = MainSceneImages.FindImageIndex(spaceShip.Name);
((SpriteFromSheet) shipImage.Source).CurrentFrame = shipIndex;
shipButton.Click += delegate
{
activeShipIndex = shipList.FindIndex(w => w.Name == spaceShip.Name);
((SpriteFromSheet)currentShipImage.Source).CurrentFrame = shipIndex;
PowerStatus = spaceShip.Power;
ControlStatus = spaceShip.Control;
SpeedStatus = spaceShip.Speed;
CloseShipSelectPopup();
};
shipButton.IsEnabled = !spaceShip.IsLocked;
if (spaceShip.IsLocked)
{
var lockIconElement = shipPanel.FindVisualChildOfType("lockIcon");
lockIconElement.Visibility = Visibility.Visible;
}
return shipPanel;
}
private void InitializeMainPage()
{
var rootElement = page.RootElement;
// counters
bonusCounter = rootElement.FindVisualChildOfType("bonusCounter");
lifeCounter = rootElement.FindVisualChildOfType("lifeCounter");
moneyCounter = rootElement.FindVisualChildOfType("moneyCounter");
Bonus = 30;
LifeStatus = 3;
Money = 30;
// lifebar
lifebarGaugeImage = MainSceneImages["life_bar"];
lifebarGrid = rootElement.FindVisualChildOfType("lifebarGrid");
gaugeBarRegion = lifebarGaugeImage.Region;
// character name
nameTextBlock = rootElement.FindVisualChildOfType("nameTextBlock");
// explanation
// FIXME: UI asset should support multiline text
var explanationText = rootElement.FindVisualChildOfType("explanationText");
explanationText.Text = "Pictogram-based alphabets are easily supported.\n日本語も簡単に入れることが出来ます。";
// status stars
var statusPanel = rootElement.FindVisualChildOfType("statusPanel");
powerStatusStar = statusPanel.FindVisualChildOfType("powerStatusStar");
controlStatusStar = statusPanel.FindVisualChildOfType("controlStatusStar");
speedStatusStar = statusPanel.FindVisualChildOfType("speedStatusStar");
PowerStatus = shipList[activeShipIndex].Power;
ControlStatus = shipList[activeShipIndex].Control;
SpeedStatus = shipList[activeShipIndex].Speed;
// ship selection
var currentShipButton = rootElement.FindVisualChildOfType