Microsoft XNA Game Studio Creator’s Guide- P8 potx

30 310 0
Microsoft XNA Game Studio Creator’s Guide- P8 potx

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

Thông tin tài liệu

MICROSOFT XNA GAME STUDIO CREATOR’S GUIDE 188 SineCycle() traces a floating-point value through a sine wave’s cycle over time. The function is only executed once per frame but is used toupdate each Y value for all vertices in the grid. Add this function to your game class: float SineCycle(GameTime gameTime){ // less than full cycle of sine wave retrieves between 0 and 1. // full cycle for sine wave is 2*PI. if (cycleIncrement < 1) cycleIncrement += 0.0000005f * (float)gameTime.ElapsedGameTime.Milliseconds; // adjust when sine wave cycle complete else cycleIncrement = cycleIncrement - 1; return cycleIncrement; } As discussed, SineCycle() is called only once per frame to trace a value on the sine wave over time. The point on the sine wave that is returned is added to the V co- ordinate for each point in the grid. This sum is used for setting the Y value of each point in the grid. The result is a set of oscillating Y values that follow the sine wave as it rises and falls over time. SetWaterHeight() receives the sum of the texture’s V coordinate plus the point in the sine wave over time. This sine wave equation returns a Y value for the co- ordinate that corresponds with the V coordinate: Height = Amplitude = sin(WaveCountPerCycle * PointInCycle * 2π) Add the SetWaterHeight() method to the game class: float SetWaterHeight(float cycleTime){ const float FREQUENCY = 6.0f; // wave count per cycle const float AMPLITUDE = 1.0f/15.0f; // wave height // generates height based on V coord and sine equation return (AMPLITUDE * (float)Math.Sin(FREQUENCY * cycleTime * 2.0f * (float)Math.PI) - 0.4f); } 189 The X, Y, Z information is the same for both the stationary image layer and the moving image layer. Since the stationary layer is drawn first, the Y value that changes with the sine wave over time can be set for this layer and the changes will apply to both image layers. Adding this code to reset the X, Y, and Z coordinates inside the nested for-loop for UpdateMovingSurface() will create a dynamically changing Y value that simulates the wave for both layers over time: float X = surface1[col + row * NUM_COLS].Position.X; float Y = SetWaterHeight(V + SineCycle(gameTime)); float Z = surface1[col + row * NUM_COLS].Position.Z; surface0[col + row * NUM_COLS].Position = new Vector3(X, Y, Z); surface1[col + row * NUM_COLS].Position = new Vector3(X, Y, Z); When you run this program, it shows the moving dynamic texture and the waves rippling through the object. The effect is actually quite beautiful (see Figure 12-5). You can try building this example, or you can download the completed example from the Solutions folder on this book’s website. There are various ways to combine images for creating exciting graphics effects. Sprites are used to animate a series of image frames that are stored in an image file. Multitexturing can be used to blend two images together and provide more detail or dynamic movement for the texture. CHAPTER 12 Combining Images for Better Visual Effects FIGURE 12-5 Surf’s up! C HAPTER 12 REVIEW EXERCISES To get the most from this chapter, try out these chapter review exercises. 1. Try the step-by-step examples presented in this chapter, if you have not already done so. 2. For your solution to the SpriteBatch example, remove the code that manually resets the RenderState properties for the GraphicsDevice in the Draw() method. Then, add code to automatically restore the render states after the SpriteBatch object is drawn. Automatically restoring the render states can be done in DrawAnimatedHud() by replacing the SpriteBatch object’s Begin() instruction with code similar to this: spriteBatch.Begin(SpriteBlendMode.AlphaBlend, SpriteSortMode.Immediate,SaveStateMode.SaveState); Try running your code and notice that the output appears to be the same as before. 3. Replace your Begin() statement in Exercise 2 with an instruction similar to the following statement and then run your project: spriteBatch.Begin(); Notice how the ground and all other 3D objects disappear when the render states are not restored. 4. With the solution for the 2D sprite and the original 2D sprite settings, call DrawAnimatedHud() before DrawGround(). Notice that you cannot see the sprite unless the view is changed so the ground is not covering it. 5. Create your own sprite with three or more frames. In the same project, show the sprite as a 2D SpriteBatch object. Display your sprite in the 3D world using a textured sprite. 6. Use multitexturing to make it appear as if moving shadows cast from the clouds are traveling across the ground. MICROSOFT XNA GAME STUDIO CREATOR’S GUIDE 190 CHAPTER CHAPTER 13 Score Score Tracking and Tracking and Game Stats Game Stats 192 BEING able to display status information about players, and their scores, is fundamental to any game dashboard. For exam- ple, you might need to show statistics such as health, fuel level, the current map name, or maybe even the opponents’ names. In the end, your ability to present this in- formation boils down to having access to a font library that can overlay 2D text on your game’s 2D or 3D environment. As you would expect, XNA offers an excellent font library for this purpose. The two examples in this chapter demonstrate how to write text and numeric out- put to the game window. When you are finished (depending on which project you start with), your output will be similar to the window display shown in Figure 13-1. FIGURE 13-1 Text and numeric data drawn in the game window 193 F ONT EXAMPLE: DISPLAYING TEXT IN THE GAME WINDOW This example explains the steps to display the string “Score Tracking and Game Stats” in the top-left corner of the game window. You could use the same technique to show your name, display your scores, or to show other important statistics—like your shield strength or health level. This example can begin with either the Windows or Xbox 360 starter projects from the BaseCode folder on the book’s website. Alternatively, you could add this font example code to a new project generated by Visual Studio’s project template. Loading the Font Type Data Once you have chosen a starter project, you will use the XNA font class, so you will need to add a reference to the font type description data, in the Solution Explorer. The font can be added by right-clicking the Content node, choosing Add and select- ing New Item. Once you have the Add New Item – Content dialog open, you can add a font by choosing the Sprite Font template icon. For this exercise, call your file “MyFont.” Once you click Add, this will generate an XML file called MyFont.spritefont, which is then automatically placed in your project. At this point you will see the spritefont file referenced in the Solution Explorer (refer to Figure 13-2). CHAPTER 13 Score Tracking and Game Stats FIGURE 13-2 Font is properly referenced under the Content node. MICROSOFT XNA GAME STUDIO CREATOR’S GUIDE 194 If you view the contents of the spritefont file, you will see XML code that stores the font properties. You can adjust these elements to change the size of the font and the spacing between characters, and you can also set the font to be Regular, Bold, Italic, or Bold Italic in the <Style> element. To reference a TrueType font on your PC or Xbox 360, you will need to adjust the <FontName> element value in the spritefont file. In this example we will load a Cou- rier New font, so to do this, you must replace the FontName element with: <FontName>Courier New</FontName> Once you have made this adjustment, your XML code will appear in the MyFont.spritefont file as follows: <?xml version="1.0" encoding="utf-8"?> <! This file contains an xml description of a font, and will be read by the XNA Framework Content Pipeline. Follow the comments to customize the appearance of the font in your game, and to change the characters which are available to draw with > <XnaContent xmlns:Graphics="Microsoft.Xna.Framework.Content.Pipeline.Graphics"> <Asset Type="Graphics:FontDescription"> <! Modify this string to change the font that will be imported > <FontName>Courier New</FontName> <! Size is a float value, measured in points. Modify this value to change the size of the font > <Size>14</Size> <! Spacing is a float value, measured in pixels. Modify this value to change the amount of spacing in between characters > <Spacing>0</Spacing> <! UseKerning controls the layout of the font. If this value is true, kerning information will be used when placing characters > <UseKerning>true</UseKerning> <! Style controls the style of the font. Valid entries are "Regular", "Bold", "Italic", and "Bold, Italic", and are case sensitive > <Style>Regular</Style> 195 <! If you uncomment this line, the default character will be substituted if you draw or measure text that contains characters which were not included in the font > <! <DefaultCharacter>*</DefaultCharacter> > <! CharacterRegions control what letters are available in the font. Every character from Start to End will be built and made available for drawing. The default range is from 32, (ASCII space), to 126, ('~'), covering the basic Latin character set. The characters are ordered according to the Unicode standard. See the documentation for more information > <CharacterRegions> <CharacterRegion> <Start>&#32;</Start> <End>&#126;</End> </CharacterRegion> </CharacterRegions> </Asset> </XnaContent> For now, aside from changing the FontName, you can leave the default spritefont file settings as they were originally generated. However, you can edit the elements in this file further to change the size, weight (boldness), italics, and other properties if desired. Loading the Font Fonts are drawn using a SpriteFont object, which you must declare at the top of the game class: private SpriteFont spriteFont; The SpriteFont object actually is a sprite, so the corresponding data behind it should be read in the LoadContent() method. This object is loaded by first retriev- ing the font description data from the spritefont file. Since the spritefont file is refer- enced in the Content folder, you do not need to specify a directory when loading it. To load this file with the Load() method, you must pass the name of the spritefont filename without the file extension: spriteFont = Content.Load<SpriteFont>("MyFont"); CHAPTER 13 Score Tracking and Game Stats Ensuring Your Fonts Are Drawn in the Visible Portion of the Window We have already discussed the need to designate a title safe region in Chapter 4. This avoids truncating your graphics when running your games on the Xbox 360. Since fonts are 2D, and you do not want your fonts to be truncated, you will need to display your text in a title-safe region. A TitleSafeRegion() method was used in Chap- ter 4 to generate a rectangle that stores the top, bottom, left, and right margins around the safe area. An alternate, but similar, version of the TitleSafeRegion() method will be used in this chapter to calculate the starting pixel position on the window for each string that is written to it. This new TitleSafeRegion() method receives a string and a SpriteFont object as parameters. It then uses the SpriteFont’s MeasureString() method to retrieve the width and height of the string. The MeasureString() method uses the string to determine the output width and it uses the SpriteFont object to calcu- late the height of the font. Here is the revised version of the TitleSafeRegion() method to conveniently generate margins for the visible display area from game class: Rectangle TitleSafeRegion(string outputString, SpriteFont font){ Vector2 stringDimensions = font.MeasureString(outputString); int stringWidth = (int)stringDimensions.X; // string pixel width int stringHeight = (int)stringDimensions.Y; // font pixel height // some televisions only show 80% of the window const float UNSAFEAREA = 0.2f; const float MARGIN = UNSAFEAREA/2.0f; // calculate title safe bounds for string int top, left, safeWidth, safeHeight; top = (int)(Window.ClientBounds.Height*MARGIN); left = (int)(Window.ClientBounds.Width *MARGIN); safeWidth = (int)((1.0f-UNSAFEAREA)*Window.ClientBounds.Width) - stringWidth; safeHeight = (int)((1.0f-UNSAFEAREA)*Window.ClientBounds.Height) - stringHeight; return new Rectangle(left, top, safeWidth, safeHeight); } MICROSOFT XNA GAME STUDIO CREATOR’S GUIDE 196 197 CHAPTER 13 Score Tracking and Game Stats Drawing the Font The font render is triggered from the Draw() method. It is drawn using an overrid- den DrawString() method from the SpriteBatch class. The DrawString() parameters for this override include the FontBatch object, an output string, the starting top-left pixel position on the window where the string is drawn, and color. Whenever you draw a 2D SpriteBatch object, the process must start with the Be- gin() method and finish with the End() method. If you are adding your font code to a 3D game project, call your font drawing code after all your other objects are rendered. This ensures that your text displays at the forefront of the window. Otherwise your text will be covered by other objects that are rendered later by the Draw() method. Saving Your Render States When drawing 2D objects with a SpriteBatch object, XNA automatically adjusts the GraphicsDevice object to render in 2D. This makes drawing with SpriteBatch objects easy, but you have to be careful because the original GraphicsDevice settings are not restored. If the GraphicsDevice settings are not restored, your 3D objects may disappear and your tiled images may be thrown out of whack. You can get some hair-raising results if you forget and think your game code is broken. To automatically restore the settings (after drawing 2D fonts in your 3D games), use the SaveStateMode.SaveState property as the third parameter in an overridden version of the Begin() method. Be aware, though, that SaveStateMode.SaveState can cause performance issues if you use it a lot in your game, so you may want to manually reset your graphics device to avoid this per- formance hit. Restoring the graphics device manually is described in Chapter 12. Here is the code to draw your output: private void DrawFonts(GameTime gameTime){ string outputString; Rectangle safeArea; // start drawing font sprites spriteBatch.Begin(SpriteBlendMode.AlphaBlend, // enable transparency SpriteSortMode.Immediate, // use manual order SaveStateMode.SaveState); // store 3D settings outputString = "Score Tracking and Game Stats"; safeArea = TitleSafeRegion(outputString, spriteFont); spriteBatch.DrawString(spriteFont, outputString, new Vector2( safeArea.Left, safeArea.Top), Color.Yellow); [...]...198 MICROSOFT XNA GAME STUDIO CREATOR’S GUIDE // stop drawing - and 3D settings are restored if SaveState used spriteBatch.End(); } This font output will display after you trigger it from the Draw() method: DrawFonts(gameTime); When you compile and run this code, the words “Score Tracking and Game Stats” will appear at the top-left corner of the title safe region in the game window F ONT... code’s performance 199 Score Tracking and Game Stats C H A P T E R 200 MICROSOFT C XNA GAME STUDIO CREATOR’S GUIDE HAPTER 13 REVIEW EXERCISES To get the most from this chapter, try out these chapter review exercises Try the step-by-step examples presented in this chapter, but make the following changes 1 Use a Times New Roman font to display the “Score Tracking and Game Stats” title and use a Courier New... model format to another or performing quick edits to your model FIGURE 14-1 A windmill model animated in code 203 3D Models C H A P T E R 204 MICROSOFT XNA GAME STUDIO CREATOR’S GUIDE Creating a New Project Starting MilkShape automatically opens the designer studio environment Most of the controls can be found in the gray panel on the right Four different viewports are located on the left, as shown... professional game developers will usually ask the modeler to position the model so it rests at the point of origin Both the fan and windmill base should be centered at the origin Adding a Joint A joint is the root of the model hierarchy It is used to identify the center of the mesh FIGURE 14-7 Group listing after merging and renaming 211 3D Models C H A P T E R 212 MICROSOFT XNA GAME STUDIO CREATOR’S. .. 216 MICROSOFT XNA GAME STUDIO CREATOR’S GUIDE To apply transformations to all meshes within the model, you must multiply each mesh’s bone transformation matrix by the cumulative transformation matrix, or World matrix The product is stored in the BasicEffect shader, which applies the final transformation to the mesh drawn effect.World = carMatrix[mesh.ParentBone.Index] * WorldMatrix; You can use XNA s... button This will rotate the new blade by 120 degrees on the Z axis The result will be two duplicate blades that appear at different angles around the Z axis 209 3D Models C H A P T E R 210 MICROSOFT XNA GAME STUDIO CREATOR’S GUIDE Next, you will create the third blade While the new blade is still selected, from the Edit menu choose Duplicate Selection again A new blade will appear on top of the original... then resize the object by dragging the cursor in the viewport to compress or stretch the box as needed FIGURE 14-3 Box base, rounded fan blade, and sphere 205 3D Models C H A P T E R 206 MICROSOFT XNA GAME STUDIO CREATOR’S GUIDE Adding a Sphere The next step is to add a pin to your windmill The windmill needs a pin to fasten the windmill fan to the base Once the pin has been added, scaled, and moved... selected in the top drop-down menu If the model and image do not appear, select the cylinder from the drop-down menu and click Remap After you select the cylinder 207 3D Models C H A P T E R 208 MICROSOFT XNA GAME STUDIO CREATOR’S GUIDE group and do the remapping, if the image and cylinder group do not appear in the Texture Coordinate Editor, the group wasn’t assigned properly To correct this, exit from the... of 1000 milliseconds is assigned for the interval to ensure that the timer returns a true value for every second bool Timer(GameTime gameTime){ bool resetInterval = false; // add time lapse between frames and keep value between 0 & 1000 ms intervalTime += (double)gameTime.ElapsedGameTime.Milliseconds; intervalTime = intervalTime % 1000; 1 3 // intervalTime has been reset so a new interval has started... to fbx from MilkShape, XNA will demand that you use images that have height and width pixel dimensions that are a power of 2 Before creating the model, it is further recommended that you first test your texture by exporting a simple model that uses this image to *.fbx and then load and display it from your XNA code When the program loads your model and tries to draw it, Game Studio will inform you . the clouds are traveling across the ground. MICROSOFT XNA GAME STUDIO CREATOR’S GUIDE 190 CHAPTER CHAPTER 13 Score Score Tracking and Tracking and Game Stats Game Stats 192 BEING able to display status. to Figure 13-2). CHAPTER 13 Score Tracking and Game Stats FIGURE 13-2 Font is properly referenced under the Content node. MICROSOFT XNA GAME STUDIO CREATOR’S GUIDE 194 If you view the contents. stringHeight; return new Rectangle(left, top, safeWidth, safeHeight); } MICROSOFT XNA GAME STUDIO CREATOR’S GUIDE 196 197 CHAPTER 13 Score Tracking and Game Stats Drawing the Font The font render is triggered

Ngày đăng: 02/07/2014, 06:20

Tài liệu cùng người dùng

Tài liệu liên quan