将用户数据输出到文件XNA

时间:2012-11-27 01:51:07

标签: c# file-io xna

namespace highscores
{
    public class Game1 : Microsoft.Xna.Framework.Game
    {
        //Stuff for HighScoreData
        public struct HighScoreData
        {
            public string[] PlayerName;
            public int[] Score;

            public int Count;

            public HighScoreData(int count)
            {
                PlayerName = new string[count];
                Score = new int[count];

                Count = count;
            }
        }

        /* More score variables */
        HighScoreData data;
        public string HighScoresFilename = "highscores.dat";
        int PlayerScore = 0;
        string PlayerName;
        string scoreboard;
        string typedText = "";
        int score = 0;
        public static SpriteFont font;
        public static Texture2D textBoxTexture;
        public static Texture2D caretTexture;
        bool txt;

        // String for get name
        string cmdString = "Enter your player name and press Enter";
        // String we are going to display – initially an empty string
        string messageString = "";

        SpriteBatch spriteBatch;
        GraphicsDeviceManager graphics;
        KeyboardState oldKeyboardState;
        KeyboardState currentKeyboardState;
        private string textString;


        public Game1()
        {
            graphics = new GraphicsDeviceManager(this);
            Content.RootDirectory = "Content";

#if XBOX
            Components.Add(new GamerServicesComponent(this));
#endif

            currentKeyboardState = Keyboard.GetState();

        }

        /// <summary>
        /// Allows the game to perform any initialization it needs to before starting to run.
        /// This is where it can query for any required services and load any non-graphic
        /// related content.  Calling base.Initialize will enumerate through any components
        /// and initialize them as well.
        /// </summary>
        protected override void Initialize()
        {
            txt = true;
            //Append characters to the typedText string when the player types stuff on the keyboard.
            KeyGrabber.InboundCharEvent += (inboundCharacter) =>
            {
                //Only append characters that exist in the spritefont.
                if (inboundCharacter < 32)
                    return;

                if (inboundCharacter > 126)
                    return;

                typedText += inboundCharacter;
            };


            // Get the path of the save game
            string fullpath = "highscores.dat";

            // Check to see if the save exists
#if WINDOWS
            if (!File.Exists(fullpath))
            {
                //If the file doesn't exist, make a fake one...
                // Create the data to save
                data = new HighScoreData(5);
                data.PlayerName[0] = "neil";
                data.Score[0] = 2000;

                data.PlayerName[1] = "barry";
                data.Score[1] = 1800;

                data.PlayerName[2] = "mark";
                data.Score[2] = 1500;

                data.PlayerName[3] = "cindy";
                data.Score[3] = 1000;

                data.PlayerName[4] = "sam";
                data.Score[4] = 500;

                SaveHighScores(data, HighScoresFilename);
            }
#elif XBOX

            using (IsolatedStorageFile iso = IsolatedStorageFile.GetUserStoreForApplication())
            {
                if (!iso.FileExists(fullpath))
                {
                    //If the file doesn't exist, make a fake one...
                    // Create the data to save
                    data = new HighScoreData(5);
                    data.PlayerName[0] = "neil";
                    data.Score[0] = 2000;

                    data.PlayerName[1] = "shawn";
                    data.Score[1] = 1800;

                    data.PlayerName[2] = "mark";
                    data.Score[2] = 1500;

                    data.PlayerName[3] = "cindy";
                    data.Score[3] = 1000;

                    data.PlayerName[4] = "sam";
                    data.Score[4] = 500;

                    SaveHighScores(data, HighScoresFilename, device);
                }
            }

#endif

            base.Initialize();
        }
        #region saving
        /* Save highscores */
        public static void SaveHighScores(HighScoreData data, string filename)
        {
            // Get the path of the save game
            string fullpath = "highscores.dat";

#if WINDOWS
            // Open the file, creating it if necessary
            FileStream stream = File.Open(fullpath, FileMode.Create);
            try
            {
                // Convert the object to XML data and put it in the stream
                XmlSerializer serializer = new XmlSerializer(typeof(HighScoreData));
                serializer.Serialize(stream, data);
            }
            finally
            {
                // Close the file
                stream.Close();
            }

#elif XBOX

            using (IsolatedStorageFile iso = IsolatedStorageFile.GetUserStoreForApplication())
                {

                    using (IsolatedStorageFileStream stream = new IsolatedStorageFileStream(fullpath, FileMode.Create, iso))
                    {

                        XmlSerializer serializer = new XmlSerializer(typeof(HighScoreData));
                        serializer.Serialize(stream, data);

                    }

                }

#endif
        }

        /* Load highscores */
        public static HighScoreData LoadHighScores(string filename)
        {
            HighScoreData data;

            // Get the path of the save game
            string fullpath = "highscores.dat";

#if WINDOWS

            // Open the file
            FileStream stream = File.Open(fullpath, FileMode.OpenOrCreate, FileAccess.Read);
            try
            {
                // Read the data from the file
                XmlSerializer serializer = new XmlSerializer(typeof(HighScoreData));
                data = (HighScoreData)serializer.Deserialize(stream);
            }
            finally
            {
                // Close the file
                stream.Close();
            }


            return (data);

#elif XBOX

            using (IsolatedStorageFile iso = IsolatedStorageFile.GetUserStoreForApplication())
            {
                using (IsolatedStorageFileStream stream = new IsolatedStorageFileStream(fullpath, FileMode.Open,iso))
                {
                    // Read the data from the file
                    XmlSerializer serializer = new XmlSerializer(typeof(HighScoreData));
                    data = (HighScoreData)serializer.Deserialize(stream);
                }
            }

            return (data);

#endif

        }

        /* Save player highscore when game ends */
        private void SaveHighScore()
        {
            // Create the data to saved
            HighScoreData data = LoadHighScores(HighScoresFilename);

            int scoreIndex = -1;
            for (int i = data.Count - 1; i > -1; i--)
            {
                if (score >= data.Score[i])
                {
                    scoreIndex = i;
                }
            }

            if (scoreIndex > -1)
            {
                //New high score found ... do swaps
                for (int i = data.Count - 1; i > scoreIndex; i--)
                {
                    data.PlayerName[i] = data.PlayerName[i - 1];
                    data.Score[i] = data.Score[i - 1];
                }

                data.PlayerName[scoreIndex] = PlayerName; //Retrieve User Name Here
                data.Score[scoreIndex] = score; // Retrieve score here

                SaveHighScores(data, HighScoresFilename);
            }
        }

        /* Iterate through data if highscore is called and make the string to be saved*/
        public string makeHighScoreString()
        {
            // Create the data to save
            HighScoreData data2 = LoadHighScores(HighScoresFilename);

            // Create scoreBoardString
            string scoreBoardString = "Highscores:\n\n";

            for (int i = 0; i < 5; i++) // this part was missing (5 means how many in the list/array/Counter)
            {
                scoreBoardString = scoreBoardString + data2.PlayerName[i] + "-" + data2.Score[i] + "\n";
            }
            return scoreBoardString;
        }
        #endregion
        /// <summary>
        /// LoadContent will be called once per game and is the place to load
        /// all of your content.
        /// </summary>
        protected override void LoadContent()
        {
            // Create a new SpriteBatch, which can be used to draw textures.
            spriteBatch = new SpriteBatch(GraphicsDevice);
            font = Content.Load<SpriteFont>("Spritefont1");
            // TODO: use this.Content to load your game content here
        }

        /// <summary>
        /// UnloadContent will be called once per game and is the place to unload
        /// all content.
        /// </summary>
        protected override void UnloadContent()
        {
            // TODO: Unload any non ContentManager content here
        }



        protected override void Update(GameTime gameTime)
        {
            if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
                this.Exit();

            oldKeyboardState = currentKeyboardState;
            currentKeyboardState = Keyboard.GetState();
            //UpdateInput();
            score = 100;
            if(typedText != "")
                PlayerName = typedText;
            if (GamePad.GetState(PlayerIndex.One).Buttons.A == ButtonState.Pressed)
            {
                SaveHighScore();
                txt = false;
            }


            base.Update(gameTime);
        }

        //ignore this method
        private void UpdateInput()
        {
            oldKeyboardState = currentKeyboardState;
            currentKeyboardState = Keyboard.GetState();

            Keys[] pressedKeys;
            pressedKeys = currentKeyboardState.GetPressedKeys();

            foreach (Keys key in pressedKeys)
            {
                if (oldKeyboardState.IsKeyUp(key))
                {
                    if (key == Keys.Back) // overflows
                        textString = textString.Remove(textString.Length - 1, 1);
                    else
                        if (key == Keys.Space)
                            textString = textString.Insert(textString.Length, " ");
                        else
                            textString += key.ToString();
                }
            }
        } 

        /// <summary>
        /// This is called when the game should draw itself.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        protected override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Color.CornflowerBlue);
            spriteBatch.Begin();
            if (txt == true)
            {
                spriteBatch.DrawString(font, typedText, new Vector2(0, graphics.GraphicsDevice.PresentationParameters.BackBufferHeight * .5f), Color.White);
            }
            else if (txt == false)
            {
               spriteBatch.DrawString(font, makeHighScoreString(), new Vector2(500, 300), Color.Red);
            }
            //spriteBatch.DrawString(font, textString, new Vector2(256, 300), Color.Red);

            spriteBatch.End();
            // TODO: Add your drawing code here

            base.Draw(gameTime);
        }
    }
}

上面是我正在测试的XNA程序的Game1.cs文件。我正在测试键盘输入(使用另一个名为KeyGrabber.cs的类)并且我正在测试将int分数和字符串名称保存到文件的能力,以便我可以在我的游戏中使用高分系统。 他们的键盘输入似乎工作正常,因为它输出到屏幕。 保存似乎也可以保存默认数据。

我的问题是,当有人完成某个分数值并在屏幕上输入他们的名字时,我想覆盖这些数据。 问题是,一旦我写入文件,一旦数据没有改变。即使我更改了样本数据的默认值(例如,PlayerName =“neil”,得分= 2000),原始数据仍然保留,不显示任何更改。

我的另一个问题实际上是动态添加值。我觉得这很容易(也许是,我很累)但我似乎无法用用户提供的数据输出到文件(例如,如果他们写了他们的名字或获得了一定的分数),甚至没有原来。

  

基本上,我想输出一个文件,一个高分榜。有两个   保存的值(名称和分数)。我想从中读取名字   在屏幕上输入的文本(变量是“typedText”)。

修改

写完所有这些后,它就打了我。显然,一旦创建文件,样本数据值就不会改变,因为只有在文件不存在时才添加它们。所以不要紧,这个问题。

1 个答案:

答案 0 :(得分:2)

如果有一个代表单个高分的简单类:

public class HighScore
{
    public String Name { get; set; }
    public int Score { get; set; }
}

您将所有高分保存在List<HighScore>中,并使用

序列化它们
XmlSerializer serializer = new XmlSerializer(typeof(List<HighScore>));

样品

拥有List<HighScore>类型的私有字段可以轻松添加和搜索分数:

List<HighScore> _highScores = new List<HighScore>();

void LoadData()
{
    //...
    Stream dataStream = //whichever way you open it
    XmlSerializer serializer = new XmlSerializer(typeof(List<HighScore>));
    _highScores = serializer.Deserialize(dataStream) as List<HighScore>;
}

要添加高分,只需拨打

即可
_highScores.Add(new HighScore(){ Name = someName, Score = someScore });

要保存它,请使用相同的序列化程序对其进行序列化。使用LINQ,可以很容易地对分数进行排序:

var orderedScores = _highScores.OrderByDescending(s=>s.Score);
HighScore bestScore = orderedScores.FirstOrDefault();

注意

使用Windows时,您可能希望将数据保存在ApplicationData文件夹中(因为在发布游戏时,您可能无法写入安装文件夹)。您可以像这样获得保存游戏路径:

String dirPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "GameName");
DirectoryInfo directory = new DirectoryInfo(dirPath);
if (!directory.Exists)
    directory.Create(); //so no exception rises when you try to access your game file

this.SavegamePath = Path.Combine(dirPath, "Savegame.xml");