472 lines
18 KiB
C#
472 lines
18 KiB
C#
#region license
|
||
// This file is part of Vocaluxe.
|
||
//
|
||
// Vocaluxe is free software: you can redistribute it and/or modify
|
||
// it under the terms of the GNU General Public License as published by
|
||
// the Free Software Foundation, either version 3 of the License, or
|
||
// (at your option) any later version.
|
||
//
|
||
// Vocaluxe is distributed in the hope that it will be useful,
|
||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
// GNU General Public License for more details.
|
||
//
|
||
// You should have received a copy of the GNU General Public License
|
||
// along with Vocaluxe. If not, see <http://www.gnu.org/licenses/>.
|
||
#endregion
|
||
|
||
using System;
|
||
using System.Collections.Generic;
|
||
using System.Diagnostics;
|
||
using System.Windows.Forms;
|
||
using Vocaluxe.Base;
|
||
using Vocaluxe.Base.Fonts;
|
||
using VocaluxeLib;
|
||
using VocaluxeLib.Draw;
|
||
using VocaluxeLib.Menu;
|
||
|
||
namespace Vocaluxe.Screens
|
||
{
|
||
enum EDirection
|
||
{
|
||
Left,
|
||
Right,
|
||
Up
|
||
}
|
||
|
||
class CCreditName
|
||
{
|
||
private readonly CStatic _Image;
|
||
private readonly CStatic _ImgDot;
|
||
private readonly CParticleEffect _Particle;
|
||
private readonly int _ParticleOffsetX;
|
||
private readonly int _ParticleOffsetY;
|
||
public EDirection Direction;
|
||
public float StartTimeUp;
|
||
|
||
public CCreditName(CStatic image, CStatic imgDot, CParticleEffect particle, int particleOffsetX, int particleOffsetY)
|
||
{
|
||
_Image = image;
|
||
_ImgDot = imgDot;
|
||
_Particle = particle;
|
||
_ParticleOffsetX = (int)Math.Round(particleOffsetX * image.Rect.W / image.Texture.OrigSize.Width - particle.Rect.W / 2);
|
||
_ParticleOffsetY = (int)Math.Round(particleOffsetY * image.Rect.H / image.Texture.OrigSize.Height - particle.Rect.H / 2);
|
||
Visible = true;
|
||
}
|
||
|
||
public float X
|
||
{
|
||
get { return _Image.X; }
|
||
set
|
||
{
|
||
_Image.X = value;
|
||
_ImgDot.X = value + _ParticleOffsetX;
|
||
_Particle.X = value + _ParticleOffsetX;
|
||
}
|
||
}
|
||
public float Y
|
||
{
|
||
get { return _Image.Rect.Y; }
|
||
set
|
||
{
|
||
_Image.Y = value;
|
||
_ImgDot.Y = value + _ParticleOffsetY;
|
||
_Particle.Y = value + _ParticleOffsetY;
|
||
}
|
||
}
|
||
|
||
public float W
|
||
{
|
||
get { return _Image.Rect.W; }
|
||
}
|
||
|
||
public float H
|
||
{
|
||
get { return _Image.Rect.H; }
|
||
}
|
||
|
||
public float Alpha
|
||
{
|
||
get { return _Image.Alpha; }
|
||
set
|
||
{
|
||
_Image.Alpha = value;
|
||
_ImgDot.Alpha = value;
|
||
}
|
||
}
|
||
|
||
public bool Visible
|
||
{
|
||
set
|
||
{
|
||
_Image.Visible = value;
|
||
_ImgDot.Visible = value;
|
||
_Particle.Visible = value;
|
||
}
|
||
get { return _Image.Visible; }
|
||
}
|
||
}
|
||
|
||
public class CScreenCredits : CMenu
|
||
{
|
||
// Version number for theme files. Increment it, if you've changed something on the theme files!
|
||
protected override int _ScreenVersion
|
||
{
|
||
get { return 1; }
|
||
}
|
||
|
||
private CStatic _Logo;
|
||
private CParticleEffect _StarsRed;
|
||
private CParticleEffect _StarsBlue;
|
||
private List<CCreditName> _CreditNames;
|
||
|
||
private Stopwatch _LogoTimer;
|
||
private Stopwatch _CreditsTimer;
|
||
private Stopwatch _TextTimer;
|
||
|
||
private List<string[]> _Paragraphs;
|
||
private List<CText> _ParagraphTexts;
|
||
|
||
private CTextureRef _TexLogo;
|
||
private CTextureRef _TexPerfectNoteStar;
|
||
|
||
private CTextureRef _TexRedDot;
|
||
private CTextureRef _TexBlueDot;
|
||
|
||
private CTextureRef _TexNameBrunzel;
|
||
private CTextureRef _TexNameDarkice;
|
||
private CTextureRef _TexNameFlokuep;
|
||
private CTextureRef _TexNameFlamefire;
|
||
private CTextureRef _TexNameLukeIam;
|
||
private CTextureRef _TexNameMesand;
|
||
private CTextureRef _TexNameBohning;
|
||
private CTextureRef _TexNameBabene03;
|
||
|
||
private SThemeBackground _BGTheme;
|
||
|
||
public override EMusicType CurrentMusicType
|
||
{
|
||
get { return EMusicType.None; }
|
||
}
|
||
|
||
public override void Init()
|
||
{
|
||
base.Init();
|
||
|
||
_LogoTimer = new Stopwatch();
|
||
_CreditsTimer = new Stopwatch();
|
||
_TextTimer = new Stopwatch();
|
||
|
||
//Text for last part of credits.
|
||
_ParagraphTexts = new List<CText>();
|
||
_Paragraphs = new List<string[]>();
|
||
|
||
string paragraph = "Inspired by the achievements of UltraStar Deluxe and its variants and pursuing the goal of making " +
|
||
"a good thing even better, we ended up rewriting the game from scratch. And a new implementation in a new " +
|
||
"programming language called for a new name - and VOCALUXE [ˈvoʊˈkəˈlʌks] it is!";
|
||
string[] words = paragraph.Split(new char[] {' '});
|
||
_Paragraphs.Add(words);
|
||
|
||
paragraph = "This first public version has already implemented many of the original features and it is fully " +
|
||
"compatible with all the song files in your existing song collection. The code design allows a much faster " +
|
||
"implementation of new features, thus the roadmap for the next few stable releases is packed and we expect much " +
|
||
"shorter release cycles than ever before. And, of course, our and your ideas may be the features of tomorrow.";
|
||
words = paragraph.Split(new char[] {' '});
|
||
_Paragraphs.Add(words);
|
||
|
||
paragraph = "We appreciate the feedback in the beta release phase and are, of course, always open for bug reports, " +
|
||
"suggestions for improvements and ideas for new features. We would also like to thank the translators who make " +
|
||
"Vocaluxe an international experience from the very beginning and all those diligent song makers out there - " +
|
||
"there's something for everyone in the huge collection of available songs! Last but not least, thanks to " +
|
||
"Kosal Sen's Philly Sans type used in the Vocaluxe Logo.";
|
||
words = paragraph.Split(new char[] {' '});
|
||
_Paragraphs.Add(words);
|
||
|
||
paragraph = "Go ahead and grab your mics, crank up your stereo, warm up your voice and get ready to sing to the best " +
|
||
"of your abilities!";
|
||
words = paragraph.Split(new char[] {' '});
|
||
_Paragraphs.Add(words);
|
||
|
||
_BGTheme.Type = EBackgroundTypes.Color;
|
||
_BGTheme.Color = new SThemeColor {Name = null, R = 0, G = 0.18f, B = 0.474f, A = 1};
|
||
}
|
||
|
||
public override void LoadTheme(string xmlPath)
|
||
{
|
||
bool ressourceOK = true;
|
||
//Vocaluxe-Logo
|
||
ressourceOK &= CDataBase.GetCreditsRessource("Logo_voc.png", ref _TexLogo);
|
||
|
||
//Little stars for logo
|
||
ressourceOK &= CDataBase.GetCreditsRessource("PerfectNoteStar.png", ref _TexPerfectNoteStar);
|
||
|
||
ressourceOK &= CDataBase.GetCreditsRessource("redDot.png", ref _TexRedDot);
|
||
ressourceOK &= CDataBase.GetCreditsRessource("blueDot.png", ref _TexBlueDot);
|
||
|
||
ressourceOK &= CDataBase.GetCreditsRessource("brunzel.png", ref _TexNameBrunzel);
|
||
ressourceOK &= CDataBase.GetCreditsRessource("Darkice.png", ref _TexNameDarkice);
|
||
ressourceOK &= CDataBase.GetCreditsRessource("flokuep.png", ref _TexNameFlokuep);
|
||
ressourceOK &= CDataBase.GetCreditsRessource("flamefire.png", ref _TexNameFlamefire);
|
||
ressourceOK &= CDataBase.GetCreditsRessource("lukeIam.png", ref _TexNameLukeIam);
|
||
ressourceOK &= CDataBase.GetCreditsRessource("bohning.png", ref _TexNameBohning);
|
||
ressourceOK &= CDataBase.GetCreditsRessource("mesand.png", ref _TexNameMesand);
|
||
ressourceOK &= CDataBase.GetCreditsRessource("babene03.png", ref _TexNameBabene03);
|
||
|
||
if (!ressourceOK)
|
||
CLog.LogError("Could not load all ressources!", true, true);
|
||
|
||
//Prepare Text
|
||
int lastY = 280;
|
||
foreach (string[] paragraph in _Paragraphs)
|
||
{
|
||
string line = "";
|
||
for (int e = 0; e < paragraph.Length; e++)
|
||
{
|
||
if (paragraph[e] == null)
|
||
continue;
|
||
string newLine = " " + paragraph[e];
|
||
CText text = GetNewText(75, lastY, -2, 25, -1, EAlignment.Left, EStyle.Bold, "Outline", new SColorF(1, 1, 1, 1), line);
|
||
text.Visible = false;
|
||
if (CFonts.GetTextBounds(text).Width < (CSettings.RenderW - 220))
|
||
{
|
||
line += newLine;
|
||
|
||
//Check if all words are used
|
||
if ((e + 1) == paragraph.Length)
|
||
{
|
||
text.Text = line;
|
||
_ParagraphTexts.Add(text);
|
||
line = "";
|
||
lastY += 40;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
_ParagraphTexts.Add(text);
|
||
line = newLine;
|
||
lastY += 27;
|
||
}
|
||
_AddText(text);
|
||
}
|
||
}
|
||
|
||
CBackground bg = new CBackground(_BGTheme, -1);
|
||
_AddBackground(bg);
|
||
|
||
//Vocaluxe-Logo
|
||
_Logo = GetNewStatic(_TexLogo, new SColorF(1, 1, 1, 1),
|
||
new SRectF((float)(CSettings.RenderW - _TexLogo.OrigSize.Width) / 2, -270, _TexLogo.OrigSize.Width, _TexLogo.OrigSize.Height, -2));
|
||
_AddStatic(_Logo);
|
||
|
||
//Little stars for logo
|
||
var numstars = (int)(_Logo.Rect.W * 0.25f / 2f);
|
||
var partRect = new SRectF(_Logo.Rect.X, _Logo.Rect.Y, _Logo.Rect.W, _Logo.Rect.H, -1);
|
||
_StarsRed = _GetStarParticles(numstars, true, partRect, true);
|
||
_StarsBlue = _GetStarParticles(numstars, false, partRect, true);
|
||
_AddParticleEffect(_StarsRed);
|
||
_AddParticleEffect(_StarsBlue);
|
||
|
||
//Credit names
|
||
_CreditNames = new List<CCreditName>();
|
||
|
||
_AddNewCreditName(_TexNameBrunzel, 502, 29, true);
|
||
_AddNewCreditName(_TexNameDarkice, 360, 55, true);
|
||
_AddNewCreditName(_TexNameFlokuep, 214, 14, true);
|
||
_AddNewCreditName(_TexNameFlamefire, 496, 46, true);
|
||
_AddNewCreditName(_TexNameLukeIam, 411, 26, true);
|
||
_AddNewCreditName(_TexNameBohning, 383, 54, false);
|
||
_AddNewCreditName(_TexNameMesand, 525, 13, false);
|
||
_AddNewCreditName(_TexNameBabene03, 33, 26, false);
|
||
}
|
||
|
||
public override void ReloadTheme(string xmlPath) {}
|
||
|
||
public override void SaveTheme() {}
|
||
|
||
public override void UnloadSkin() {}
|
||
|
||
public override void ReloadSkin() {}
|
||
|
||
public override bool HandleInput(SKeyEvent keyEvent)
|
||
{
|
||
if (!keyEvent.KeyPressed || Char.IsControl(keyEvent.Unicode))
|
||
{
|
||
switch (keyEvent.Key)
|
||
{
|
||
case Keys.Escape:
|
||
case Keys.Back:
|
||
case Keys.Enter:
|
||
CGraphics.FadeTo(EScreen.Main);
|
||
break;
|
||
}
|
||
}
|
||
|
||
return true;
|
||
}
|
||
|
||
public override bool HandleMouse(SMouseEvent mouseEvent)
|
||
{
|
||
if (mouseEvent.LB || mouseEvent.RB)
|
||
CGraphics.FadeTo(EScreen.Main);
|
||
return true;
|
||
}
|
||
|
||
public override bool UpdateGame()
|
||
{
|
||
if (!_Animation() && CGraphics.NextScreen != CGraphics.GetScreen(EScreen.Main))
|
||
CGraphics.FadeTo(EScreen.Main);
|
||
return true;
|
||
}
|
||
|
||
private CParticleEffect _GetStarParticles(int numStars, bool isRed, SRectF rect, bool bigParticles)
|
||
{
|
||
SColorF partColor = isRed ? new SColorF(1, 0, 0, 1) : new SColorF(0.149f, 0.415f, 0.819f, 1);
|
||
int partSize = bigParticles ? 35 : 25;
|
||
return GetNewParticleEffect(numStars, partColor, rect, _TexPerfectNoteStar, partSize, EParticleType.Star);
|
||
}
|
||
|
||
private void _AddNewCreditName(CTextureRef texture, int particleOffsetX, int particleOffsetY, bool bigParticles)
|
||
{
|
||
bool isRed = _CreditNames.Count % 2 == 0;
|
||
int partRectSize = bigParticles ? 25 : 20;
|
||
int partCount = bigParticles ? 8 : 6;
|
||
CTextureRef texDot = isRed ? _TexRedDot : _TexBlueDot;
|
||
|
||
CStatic image = GetNewStatic(texture, new SColorF(1, 1, 1, 1), new SRectF(-1, -1, 400, 120, -4));
|
||
|
||
var particleRect = new SRectF(-1, -1, partRectSize, partRectSize, -6);
|
||
SRectF imgDotRect = particleRect;
|
||
imgDotRect.Z = -5;
|
||
CStatic imgDot = GetNewStatic(texDot, new SColorF(1, 1, 1, 1), imgDotRect);
|
||
CParticleEffect particle = _GetStarParticles(partCount, isRed, particleRect, bigParticles);
|
||
|
||
var credit = new CCreditName(image, imgDot, particle, particleOffsetX, particleOffsetY);
|
||
|
||
_CreditNames.Add(credit);
|
||
_AddStatic(image);
|
||
_AddStatic(imgDot);
|
||
_AddParticleEffect(particle);
|
||
}
|
||
|
||
public override void OnShow()
|
||
{
|
||
base.OnShow();
|
||
|
||
foreach (CText text in _ParagraphTexts)
|
||
text.Visible = false;
|
||
bool isRight = true;
|
||
foreach (CCreditName name in _CreditNames)
|
||
{
|
||
name.Visible = true;
|
||
name.Direction = isRight ? EDirection.Right : EDirection.Left;
|
||
name.X = -name.W;
|
||
name.Y = 580;
|
||
name.Alpha = 1;
|
||
isRight = !isRight;
|
||
}
|
||
_Logo.Y = -270;
|
||
_StarsRed.Y = _Logo.Y;
|
||
_StarsBlue.Y = _Logo.Y;
|
||
|
||
_TextTimer.Reset();
|
||
_LogoTimer.Reset();
|
||
_CreditsTimer.Reset();
|
||
}
|
||
|
||
public override void OnShowFinish()
|
||
{
|
||
base.OnShowFinish();
|
||
|
||
_LogoTimer.Start();
|
||
}
|
||
|
||
private bool _Animation()
|
||
{
|
||
bool active = false;
|
||
if (_LogoTimer.IsRunning)
|
||
{
|
||
active = true;
|
||
|
||
_Logo.Y = -270 + (270f / 3000f) * _LogoTimer.ElapsedMilliseconds;
|
||
_StarsRed.Y = _Logo.Y;
|
||
_StarsBlue.Y = _Logo.Y;
|
||
if (_LogoTimer.ElapsedMilliseconds >= 2000 && !_CreditsTimer.IsRunning)
|
||
_CreditsTimer.Start();
|
||
if (_LogoTimer.ElapsedMilliseconds >= 3000)
|
||
_LogoTimer.Stop();
|
||
}
|
||
|
||
if (_CreditsTimer.IsRunning)
|
||
{
|
||
active = true;
|
||
|
||
for (int i = 0; i < _CreditNames.Count; i++)
|
||
{
|
||
if (!_CreditNames[i].Visible)
|
||
continue;
|
||
switch (_CreditNames[i].Direction)
|
||
{
|
||
case EDirection.Right:
|
||
if (i * 4000f <= _CreditsTimer.ElapsedMilliseconds)
|
||
{
|
||
_CreditNames[i].X = -450 + (((CSettings.RenderW - _CreditNames[i].W) / 2) / 3000f) * (_CreditsTimer.ElapsedMilliseconds - (i * 4000f));
|
||
|
||
//Check if name is in middle of screen and should go up
|
||
if (_CreditNames[i].X >= (CSettings.RenderW - _CreditNames[i].W) / 2)
|
||
{
|
||
_CreditNames[i].Direction = EDirection.Up;
|
||
_CreditNames[i].StartTimeUp = _CreditsTimer.ElapsedMilliseconds;
|
||
}
|
||
}
|
||
break;
|
||
|
||
case EDirection.Left:
|
||
if (i * 4000f <= _CreditsTimer.ElapsedMilliseconds)
|
||
{
|
||
_CreditNames[i].X = CSettings.RenderW -
|
||
(((CSettings.RenderW - _CreditNames[i].W) / 2) / 3000f) * (_CreditsTimer.ElapsedMilliseconds - (i * 4000f));
|
||
|
||
//Check if name is in middle of screen and should go up
|
||
if (_CreditNames[i].X <= (CSettings.RenderW - _CreditNames[i].W) / 2)
|
||
{
|
||
_CreditNames[i].Direction = EDirection.Up;
|
||
_CreditNames[i].StartTimeUp = _CreditsTimer.ElapsedMilliseconds;
|
||
}
|
||
}
|
||
break;
|
||
|
||
case EDirection.Up:
|
||
_CreditNames[i].Y = 580 - (430f / 3000f) * (_CreditsTimer.ElapsedMilliseconds - _CreditNames[i].StartTimeUp);
|
||
|
||
//Set name inactive
|
||
if (_CreditNames[i].Y <= 160f)
|
||
{
|
||
_CreditNames[i].Visible = false;
|
||
//Check, if last name is shown
|
||
if (i == _CreditNames.Count - 1)
|
||
{
|
||
_CreditsTimer.Stop();
|
||
_TextTimer.Start();
|
||
foreach (CText text in _ParagraphTexts)
|
||
text.Visible = true;
|
||
}
|
||
}
|
||
else if (_CreditNames[i].Y <= 360f)
|
||
{
|
||
//Fade names out
|
||
float alpha = ((360 - _CreditNames[i].Y) / 200).Clamp(0, 1);
|
||
_CreditNames[i].Alpha = 1 - alpha;
|
||
}
|
||
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|
||
if (_TextTimer.IsRunning)
|
||
active = _TextTimer.ElapsedMilliseconds <= 500;
|
||
|
||
return active;
|
||
}
|
||
}
|
||
} |