Almost done

October 10, 2009

I’ve completed cards #13-16 and my little app is looking good.  There are only a few more things to do so a few more cards:

  • Card #17 – Fix icons for tab buttons
  • Card #18 – Figure out how/where to host source and link here

Here are the latest screenshots:
StopWatch Game Screen OneStopWatch Game Screen Two

You will notice my icons on the bottom are cut off by where the text should be.  I need to make smaller icons (figure out the size) and then fill in the button text.
Notes on the project:

  1. I hooked everything up through the app delegate class, even though I had two views to work with, this isn’t a good pattern to follow for a real app.
  2. The score saving/loading is not very robust, any damage to the score file and the app is toast.
  3. Sandwich logging, I’d say is sufficient for this type of application as it allows you to quickly isolate which method fatal errors occur in and go from there.  A real app will have better logging functionality esp. given that monotouch does not support a visual ide level debugger currently.
  4. WordPress strips the xml out of my posted code.  Need to fix this.  The xml is HighScores on the root, and each sub node is HighScoreOne and HighScoreTwo with the values between.

Here is the source for your perusal.  I could use to do some refactoring but this whole exercise was a spike in basic functionality and general how does it worky for MonoTouch.  So I will probably leave it as is and move on to some more interesting problems and definitely a whole new twist on this project.

	// The name AppDelegate is referenced in the MainWindow.xib file.
	public partial class AppDelegate : UIApplicationDelegate
	{
		bool isRunning = false;
		DateTime start, end = new DateTime();
		TimeSpan ts = new TimeSpan(0,0,0,0,0);
		TimeSpan hs = new TimeSpan(0,0,1);
		TimeSpan hs2 = new TimeSpan(0,0,1);
		private static Selector selector = new Selector("UpdateTimer");
		private static string path = Environment.GetFolderPath(Environment.SpecialFolder.Personal);
		private static string filePath = Path.Combine(path, "highscore.xml");

		// This method is invoked when the application has loaded its UI and its ready to run
		public override bool FinishedLaunching (UIApplication app, NSDictionary options)
		{
			// If you have defined a view, add it here:
			window.AddSubview (tabBarController.View);

			buttonStartOne.TouchDown += ButtonStartOnePushed;
			buttonStartTwo.TouchDown += ButtonStartTwoPushed;
			buttonEndTwo.TouchDown += ButtonEndTwoPushed;

			InitHighScore();

			// Create timer
			// notes: the timer starts immediately
			//        selector is the delegate we want to run when the timer fires
			NSTimer.CreateScheduledTimer(0.01, this, selector, null, true);

			window.MakeKeyAndVisible ();

			return true;
		}

		public void InitHighScore()
		{
			Console.WriteLine("InitHighScore() Enter");
			if (File.Exists(filePath))
			{
				string hsXML = File.ReadAllText(filePath);
				XmlDocument doc = new XmlDocument();
				doc.LoadXml(hsXML);

				hs = GetScoresFromXML(doc, "/HighScores/HighScoreOne");
				hs2 = GetScoresFromXML(doc, "/HighScores/HighScoreTwo");

				// highScoreOne.Text = hsText;
			}

			highScoreOne.Text = string.Format("{0}:{1}", hs.Seconds, hs.Milliseconds);
			highScoreTwo.Text = string.Format("{0}:{1}", hs2.Seconds, hs2.Milliseconds);
			Console.WriteLine("HighScore: {0}", highScoreOne.Text);
			Console.WriteLine("HighScore2: {0}", highScoreTwo.Text);
			Console.WriteLine("InitHighScore() Exit");
		}

		public TimeSpan GetScoresFromXML(XmlDocument doc, string node)
		{
			Console.WriteLine("GetScoresFromXML() Enter");
			TimeSpan ts;
			string hsText = doc.SelectSingleNode(node).InnerText;
			string[] ret = hsText.Split(':');
			Console.WriteLine("Ref?: {0}, {1}:{2}", hsText, ret[0], ret[1]);
			ts = new TimeSpan(0,0,0,Convert.ToInt32(ret[0]),Convert.ToInt32(ret[1]));
			Console.WriteLine("Got High Score: {0}:{1}", ts.Seconds, ts.Milliseconds);
			return ts;
		}

		[Export ("UpdateTimer")]
		public void UpdateTimer()
		{
			string time;
			DateTime increment;

			if (isRunning)
			{
				increment = DateTime.Now;
				ts = increment.Subtract(start);
				time = string.Format("{0}:{1}", ts.Seconds, ts.Milliseconds);
				displayOne.Text = time;
				displayTwo.Text = time;
			}
		}

		public void UpdateScoreFile()
		{
			Console.WriteLine("UpdateScoreFile() Enter");
			if (!File.Exists(filePath))
			{
				Console.WriteLine("Creating new highscore file");
				StreamWriter sw = File.CreateText(filePath);
				sw.Close();
			}

			string hsXML = string.Format("" +
				"&ltHighScoreOne&gt{0}:{1}&lt/HighScoreOne&gt" +
			    "{2}:{3}" +
				"", hs.Seconds, hs.Milliseconds,
			                     hs2.Seconds, hs2.Milliseconds);
			File.WriteAllText(filePath, hsXML);
			Console.WriteLine(File.ReadAllText(filePath));
			Console.WriteLine("UpdateScoreFile() Exit");
		}

		public void ButtonStartOnePushed(object sender, EventArgs e)
		{
			Console.WriteLine("ButtonStartOnePushed() Enter");
			if (isRunning)
			{
				end = DateTime.Now;
				isRunning = false;
				buttonStartOne.SetTitle("Start", UIControlState.Normal);
				ts = end.Subtract(start);
				displayOne.Text = string.Format("{0}:{1}", ts.Seconds, ts.Milliseconds);
				if (ts < hs) {
					hs = ts;
					highScoreOne.Text = string.Format("{0}:{1}", hs.Seconds, hs.Milliseconds);
					UpdateScoreFile();
					AnnounceWinner();
				}
			}
			else
			{
				start = DateTime.Now;
				isRunning = true;
				buttonStartOne.SetTitle("Stop", UIControlState.Normal);
			}
			Console.WriteLine("ButtonStartOnePushed() Exit");
		}

		public void ButtonStartTwoPushed(object sender, EventArgs e)
		{
			Console.WriteLine("ButtonStartTwoPushed() Enter");
			if (!isRunning)
			{
				start = DateTime.Now;
				isRunning = true;
			}
			Console.WriteLine("ButtonStartTwoPushed() Exit");
		}

		public void AnnounceWinner()
		{
			SystemSound sound = SystemSound.FromFile(new NSUrl("sounds/winner.wav"));
			sound.PlaySystemSound();
		}

		public void ButtonEndTwoPushed(object sender, EventArgs e)
		{
			Console.WriteLine("ButtonEndTwoPushed() Enter");
			if (isRunning)
			{
				end = DateTime.Now;
				isRunning = false;
				ts = end.Subtract(start);
				displayTwo.Text = string.Format("{0}:{1}", ts.Seconds, ts.Milliseconds);
				if (ts < hs2) {
					hs2 = ts;
					highScoreTwo.Text = string.Format("{0}:{1}", hs2.Seconds, hs2.Milliseconds);
					UpdateScoreFile();
					AnnounceWinner();
				}
			}
			Console.WriteLine("ButtonEndTwoPushed() Exit");
		}

		// This method is required in iPhoneOS 3.0
		public override void OnActivated (UIApplication application)
		{
		}
	}
Advertisement

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.