// Project: XnaGraphicEngine, File: Highscores.cs // Namespace: XnaGraphicEngine.GameScreens, Class: Highscores // Path: C:\code\XnaGraphicEngine\GameScreens, Author: Abi // Code lines: 46, Size of file: 863 Bytes // Creation date: 01.11.2005 23:55 // Last modified: 17.03.2006 03:34 // Generated with Commenter by abi.exDream.com #region Using directives using System; using System.Collections.Generic; using System.Text; using System.IO; using System.Globalization; using System.Threading; using System.Diagnostics; using System.Runtime.Serialization; using XnaGraphicEngine.Helpers; using XnaGraphicEngine.Graphics; using XnaGraphicEngine.Properties; using XnaGraphicEngine.Game; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; #endregion namespace XnaGraphicEngine.GameScreens { /// /// Highscores /// class Highscores : IGameScreen { #region Variables /// /// Highscore modes /// private enum HighscoreModes { Local, //ohs: OnlineThisHour, //OnlineTotal, } // enum HighscoreModes /// /// Current highscore mode, initially set to local. /// private HighscoreModes highscoreMode = HighscoreModes.Local; #endregion #region Properties /// /// Name of this game screen /// /// String public string Name { get { return "Highscores"; } // get } // Name private bool quit = false; /// /// Returns true if we want to quit this screen and return to the /// previous screen. If no more screens are left the game is exited. /// /// Bool public bool Quit { get { return quit; } // get } // Quit #endregion #region Highscore helper class /// /// Highscore helper class /// private struct Highscore { /// /// Player name /// public string name; /// /// Level name /// public string level; /// /// Highscore points /// public int points; /// /// Create highscore /// /// Set name /// Set level name /// Set points public Highscore(string setName, string setLevelName, int setPoints) { name = setName; level = setLevelName; points = setPoints; } // Highscore(setName, setLevelName, setPoints) /// /// To string /// /// String public override string ToString() { return name + ":" + level + ":" + points; } // ToString() } // struct Highscore /// /// Number of highscores displayed in this screen. /// private const int NumOfHighscores = 10; /// /// List of remembered highscores. /// private static Highscore[] highscores = new Highscore[NumOfHighscores]; /// /// Get top highscore, displayed in the upper right when playing. /// public static int TopHighscore { get { return highscores[0].points; } // get } // TopHighscore /// /// Write highscores to string. Used to save to settings. /// private static void WriteHighscoresToSettings() { GameSettings.Default.Highscores = StringHelper.WriteArrayData(highscores); } // WriteHighscoresToSettings() /// /// Read highscores from settings /// /// True if reading succeeded, false otherwise. private static bool ReadHighscoresFromSettings() { if (String.IsNullOrEmpty(GameSettings.Default.Highscores)) return false; try { string[] allHighscores = GameSettings.Default.Highscores.Split( new char[] { ',' }); for (int num = 0; num < allHighscores.Length && num < highscores.Length; num++) { string[] oneHighscore = StringHelper.SplitAndTrim(allHighscores[num], ':'); highscores[num] = new Highscore( oneHighscore[0], oneHighscore[1], Convert.ToInt32(oneHighscore[2])); } // for (num) return true; } // try catch (Exception ex) { Log.Write("Failed to load highscores: " + ex.ToString()); return false; } // catch } // ReadHighscoresFromSettings() #endregion #region Generate hash from file for sending value to online server /*obs /// /// Generate hash from file /// /// Filename private static byte[] GenerateHashFromFile(string filename) { FileStream file = File.OpenRead(filename); byte[] readData = new byte[file.Length]; file.Read(readData, 0, (int)file.Length); file.Close(); SHA1Managed shaHash = new SHA1Managed(); return shaHash.ComputeHash(readData); } // GenerateHashFromFile(filename) /// /// Precalculated game file hash of "Rocket Commander.exe" /// static byte[] gameFileHash = null; */ #endregion #region Static constructor /// /// Default level name /// public static string DefaultLevelName = "Apocalypse"; /// /// Create Highscores class, will basically try to load highscore list, /// if that fails we generate a standard highscore list! /// static Highscores() { //obs: gameFileHash = GenerateHashFromFile("Rocket Commander.exe"); if (ReadHighscoresFromSettings() == false) { // Generate default list highscores[9] = new Highscore("Newbie", DefaultLevelName, 0); highscores[8] = new Highscore("Desert-Fox", DefaultLevelName, 5000); highscores[7] = new Highscore("Waii", DefaultLevelName, 10000); highscores[6] = new Highscore("ViperDK", DefaultLevelName, 15000); highscores[5] = new Highscore("Netfreak", DefaultLevelName, 20000); highscores[4] = new Highscore("Judge", DefaultLevelName, 25000); highscores[3] = new Highscore("exDreamBoy", DefaultLevelName, 30000); highscores[2] = new Highscore("Master_L", DefaultLevelName, 35000); highscores[1] = new Highscore("Freshman", DefaultLevelName, 40000); highscores[0] = new Highscore("abi", DefaultLevelName, 45000); WriteHighscoresToSettings(); } // if } // Highscores() #endregion #region Constructor /// /// Create highscores /// public Highscores() { } // Highscores() #endregion #region Get rank from current score /// /// Get rank from current score. /// Used in game to determinate rank while flying around ^^ /// /// Score /// Int public static int GetRankFromCurrentScore(int score) { // Just compare with all highscores and return the rank we have reached. for (int num = 0; num < highscores.Length; num++) { if (score >= highscores[num].points) return num; } // for (num) // No Rank found, use rank 11 return highscores.Length; } // GetRankFromCurrentScore(score) #endregion #region Submit highscore after game //obs: static bool onlineUploadHighscoreFailedAlreadyLogged = false; /// /// Submit highscore. Done after each game is over (won or lost). /// New highscore will be added to the highscore screen and send /// to the online server. /// /// Score /// Level name public static void SubmitHighscore(int score, string levelName) { // Search which highscore rank we can replace for (int num = 0; num < highscores.Length; num++) { if (score >= highscores[num].points) { // Move all highscores up for (int moveUpNum = highscores.Length - 1; moveUpNum > num; moveUpNum--) { highscores[moveUpNum] = highscores[moveUpNum - 1]; } // for (moveUpNum) // Add this highscore into the local highscore table highscores[num].name = GameSettings.Default.PlayerName; highscores[num].level = levelName; highscores[num].points = score; // And save that Highscores.WriteHighscoresToSettings(); break; } // if } // for (num) // Else no highscore was reached, we can't replace any rank. /*can't do on the Xbox 360! // Upload highscore to server with help of the webservice :) // Do this asyncronly, it could take a while and we don't want to wait // for it to complete (there is no return value anyway). new Thread(new ThreadStart( // Anoymous delegates, isn't .NET 2.0 great? ^^ delegate { // Note: We could also use UploadHighscoreAsync, this does help, // BUT the webservice class still needs to be created and that // does take a little while too (0.5 secs sometimes). // For this reason we let everything execute asyncronly in // this thread. This has also the benefit allowing us to // check if something failed (e.g. timeout, not online, etc.) try { //tst: Log.Write("Start uploading score"); string ret = new www.RocketCommander.com. XnaGraphicEngineService().UploadHighscore( gameFileHash, Options.currentPlayerName, score, levelName, GenerateHashFromFile(Directories.LevelsDirectory + "\\" + levelName + ".png")); //tst: Log.Write("Finished uploading score: " + ret); } // try catch (Exception ex) { // Only log this once if (onlineUploadHighscoreFailedAlreadyLogged == false) { onlineUploadHighscoreFailedAlreadyLogged = true; Log.Write("Failed to upload highscore to online server. " + "Error message: " + ex.ToString()); } // if } // catch })).Start(); */ } // SubmitHighscore(score) #endregion #region Get online highscores Highscore[] onlineHighscores = new Highscore[10]; //obs: Thread onlineGetHighscoreThread = null; /// /// Get online highscores /// /// Only this hour private void GetOnlineHighscores(bool onlyThisHour) { // Clear all online highscores and wait for a new update! for (int num = 0; num < onlineHighscores.Length; num++) { onlineHighscores[num].name = "-"; onlineHighscores[num].level = ""; onlineHighscores[num].points = 0; } // for (num) /*obs // Stop any old threads if (onlineGetHighscoreThread != null) onlineGetHighscoreThread.Abort(); // Ask web service for highscore list! Do this asyncronly, // it could take a while and we don't want to wait for it to complete. onlineGetHighscoreThread = new Thread(new ThreadStart( // Anoymous delegates, isn't .NET 2.0 great? ^^ delegate { // See notes above try { string ret = new www.RocketCommander.com. XnaGraphicEngineService().GetTop10Highscores( onlyThisHour); // Now split this up and build the online highscore with it. string[] allHighscores = ret.Split(new char[] { ',' }); for (int num = 0; num < allHighscores.Length && num < onlineHighscores.Length; num++) { string[] oneHighscore = allHighscores[num].Split(new char[] { ':' }); onlineHighscores[num] = new Highscore( oneHighscore[0].Trim(), oneHighscore[2], Convert.ToInt32(oneHighscore[1])); } // for (num) } // try #if DEBUG catch (Exception ex) { Log.Write("Online highscores failed: " + ex.ToString()); } // catch #else catch { } // ignore any exceptions! #endif })); onlineGetHighscoreThread.Start(); */ } // GetOnlineHighscores(onlyThisHour) #endregion #region Run /// /// Run game screen. Called each frame. /// /// Form for access to asteroid manager and co public void Run(YourGame game) { // Render background game.RenderMenuBackground(); // Show highscores, allow to select between local highscores, // online highscores this hour and online highscores best of all time. int xPos = 100 * BaseGame.Width / 1024; int yPos = 260 * BaseGame.Height / 768; TextureFont.WriteText(xPos, yPos, "Highscores:"); // Local Highscores Rectangle rect = new Rectangle( xPos + 210 * BaseGame.Width / 1024, yPos + 0 * BaseGame.Height / 768, 130, 28); bool highlighted = Input.MouseInBox(rect); TextureFont.WriteText(rect.X, rect.Y, "Local", highscoreMode == HighscoreModes.Local ? Color.Red : highlighted ? Color.LightSalmon : Color.White); if (highlighted && Input.MouseLeftButtonJustPressed) highscoreMode = HighscoreModes.Local; yPos = 310 * BaseGame.Height / 768; Highscore[] selectedHighscores = highscoreMode == HighscoreModes.Local ? highscores : onlineHighscores; for (int num = 0; num < NumOfHighscores; num++) { Color col = Input.MouseInBox(new Rectangle( xPos, yPos + num * 30, 600 + 200, 28)) ? Color.White : ColorHelper.FromArgb(200, 200, 200); TextureFont.WriteText(xPos, yPos + num * 29, (1 + num) + ".", col); TextureFont.WriteText(xPos + 50, yPos + num * 30, selectedHighscores[num].name, col); TextureFont.WriteText(xPos + 340, yPos + num * 30, "Score: " + selectedHighscores[num].points, col); TextureFont.WriteText(xPos + 610, yPos + num * 30, "Mission: " + selectedHighscores[num].level, col); } // for (num) if (game.RenderMenuButton(MenuButton.Back, new Point(1024 - 230, 768 - 150)) || Input.KeyboardEscapeJustPressed || Input.GamePadBackJustPressed) { quit = true; } // if } // Run(game) #endregion } // class Highscores } // namespace XnaGraphicEngine.GameScreens