XNA Game-Themed CS1 Examples ( XGC1 ) Release 2.0 (XNA V3.1) 2/8/2010
Topic: Topic.2.Input_Output_PrimitiveDataTypes
Example: Ex_13.Formula

# Math Operators: Translating Math Formulas Into C#

References:
• Pre-requisite: it is assumed that you have read through the prior tutorials, and are familiar with the concepts covered in those tutorials.
• It may be useful to refer to refer to the diagram illustrating the Draw-Update loop (which explains that your initialization code will be called once, and then the XNACS1Lib will repeatedly call your Update method (after which it will Draw the screen) ), in order to have a clear picture of how your game executes.

Goals:

• In this tutorial, we will:
• Examine how to implement a mathematical formula in C#
• Examine how to use some of the built-in Math functionality within C#
• Examine how to create a visual representation of the formula
• Examine how to update and change on-screen shapes in response to the player's input

1. Obtain the example code

Download and unzip the zip file and you will see an ExampleProgram folder. Open the ExampleProgram folder, the EXE folder contains the compiled program and you can double click on the .sln file to work with the source code.

This program is intended to visually show much money you would have in the bank in 20 years, if you started with a particular amount of money now, and you were able to accrue a certain amount of interest each year.  This is is calculated using the formula for compounding interest .  Note that in this program, will will calculate the future value (i.e., how much money you'll have in the future), starting from the present value (i.e., how much money you have now).  Another, different thing that we will NOT calculate here is the present value given a future value sum of money (i.e., how much money you should start with, if you want to end up saving up to a particular amount of money in the future).

Once we compile and run this project, the program displays two rectangles on the screen. The left rectangle is labeled with the present value (i.e., the sum of money that you start with), and the right rectangle is labeled with the future value (i.e., the sum of money you'll end up with).  At the top of the screen, the number of years, and the interest rate are displayed.  The heights of each rectangle are proportional to the values that they represent, and the distance between the 'future value' rectangle and the left edge of the screen is proportional to the number of years.

At the bottom of the screen are instructions for playing the game.  By using the left thumbstick's vertical axis (the Y axis), you can control the present value of the money that you're saving (and thus, you can control the current height of the present value rectangle).  By using the left thumbstick's horizontal axis (the X axis), you can control the rate.  By using the right thumbstick's vertical (Y) axis, you can control the number of years that the money will be saved for (and thus, you can control the location of the future value rectangle).  The height of the future value rectangle depends on the future value of the saved up money, which is calculated for you.

Additionally, when player presses the 'Back' button (or the keyboard equivalent), the program will exit.

2. Examining The Program:

Let's examine the C# source code that produces the behavior we see on-screen

• Declaring the instance variables

We need to declare (to define, really) our instance variables before we can use them.

 public class Game1 : XNACS1Base {         private XNACS1Rectangle presentRec;     private XNACS1Rectangle futureRec;     private float presentValue; // present value of the money     private float rate; // interest rate     private float years; // number of years
• We'll need to keep track of each of the rectangles that we see on-screen, so we declare each of them here.
• You'll notice something new for this tutorial: we've declared three private float s, to keep track of various pieces of information.  We declare them here (as instance variables) because we'll need this information to exist throughout the entire program.  The information is:

presentValue
This is the value of the money that you start saving with.  In other words, if you walked down to the bank today with some money you want to put into your savings account, this variable would represent that amount of money
rate
This is the interest rate that your savings will accumulate at.
years
This is the number of years that you will leave your money in the bank.
• For this tutorial, we're using the formula for compound interest.  We're assuming that you're paid the interest only once per year.
• We will calculate the future value of the money given the above information, and the appropriate formula.  We will store the future value of the money into a local variable.
• InitializeWorld():  protected override void   InitializeWorld() {     World. SetWorldCoordinate( new Vector2 (0,0), 100.0f);     presentValue = 10.0f;     years = 20;     rate = 0.02f;     float futureValue = presentValue * ( float ) Math .Pow((1 + rate), years);     presentRec = new XNACS1Rectangle ();     presentRec.LowerLeft= new Vector2 (5.0f, 5.0f);     presentRec.Height = presentValue;     presentRec.Width = 10.0f;     futureRec = new XNACS1Rectangle ();     futureRec.LowerLeft = new Vector2 (years, 5.0f);     futureRec.Height = futureValue;     futureRec.Width = 10.0f; }
• The first thing that we do is to initialize the instance variables (the program-wide variables) with some starting values.  Visually, the following values work well, so we'll use them:

presentValue = 10.0f;

years = 20;

rate = 0.02f;

• Next, we declare a variable hold the future value of the money, and then we go ahead and calculate that future value, all in one line
float futureValue = presentValue * ( float ) Math .Pow((1 + rate), years);

Let's examine how this works, in detail:

1. There are three types of operators: the the assignment operator, and the multiplication operator, and the addition operator.  The assignment operator is executed last, so that all the other math can be done, and the result assigned to the the variable as we'd expect.  Normally, the multiplication operator would be evaluated first.  However, before the multiplication operation can be done, C# needs to know the values on both the left and right side of the *.  The left side is just the variable  presentValue , so getting that value is trivial. However, the right side is ( float ) Math .Pow((1 + rate), years) , which is more complicated.  Since C# can't do the multiplication until it knows this value, C# will have to evaluate all this first , then go back and do the multiplication.
• Before we go through ( float ) Math .Pow((1 + rate), years) in detail, let's first get a quick overview of what's going on here:
• The ( float ) is another example of (type) casting, as we saw in previous tutorials, and it means that once we've done everything else, we'll translate that result into being a float
• The Math .Pow(...)  is a call to some built-in functionality, kind of like EchoToTopStatus(...) .  One key difference is that Math .Pow() is built-in the core C# library, so you can use it in almost any C# program you'll ever write, while EchoToTopStatus() is only available to programs using the XNACS1Lib library.  Math .Pow() requires two pieces of data to do it's job, which are placed inside the parentheses, separated by the comma.  We'll examine what these two pieces of data mean later on in this walkthrough.
• (1 + rate) is the first piece of information that we need to give to Math .Pow() .  You'll notice that this is an expression itself (i.e., it contains operators).  Before we can make use of the Math .Pow() , we need to know what this is, so we'll be forced to do this before the Math .Pow() .
• years  is the second piece of information that we need to give to Math .Pow() .  Since this is a simple variable, we can grab the value whenever we need it.
• Next, let's step through this, piece by piece:
1. float futureValue = presentValue * (float)Math.Pow(( 1 + rate ), years);

As we established above, we need to first do the Math .Pow , before we can do the multiplication.  And in order to do the Math .Pow , we need to do the addition.
In order to do the addition, we should first (mentally) substitute the value that rate is storing into the expression.  We also need to make sure that both numbers are of the same type - in this case, the 1 (which is technically an integer) will be promoted to being a float.  So what we end up with is actually like this:

float futureValue = presentValue * (float)Math.Pow(( 1 .0f + 0.02f ), years);

2. float futureValue = presentValue * (float)Math.Pow( ( 1.0f + 0.02f ) , years);
Next, we follow through with the addition, and end up with 1.02f.  Additionally, since we no longer need the parentheses, we will remove them now
float futureValue = presentValue * (float)Math.Pow(( 1.02f ), years);
• Technically, the the parentheses were never required, and had no effect on the order in which things were evaluated.  In writing this tutorial, it was felt that having the parentheses there would help make it more clear that the first piece of information that Math .Pow needs is really (1 + rate) , added together BEFORE making the call
3. float futureValue = presentValue * (float)Math.Pow(1.02f, years );
Next, we'll mentally substitute the value of years in.  Note that since years is a float , the value stored in it is already 20.0f.  The conversion/promotion from "20" to "20.0f" already happened on the years = 20; line.
float futureValue = presentValue * (float)Math.Pow(1.02f, 20.0f );
4. float futureValue = presentValue * (float) Math .Pow ( 1.02f, 20.0f ) ;
Next, we'll make the call to Math.Pow.  But first, what does Math.Pow do?
• If you look in the online documentation (or try typing something like "C# math.pow" into a search engine), and you'll probably end up at a page like http://msdn.microsoft.com/en-us/library/system.math.pow.aspx .  Looking through it, we find (under the 'Syntax' part, for C#):
public static double Pow(
double x ,
double y
)

What this tells us is that the documentation will refer to the first piece of information that we're giving it as X , and the second piece as Y .  Reading further, the section on parameters seems to be talking about raising one number to a power; even if this section isn't crystal-clear to you, it does provide valuable hints about what Math.Pow does.  Finally, in the section entitled 'Return Value', we find the sentence 'The number x raised to the power y .', which tells us that if we give Math.Pow the base (X), and an exponent (Y), it will return to us X Y .  For example, if we do Math.Pow(2,3), then we expect to get back the value of 2 3 (which is the same as  2 ? 2 ?/font>2), or 8.
• In our case, we're going to pass it 1.02 as the base, and 20 as the exponent., so that we can use Math.Pow to calculate 1.02 20
• This will actually produce a double-precision number: 1.48594738295345 , which means that our final result is:

float futureValue = presentValue * (float) 1.48594738295345 ;

5. float futureValue = presentValue * ( float ) 1.48594738295345 ;
As mentioned above, we will do the type-casting once we've gotten the result of doing the Math.Pow.  Since Math.Pow returned a double-precision number, and since most of XNA uses single-precision floating point numbers, we'll convert from double precision to single-precision here.  Notice that this number starts the same, but isn't nearly as precise:
float futureValue = presentValue *
1.485947 ;
6. At this point, we've now finished evaluating ( float ) Math .Pow((1 + rate), years) , so we can take the results of that, and continue evaluating the rest of the line:
2. float futureValue = presentValue * 1.48597;
At this point, we're down to just the normal multiplication and assignment, which we've seen before.  Let's go through them in detail anyways.  Since multiplication is the operator to evaluate next, let's (mentally) substitute the value stored in presentValue in:
float futureValue = 10.0f * 1.48597;
3. float futureValue = 10.0f  * 1.48597;
Next, let's do the multiplication:
float futureValue = 14.85947 ;
4. float futureValue = 14.85947 ;
Finally, we do the assignment, and store 14.85947 into the variable futureValue.
• Having calculated the various numbers that we'll use, we then use our familiar code to initialize the rectangles.

UpdateWorld():

 protected override void UpdateWorld() {     if (GamePad.ButtonBackClicked())         this .Exit();     float leftThumbY = GamePad.ThumbSticks.Left.Y;     float leftThumbX = GamePad.ThumbSticks.Left.X;     float rightThumbY = GamePad.ThumbSticks.Right.Y;     // Get user's input, accumulate for: years, rate, and presentValue     years = years + rightThumbY;     rate = rate + (0.005f * leftThumbX);     presentValue = presentValue + leftThumbY;     // compute futureValue according to the formula     float futureValue = presentValue * ( float ) Math .Pow((1 + rate), years);     // Update the height & label of the present rectangle:     presentRec.Height = presentValue;     presentRec.Label = "present value=" + presentRec.Height;     // Update the height & label of the future rectangle:     futureRec.Height = futureValue;     futureRec.Label = "future value=" + futureRec.Height;     // Change futureValue's lower-left corner to show year     futureRec.LowerLeft = new Vector2 (years, 5.0f);     EchoToTopStatus( "Years=" + years + " rate=" + rate);     EchoToBottomStatus( "LeftThumb-Y adjust Present Value; LeftThumb-X adjust rate; RightThumb-Y adjust Years" ); }
• As per normal, our game will check if the user presses the 'Back' button.  If we're going to exit, there's no sense in doing any work prior to exiting, so we check if we need to exit as the first two lines in the method
• Let's start by creating local variables that will hold copies of the numbers in the thumbsticks.  Since we're going to calculate new heights for both rectangles (using presentValue, which is an instance variable that we already have), we don't need to retrieve the values of the rectangles' heights.

float leftThumbY = GamePad.ThumbSticks.Left.Y;

float leftThumbX = GamePad.ThumbSticks.Left.X;

float rightThumbY = GamePad.ThumbSticks.Right.Y;

• Once we've got our local copies of the thumbstick data, we can now calculate the new values for the number of years to calculate the interest over, for the rate, and for the new present value:

// Get user's input, accumulate for: years, rate, and presentValue

years = years + rightThumbY;

rate = rate + (0.005f * leftThumbX);

presentValue = presentValue + leftThumbY;

• Notice that these variables have the same name as the variables that we used in the InitializeWorld method.  Since these variables were declared to be instance variables , they exist throughout the entire program.  Therefore, these variables are the exact same variables as the ones we were using in the InitializeWorld method.
• Contrast this with creating separate local variables that have the same name, in two different methods, as was done in the previous tutorial.
• Next, we reclcalculate the future value of our savings, using the same formula (and the same process) as was explained above.

// compute futureValue according to the formula

float futureValue = presentValue * ( float ) Math .Pow((1 + rate), years);

• The procedure for evaluating this expression is the same as the procedure that was explained above, in the InitializeWorld section.
• Next, we copy all the values back into the rectangles, and update their labels, so that the rectangles will be completed updated for when the Update step is done:

presentRec.Height = presentValue;

presentRec.Label = "present value=" + presentRec.Height;

// Update the height & label of the future rectangle:

futureRec.Height = futureValue;

futureRec.Label = "future value=" + futureRec.Height;

• Finally, we update the position of the futureRectangle.  Basically, if the user wants to see how much money they'll have in, say, 20 years, then we want to move the future rectangle over so that it's left edge is 20 units away from the left side of the screen.  We do this by using the variable years as the X value in the position vector for the rectangle:

// Change futureValue's lower-left corner to show year

futureRec.LowerLeft = new Vector2 ( years , 5.0f);

• In order to try and be helpful, we also echo a brief message to the bottom status bar, telling the user how to play the game.

EchoToTopStatus( "Years=" + years + " rate=" + rate);

EchoToBottomStatus( "LeftThumb-Y adjust Present Value; LeftThumb-X adjust rate; RightThumb-Y adjust Years" );

FURTHER EXERCISES::

1. Start from a blank starter project (1000.201, if you need it), and re-do the code from this tutorial, from memory, in the starter project, as much as possible.  On your first try, do what you can, and keep the above code open so that when you get stuck, you can quickly look up what you forgot (and that after you finish a line, so that you can compare your line to the 'correct' line).  On the next try, do the same thing, but try to use the finished code less.  Repeat this until you can type everything, without refering the tutorial's code.
• Repeat this exercise daily for several days, so that you really get the hang of this.  As you go on, periodically review this by re-doing this exercise.
2. Translating a different formula
Using the Exercise_ 2 _DifferentFormula's starter project , you should modify the solution so that your program uses a different formula.  Notice that there are two rectangles - one on the left, and one on the right.  You must make sure that each rectangle is always labeled with it's current height.  The user should be allowed to control the current height of the left rectangle using the left thumbstick - pushing that thumbstick up/forward increases the height of the rectangle, and pulling it down/backward decreases the height.   You should set up your code so that the height of the right rectangle is determined by the following formula:

Hint:
Use local variables wherever you can
3. Translating a different formula
Using the Exercise_ 3 _DifferentFormula's starter project , you should modify the solution so that your program uses a different formula.  Notice that there are two rectangles - one on the left, and one on the right.  You must make sure that each rectangle is always labeled with it's current height.  The user should be allowed to control the current height of the left rectangle using the left thumbstick - pushing that thumbstick up/forward increases the height of the rectangle, and pulling it down/backward decreases the height.   Let's define a math-style equation to describe the height of the right rectangle.  Let's say that the height of the left rectangle is given as X , and the height of the right rectangle is given by Y , in the following equation.  You should set up your code so that the height of the right rectangle is determined by the following formula:
4. Using the Math.Pow built-in function
Using the Exercise_ 4 _DifferentFormula's starter project , you should modify the solution so that your program uses a different formula.  Notice that there are two rectangles - one on the left, and one on the right.  You must make sure that each rectangle is always labeled with it's current height.  The user should be allowed to control the current height of the left rectangle using the left thumbstick - pushing that thumbstick up/forward increases the height of the rectangle, and pulling it down/backward decreases the height.   Let's define a math-style equation to describe the height of the right rectangle.  Let's say that the height of the left rectangle is given as X , and the height of the right rectangle is given by Y , in the following equation.  You should set up your code so that the height of the right rectangle is determined by the following formula:

Hint: Make sure that you can do this using the Math.Pow method, so that you're able to use functions built into C#

Also: In addition to using Math.Pow, can you do this using nothing more than the arithmetic operators (i.e., nothing more than + , * , - and / ?)

5. Using other built-in Math functionality
Using the Exercise_ 6 _MathFunction's starter project , you should modify the solution so that your program demonstrates the use of several common mathematical functions, that are built into the core C# / .Net framework.  Notice that there are several rectangles - left-most one is rectangle X , and others show the result of doing some operation on the current height of rectangle X.  For example, the rectangle next to X starts off with the label Sqrt(10)=3.162278 .  As the height of X is changed (by pushing the left thumbstick up/down), the height (and label) of this "square root" rectangle is updated accordingly.  The goal for this exercise is to give you the opportunity to look up various math functions, and make use of them here, in a graphical manner.

For this exercise, you need to fill in each of the other rectangles, as they're labeled, with the following functions:

• Math.Sqrt
This is already filled in for you - it returns the square root of the number that you give it.
• Math.Round
This method will round off a number to the nearest integer.  (You can also use it to round off after a certain number of decimal places, but that's beyond what this exercise is asking you to do)
• Math.Ceiling
This method will round up.
• Math.Floor
This method will round down.  Note that while this accomplishes the same sort of task as casting a number to an integer (i.e., digits after the decimal place will be removed), this method will NOT convert the number to an integer.  So you should use this if you want to round something down, but you want to keep your calculations as a double-precision number.
• Math.Abs
This method returns the absolute value of the number you give it. So Math.Abs( -10 ) will produce 10; Math.Abs(10) will also produce 10.
• Math.Sign
This method will return an int with the value -1 to indicate that the number you've given it is negative, 0 if the number you've given it is zero, and +1 if the number you've given is it positive.  For this rectangle, don't change the height, but do update the label to be -1, 0, or +1, depending on what the current height of X is.
• HINT: It may be useful to look these up online.  The following seems to be a good resource: http://msdn.microsoft.com/en-us/library/system.math_methods.aspx , but you may find other resources online, too.
6. Using other built-in Math functionality
Using the Exercise_ 7 _MinMax's starter project , you should modify the solution so that your program demonstrates the use of two common mathematical functions: Max and Min.  These are built into the core C# / .Net framework.

Notice that there are four rectangles - left-most one is rectangle min , the rightmost one is named max, and the two in the middle will be referred to as X (on the left) and Y (on the right).  You should set the height of the min rectangle so that it's equal to the height of the smaller of the two middle rectangles, and set the height of the max rectangle so that it's equal to the height of the larger of the two middle rectangles.  Additionally, you should label all rectangles with their name and current height.

• Math.Min:
Given two numbers, it will return the smaller number.
• Math.Max:
Given two numbers, it will return the larger number.

Project home page : The Game-Themed Introductory Programming Project.
 Kelvin Sung Computing and Software Systems University of Washington, Bothell ksung@u.washington.edu Michael Panitz Business And Information Technology Cascadia Community College mpanitz@cascadia.eduu

 This work is supported in part by a grant from Microsoft Research under the Computer Gaming Curriculum in Computer Science RFP, Award Number 15871 and 16531. 2/8/2010