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”)。
修改
写完所有这些后,它就打了我。显然,一旦创建文件,样本数据值就不会改变,因为只有在文件不存在时才添加它们。所以不要紧,这个问题。
答案 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");