0
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"、score = 2000)、元のデータは保持され、変更は表示されません。

私の他の問題は、実際に値を動的に追加することです。簡単だろうと思っていたのですが(たぶん、とても疲れています)、ユーザーが提供したデータ(たとえば、名前を書いたり、特定のスコアを獲得した場合)をファイルに出力できないようです。最初に。

基本的には、ハイスコアのリストをファイルに出力したいと考えています。保存された 2 つの値 (名前とスコア)。画面に入力されたテキストから名前を読み取りたい(変数は「typedText」)。

編集

それをすべて書いた後、それは私を襲った。ファイルが存在しない場合にのみ追加されるため、ファイルが作成されると、サンプルデータの値は変更されません。ですから、その問題は気にしないでください。

4

1 に答える 1

2

単一のハイスコアを表す単純なクラスを作成するのはどうでしょうか。

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

すべてのハイスコアを に保持し、List<HighScore>それらをシリアル化します

XmlSerializer serializer = new XmlSerializer(typeof(List<HighScore>));

サンプル

type のプライベート フィールドがある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");
于 2012-11-27T16:09:35.607 に答える