1 / 41

Chapter 10

Chapter 10. Using C# Methods to Solve Problem. XNA Game Studio 4.0. Objectives. Use image manipulation to write a game you might like to play . Discover how to create and use your first C# methods . Take a look at test-driven development . Make some mistakes and discover how to fix them.

jacie
Download Presentation

Chapter 10

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Chapter 10 Using C# Methods to Solve Problem XNA Game Studio 4.0

  2. Objectives • Use image manipulation to write a game you might like to play. • Discover how to create and use your first C# methods. • Take a look at test-driven development. • Make some mistakes and discover how to fix them.

  3. Playing with Images

  4. Zooming In on an Image • You change the way that the picture is drawn by changing the values in jakeRectas the program runs. • XNA can resize the picture for you so that you can move and scale your picture very easily. • You start by adding the following Update method to the display program protected override void Update(GameTimegameTime) { // Allows the game to exit if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed) this.Exit(); jakeRect.Height++; jakeRect.Width++; base.Update(gameTime); }

  5. Zooming In on an Image • You get a hold of a field in an object by giving the identifier of the variable a period character ( . ) and then the name of the field you wish to use. • This is true with a struct. • ExamplejakeRect.Height++;

  6. Creating a Zoom-Out • Updating the Drawing Rectangle • Change the way that you set up the Rectangle, which Describes the part of the image that you’ll draw protected override void Initialize() { gameSpriteBatch = new SpriteBatch(graphics.GraphicsDevice); jakeRect = new Rectangle(0, 0, 6000, 4500); base.Initialize(); } • This creates a rectangle that’s 6,000 pixels wide and 4,500 pixels high, or 10 times the original image size and much bigger than the screen

  7. Creating a Zoom-Out • More of the picture is visible, but it seems to have been stretched for some reason. • To understand what’s happening, you need to think first about what you set out to do. • You wanted to display only part of the image on the screen. This allows you to show only part of the image so that the player has to guess what the picture is. • To achieve this, you made the draw rectangle enormous by multiplying its width and height by 10 so that only part of the drawn image was visible on the screen. • You then created an Update method that reduces the width and height of this rectangle by one each time it is called so that the amount of image in the screen increases progressively. • You’ve noticed that as this program “zooms out” of the image, it no longer looks right.

  8. What happened. • You’re reducing the height and width by the same amount each time. Because the picture is not as high (4,500) as it is wide (6,000), the height is “used up” more quickly, leading to a scrunched picture. • Fix the problem by reducing each value by a percentageeach time rather than bya particular value.

  9. The Great Programmer Speaks

  10. Creating a Method to Calculate Percentages

  11. Putting a Method into Your Game Class • A method is a block of code that does something for you. • Each method has an identifierthat you use to refer to the method when you call it. • The details of what information is passed into the method (the telephone call) and the result it delivers (what’s written on the piece of paper) are written in C# as the method header. • The details of what the method does is called the method body.

  12. Putting a Method into Your Game Class • The methodheadergives the identifier for the method, what type of result it returns, and the number and type of any parameters. • A parameteris used to feed information into a method.

  13. Putting a Method into Your Game Class • Once the compiler has the header of a method, it knows what the method “looks like” in that it can create the code to use the method. • This description of a method is often called the signatureof the method. • When you create a method, you decide the type and number of the parameters that the method needs to do its job. • Some methods have many parameters; others have none.

  14. Putting a Method into Your Game Class • The method header is followed by the method body, a block of statements that perform the task for which the method was created. • The body can be a very large number of statements or only one or two. • If the method delivers a result then the body must contain a statement that returns a value of the type specified in the method header. • Once the compiler has the body of the method, it knows what statements need to be performed when the method is called.

  15. Calling a Method height = height - getPercentage(1, height); • This line of code would use getPercentage to reduce the value of the variable called height by 1 percent.

  16. What Happens in a Method Call • It makes a note of where it is in the program so that it can come back to the right place when the method finishes. • It gets the values of any parameters and sets them up for the method to use. • It jumps into the method body and performs the statements in the method body. • At the end of the method body, or when it reaches a return statement, it goes back and delivers whatever value was expected. • Then the program continues running at the statement following the method call.

  17. Returning Nothing Using void • Methods that don’t return a result are given the return type void. • This tells the compiler that the method does not deliver any information to the caller • protected override void Draw(GameTimegameTime) • If you want a method to return before the end of the method block, you can use the return key word to cause a return at that point. • If the method returns a value, the return key word must be followed by an expression that delivers a value of the required type.

  18. Testing a Method • The Great Programmer tells you that it’s quite sensible to create “broken” methods like this; you can use them to decide what the method looks like and then go back and fill in the statements later. • This is a version of a professional development technique called test-driven development. • You can also use them to write tests, as follows: protected override void Draw(GameTimegameTime) { if ( getPercentage(10, 800) == 80 ) { graphics.GraphicsDevice.Clear(Color.Green); } else { graphics.GraphicsDevice.Clear(Color.Red); } base.Draw(gameTime); }

  19. Designing Tests for getPercentage • A test can prove only that a particular fault is not present. It can’t prove that there are no faults in the code at all. • If programmers claim that their code is “fully tested,” usually what they really mean is that they can’t think of a reason it shouldn’t work, and this is not quite the same thing. • Next is C# code that gives your method a reasonable workout. It is not a particularly comprehensive test, but it will do for now

  20. Designing Tests for getPercentage protected override void Draw(GameTimegameTime) { if ( (getPercentage(0, 0) == 0) && // 0 percent of 0 (getPercentage(0, 100) == 0) && // 0 percent of 100 (getPercentage(50, 100) == 50) && // 50 percent of 100 (getPercentage(100, 50) == 50) && // 100 percent of 50 (getPercentage(10, 100) == 10) ) // 10 percent of 100 { graphics.GraphicsDevice.Clear(Color.Green); } else { graphics.GraphicsDevice.Clear(Color.Red); } base.Draw(gameTime); }

  21. Creating the getPercentageMethod Body • Algorithm • Calculate the fraction of the amount that you want (this is the percentage divided by 100; in other words, 50 percent would give you 50/100, which is a half). • Multiply the incoming amount by this fraction to create the result. • Code intgetPercentage(int percentage, intinputValue) { intfraction = percentage / 100; intresult = fraction * inputValue; return result; }

  22. Debugging C# Programs

  23. Debugging with Breakpoints • A breakpointis a way of marking a particular statement in your program and saying to XNA Game Studio “When the program reaches this statement, pause it and let me take a look at stuff.” • How to set a breakpoint • Click on the left margin • XNA Game Studio highlights the line in brown, and a brown dot appears against the line.

  24. Debugging with Breakpoints

  25. Hitting a Breakpoint • If you now run the program, you see that when it gets to the line that you’ve marked as a breakpoint, it stops.

  26. Viewing Variables • Rest the mouse pointer over the identifier of the variable in the code that you’re interested in. • A box pops up and tells you the value in that variable. • To run the program a bit further, click the green arrow in the program controls in the top left corner.

  27. Using Floating-Point Numbers in C# • You can use the float type, which can hold floating-point numbers. • These are so called because they have a decimal point that can “float” up and down the number, depending on the value being held. • Change the type of the fraction variable to float in your method intgetPercentage(int percentage, intinputValue) { floatfraction = percentage / 100; intresult = fraction * inputValue; return result; }

  28. The Compiler and C# Types • You now get an error message because your program no longer compiles. • If you look at your code, notice the wavy blue lines. • The compiler is saying “Cannot implicitly convert type 'float' to 'int'. An explicit conversion exists (are you missing a cast?).”

  29. The Compiler and C# Types • If you try to put a floating-point value (with a fractional part, say, the value 2.9) into a variable of type int (which doesn’t have support for the floating bit), you are in danger of losing information. • The line of code that you’re looking at does just that. intresult = fraction * inputValue; • When you move that into the result, you’re moving a floating-point value into an integer, which results in data loss. In programming terms, this is called narrowing. • You’re moving values from a data type with a wide range of values (floating point) into a type with a narrower range of values (integer).

  30. Compilers and Casting • When the compiler sees a statement that narrows a value, it produces the error message, “Cannot implicitly convert type 'float' to 'int'.” • The compiler won’t produce output steps that perform the conversion unless you explicitly ask it to. • The next part of the message gives you some more help. “An explicit conversion exists (are you missing a cast?).” • This means that the compiler can perform such a conversion, but you need to use a cast to request that the action be performed.

  31. Compilers and Casting • A castis where you ask the compiler to produce code that converts a value from one type to another. • A cast is the name of the type you want (in parentheses). • int result = (int)(fraction * inputValue); • Note that not all casts work. • You can’t convert from a Color to an intby using a cast because the compiler hasn’t been told how to generate code to do this.

  32. Expression Types • There are two kinds of division: those that produce an integer result and those that produce a floating-point result. • If the compiler sees an expression that divides an integer by another integer, it performs the integer division even if the result is being put into a floating-point variable. • If you need to force the compiler to perform floating-point division, and the way you do that is to turn one of the things in the calculation into a floating-point value. • You can do this by casting again: floatfraction = (float) percentage / 100;

  33. The Great Programmer Speaks

  34. Stopping the Zoom • You need to find a way to stop the zoom when the image is the same size as the screen. • Just change the size of the sprite rectangle while it’s wider than the screen. if (jakeRect.Width > graphics.GraphicsDevice.Viewport.Width) { jakeRect.Width= jakeRect.Width- getPercentage(1, jakeRect.Width); jakeRect.Height= jakeRect.Height- getPercentage(1, jakeRect.Height); }

  35. Zooming from the Center • If you want to zoom in on the center of the image, you need to move the upper-left corner of the draw rectangle up and to the left moving the display area into the middle of the image.

  36. Zooming from the Center • For the method to work properly, it has to know the width of the texture that is to be used, so all the work must be performed in the LoadContentmethod. protected override void LoadContent() { // Create a new SpriteBatch, which can be used to draw textures. spriteBatch = new SpriteBatch(GraphicsDevice); jakeTexture = this.Content.Load<Texture2D>("jake"); intdisplayWidth = GraphicsDevice.Viewport.Width; intdisplayHeight = GraphicsDevice.Viewport.Height; intscaledWidth = jakeTexture.Width * 10; intscaledHeight = jakeTexture.Height * 10; jakeRect = new Rectangle( -(scaledWidth / 2) + (displayWidth / 2), -(scaledHeight / 2) + (displayHeight / 2), scaledWidth, scaledHeight); }

  37. Zooming from the Center • Now that you’ve put the viewing rectangle in the center of the screen, you need to move the draw position each time you scale the image. • It turns out that if the width of the rectangle changes by X-amount, the position of the upper-left corner must move to the right by half of X to keep the rectangle centered with respect to the display area. intwidthChange = getPercentage(1, jakeRect.Width); intheightChange = getPercentage(1, jakeRect.Height); jakeRect.Width = jakeRect.Width - widthChange; jakeRect.Height = jakeRect.Height - heightChange; jakeRect.X = jakeRect.X + (widthChange / 2); jakeRect.Y = jakeRect.Y + (heightChange / 2);

  38. Zooming from the Center • The problem with this zoom program is that although it works fine, when the zoom finishes, the image is not lined up properly with the display. • The X and Y draw positions, which should be 0 when you’ve fully zoomed out of the image, still hold negative values at the end of the zoom. • The problem lies with the following two statements jakeRect.X = jakeRect.X + (widthChange / 2); jakeRect.Y = jakeRect.Y + (heightChange / 2);

  39. Zooming from the Center • if the width change were 101, the change to the value of X would be 50, not 50.5. • This calculation is repeated many times, and eventually this lack of precision leads to an answer that’s incorrect. • The only way to solve this problem is to change the data type you’re using to hold all the values. • Change your variable type to float. • Errors in values that build up over time, sometimes called cumulative errors, are something that programmers often need to address.

More Related