Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống
1
/ 57 trang
THÔNG TIN TÀI LIỆU
Thông tin cơ bản
Định dạng
Số trang
57
Dung lượng
268,57 KB
Nội dung
430 | Appendix: Answers to Quizzes and Exercises • The bounding-box algorithm is a simple collision-detection algorithm in which you “draw” imaginary boxes around objects and then run collision checks on the boxes themselves to see if any objects are colliding. 5. Describe the pros and cons of the bounding-box collision-detection algorithm. • The two biggest pros of the algorithm are its speed and simplicity. The big- gest drawback is its inherent inaccuracy—not all objects are square or rect- angular, and as such the algorithm has accuracy issues. 6. When George Costanza is about to announce that he will henceforth be known as “T-Bone,” in one of the all-time classic Seinfeld episodes (“The Maid”), what does Mr. Kruger name him instead? • George: “OK, everybody. I have an announcement to make. From now on, I will be known as—” Kruger: “Koko the monkey.” George: “What?” All (chanting): “Koko! Koko! Koko! Koko! Koko! Koko! Koko!” Exercise Answer 1. Let’s combine some aspects of this chapter and the previous one. Take the code where we left off at the end of this chapter and modify it to include another nonuser-controlled sprite (use the plus.png image, which is located with the source code for this chapter in the AnimatedSprites\Collision\Content\Images folder). Add movement to both nonuser-controlled sprites, as you did in Chapter 2, so that each sprite moves in the X and Y directions and bounces off the edges of the screen. Add collision detection to the newly added sprite as well. The end result will be a game where you try to avoid two moving sprites. When you hit either sprite, the game ends. For clarity in working with the plus.png image, the frame size of the sprite sheet is 75 × 75 pixels, and it has six columns and four rows (note that the rings and skull ball sprite sheets both had six columns and eight rows). • This exercise takes principles from Chapters 2 and 3 and combines them to create a very basic game where you try to avoid two sprites that move around the screen. The addition of a new animated sprite is a bit of a chal- lenge, especially the way the code is currently written (in Chapter 4 you’ll learn how to fine-tune the object-oriented design of the system you’re build- ing). Other than that, collision detection and object movement and edge bouncing are handled the same way as in previous examples and should be fairly straightforward at this point. Here’s some sample code for this exercise: using System; using System.Collections.Generic; Chapter 3: User Input and Collision Detection | 431 using System.Linq; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Audio; using Microsoft.Xna.Framework.Content; using Microsoft.Xna.Framework.GamerServices; using Microsoft.Xna.Framework.Graphics; using Microsoft.Xna.Framework.Input; using Microsoft.Xna.Framework.Media; using Microsoft.Xna.Framework.Net; using Microsoft.Xna.Framework.Storage; namespace AnimatedSprites { public class Game1 : Microsoft.Xna.Framework.Game { GraphicsDeviceManager graphics; SpriteBatch spriteBatch; //Rings variables Texture2D ringsTexture; Point ringsFrameSize = new Point(75, 75); Point ringsCurrentFrame = new Point(0, 0); Point ringsSheetSize = new Point(6, 8); int ringsTimeSinceLastFrame = 0; int ringsMillisecondsPerFrame = 50; //Skull variables Texture2D skullTexture; Point skullFrameSize = new Point(75, 75); Point skullCurrentFrame = new Point(0, 0); Point skullSheetSize = new Point(6, 8); int skullTimeSinceLastFrame = 0; const int skullMillisecondsPerFrame = 50; //Plus variables Texture2D plusTexture; Point plusFrameSize = new Point(75, 75); Point plusCurrentFrame = new Point(0, 0); Point plusSheetSize = new Point(6, 4); int plusTimeSinceLastFrame = 0; const int plusMillisecondsPerFrame = 50; //Rings movement Vector2 ringsPosition = Vector2.Zero; const float ringsSpeed = 6; MouseState prevMouseState; //Skull position Vector2 skullPosition = new Vector2(100, 100); Vector2 skullSpeed = new Vector2(4, 2); //Plus position Vector2 plusPosition = new Vector2(200, 200); 432 | Appendix: Answers to Quizzes and Exercises Vector2 plusSpeed = new Vector2(2, 5); //Collision detection variables int ringsCollisionRectOffset = 10; int skullCollisionRectOffset = 10; int plusCollisionRectOffset = 10; public Game1() { graphics = new GraphicsDeviceManager(this); Content.RootDirectory = "Content"; } protected override void Initialize() { // TODO: Add your initialization logic here base.Initialize(); } protected override void LoadContent() { // Create a new SpriteBatch, which can be used to draw textures. spriteBatch = new SpriteBatch(GraphicsDevice); ringsTexture = Content.Load<Texture2D>(@"imageshreerings"); skullTexture = Content.Load<Texture2D>(@"images\skullball"); plusTexture = Content.Load<Texture2D>(@"images lus"); } protected override void UnloadContent() { // TODO: Unload any non ContentManager content here } protected override void Update(GameTime gameTime) { // Allows the game to exit if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed) this.Exit(); //Update time since last frame and only //change animation if framerate expired ringsTimeSinceLastFrame += gameTime.ElapsedGameTime.Milliseconds; if (ringsTimeSinceLastFrame > ringsMillisecondsPerFrame) { ringsTimeSinceLastFrame -= ringsMillisecondsPerFrame; ++ringsCurrentFrame.X; if (ringsCurrentFrame.X >= ringsSheetSize.X) Chapter 3: User Input and Collision Detection | 433 { ringsCurrentFrame.X = 0; ++ringsCurrentFrame.Y; if (ringsCurrentFrame.Y >= ringsSheetSize.Y) ringsCurrentFrame.Y = 0; } } //Then do the same to update the skull animation skullTimeSinceLastFrame += gameTime.ElapsedGameTime.Milliseconds; if (skullTimeSinceLastFrame > skullMillisecondsPerFrame) { skullTimeSinceLastFrame -= skullMillisecondsPerFrame; ++skullCurrentFrame.X; if (skullCurrentFrame.X >= skullSheetSize.X) { skullCurrentFrame.X = 0; ++skullCurrentFrame.Y; if (skullCurrentFrame.Y >= skullSheetSize.Y) skullCurrentFrame.Y = 0; } } //Then do the same to update the plus animation plusTimeSinceLastFrame += gameTime.ElapsedGameTime.Milliseconds; if (plusTimeSinceLastFrame > plusMillisecondsPerFrame) { plusTimeSinceLastFrame -= plusMillisecondsPerFrame; ++plusCurrentFrame.X; if (plusCurrentFrame.X >= plusSheetSize.X) { plusCurrentFrame.X = 0; ++plusCurrentFrame.Y; if (plusCurrentFrame.Y >= plusSheetSize.Y) plusCurrentFrame.Y = 0; } } //Move position of rings based on keyboard input KeyboardState keyboardState = Keyboard.GetState(); if (keyboardState.IsKeyDown(Keys.Left)) ringsPosition.X -= ringsSpeed; if (keyboardState.IsKeyDown(Keys.Right)) ringsPosition.X += ringsSpeed; if (keyboardState.IsKeyDown(Keys.Up)) ringsPosition.Y -= ringsSpeed; if (keyboardState.IsKeyDown(Keys.Down)) ringsPosition.Y += ringsSpeed; 434 | Appendix: Answers to Quizzes and Exercises //Move the skull skullPosition += skullSpeed; if (skullPosition.X > Window.ClientBounds.Width - skullFrameSize.X || skullPosition.X < 0) skullSpeed.X *= -1; if (skullPosition.Y > Window.ClientBounds.Height - skullFrameSize.Y || skullPosition.Y < 0) skullSpeed.Y *= -1; //Move the plus plusPosition += plusSpeed; if (plusPosition.X > Window.ClientBounds.Width - plusFrameSize.X || plusPosition.X < 0) plusSpeed.X *= -1; if (plusPosition.Y > Window.ClientBounds.Height - plusFrameSize.Y || plusPosition.Y < 0) plusSpeed.Y *= -1; //Move rings based on mouse movement MouseState mouseState = Mouse.GetState(); if (mouseState.X != prevMouseState.X || mouseState.Y != prevMouseState.Y) ringsPosition = new Vector2(mouseState.X, mouseState.Y); prevMouseState = mouseState; //Move rings based on gamepad input GamePadState gamepadState = GamePad.GetState(PlayerIndex.One); if (gamepadState.Buttons.A == ButtonState.Pressed) { //A is pressed, double speed and vibrate ringsPosition.X += ringsSpeed * 2 * gamepadState.ThumbSticks.Left.X; ringsPosition.Y -= ringsSpeed * 2 * gamepadState.ThumbSticks.Left.Y; GamePad.SetVibration(PlayerIndex.One, 1f, 1f); } else { //A is not pressed, normal speed and stop vibration ringsPosition.X += ringsSpeed * gamepadState.ThumbSticks. Left.X; ringsPosition.Y -= ringsSpeed * gamepadState.ThumbSticks. Left.Y; GamePad.SetVibration(PlayerIndex.One, 0, 0); } //Adjust position of rings to keep it in the game window if (ringsPosition.X < 0) ringsPosition.X = 0; Chapter 3: User Input and Collision Detection | 435 if (ringsPosition.Y < 0) ringsPosition.Y = 0; if (ringsPosition.X > Window.ClientBounds.Width - ringsFrameSize.X) ringsPosition.X = Window.ClientBounds.Width - ringsFrameSize.X; if (ringsPosition.Y > Window.ClientBounds.Height - ringsFrameSize.Y) ringsPosition.Y = Window.ClientBounds.Height - ringsFrameSize.Y; //If objects collide, exit the game if (Collide()) Exit(); base.Update(gameTime); } protected bool Collide() { Rectangle ringsRect = new Rectangle( (int)ringsPosition.X + ringsCollisionRectOffset, (int)ringsPosition.Y + ringsCollisionRectOffset, ringsFrameSize.X - (ringsCollisionRectOffset * 2), ringsFrameSize.Y - (ringsCollisionRectOffset * 2)); Rectangle skullRect = new Rectangle( (int)skullPosition.X + skullCollisionRectOffset, (int)skullPosition.Y + skullCollisionRectOffset, skullFrameSize.X - (skullCollisionRectOffset * 2), skullFrameSize.Y - (skullCollisionRectOffset * 2)); Rectangle plusRect = new Rectangle( (int)plusPosition.X + plusCollisionRectOffset, (int)plusPosition.Y + plusCollisionRectOffset, plusFrameSize.X - (plusCollisionRectOffset * 2), plusFrameSize.Y - (plusCollisionRectOffset * 2)); return ringsRect.Intersects(skullRect) || ringsRect.Intersects(plusRect); } protected override void Draw(GameTime gameTime) { GraphicsDevice.Clear(Color.White); spriteBatch.Begin(SpriteBlendMode.AlphaBlend, SpriteSortMode.FrontToBack, SaveStateMode.None); //Draw the rings spriteBatch.Draw(ringsTexture, ringsPosition, new Rectangle(ringsCurrentFrame.X * ringsFrameSize.X, ringsCurrentFrame.Y * ringsFrameSize.Y, ringsFrameSize.X, 436 | Appendix: Answers to Quizzes and Exercises ringsFrameSize.Y), Color.White, 0, Vector2.Zero, 1, SpriteEffects.None, 0); //Draw the skull spriteBatch.Draw(skullTexture, skullPosition, new Rectangle(skullCurrentFrame.X * skullFrameSize.X, skullCurrentFrame.Y * skullFrameSize.Y, skullFrameSize.X, skullFrameSize.Y), Color.White, 0, Vector2.Zero, 1, SpriteEffects.None, 0); //Draw the plus spriteBatch.Draw(plusTexture, plusPosition, new Rectangle(plusCurrentFrame.X * plusFrameSize.X, plusCurrentFrame.Y * plusFrameSize.Y, plusFrameSize.X, plusFrameSize.Y), Color.White, 0, Vector2.Zero, 1, SpriteEffects.None, 0); spriteBatch.End(); base.Draw(gameTime); } } } Chapter 4: Applying Some Object-Oriented Design Quiz Answers 1. What class does a game component derive from? • GameComponent. 2. If you want to be able to draw on the screen with your game component, what class do you need to derive from? • DrawableGameComponent. 3. Fact or fiction: time spent building a solid object-oriented design should not count as time spent developing software because it is unnecessary and superfluous. • Absolutely fiction. Creating a proper design up front will help you avoid countless headaches and maintenance issues down the road. Always, no matter what the project, plan ahead and code around a solid design. 4. Which U.S. state prohibits snoring by law unless all bedroom windows are closed and securely locked? • Massachusetts (http://www.dumblaws.com/laws/united-states/massachusetts/). Chapter 4: Applying Some Object-Oriented Design | 437 Exercise Answer 1. Add the following exercise and solution: Modify the code that you worked on this chapter to create four sprites which move and bounce off all four edges of the screen. To accomplish this, create a new class called BouncingSprite which derives from AutomatedSprite. BouncingSprite should do the same thing that AutomatedSprite does with the exception that it will check during the Update method to determine if the sprite has gone off the edge of the screen. If it has, reverse the direction of the sprite by multiplying the speed variable by –1. Also, make two of the bouncing sprites use the skull image and two of them use the plus image (located with the source code for this chapter in the AnimatedSprites\AnimatedSprites\Content\Images directory). Note that when running this game after making these changes you’ll have four sprites moving around the screen and the game will exit when any of them col- lide with the user controlled sprite. This may cause some issues in testing the game because the sprites may be colliding when the game first loads. Try mov- ing your mouse to a far corner of the screen when loading the game to get your user controlled sprite out of the way to begin with. • Creating a bouncing sprite should be fairly straightforward at this point. You’ve already created a sprite that bounces off the edges of the game win- dow in a previous chapter (and done it again if you did the exercises for the previous chapters). All you’ll need to do is check in the Update method if the sprite has gone off the edge of the game window and, if it has, reverse its direction. Here’s the BouncingSprite class: using System; using System.Collections.Generic; using System.Linq; using System.Text; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; namespace AnimatedSprites { class BouncingSprite: AutomatedSprite { public BouncingSprite(Texture2D textureImage, Vector2 position, Point frameSize, int collisionOffset, Point currentFrame, Point sheetSize, Vector2 speed) : base(textureImage, position, frameSize, collisionOffset, currentFrame, sheetSize, speed) { } public BouncingSprite(Texture2D textureImage, Vector2 position, Point frameSize, int collisionOffset, Point currentFrame, Point sheetSize, Vector2 speed, int millisecondsPerFrame) 438 | Appendix: Answers to Quizzes and Exercises : base(textureImage, position, frameSize, collisionOffset, currentFrame, sheetSize, speed, millisecondsPerFrame) { } public override void Update(GameTime gameTime, Rectangle clientBounds) { position += direction; //Reverse direction if hit a side if (position.X > clientBounds.Width - frameSize.X || position.X < 0) speed.X *= -1; if (position.Y > clientBounds.Height - frameSize.Y || position.Y < 0) speed.Y *= -1; base.Update(gameTime, clientBounds); } } } Chapter 5: Sound Effects and Audio Quiz Answers 1. What do you use to reference a sound that has been included in an XACT audio file? • To play a sound in an XACT audio file, you reference the sound by its asso- ciated cue name. 2. What are the pros and cons of using the simple sound API available in XNA 3.0 instead of using XACT? • Pros: simple and fast, and supported on the Zune. Cons: no design time modification of sound properties. 3. Fact or fiction: the only way to get a soundtrack to loop during gameplay is to manually program the sound in code to play over and over. • Fiction. You can set the looping property of a particular sound in XACT by specifying a certain number of times for the sound to play or by specifying the sound to play in an infinite loop. 4. Fact or fiction: you can adjust the volume of your sounds using XACT. • Fact. You can adjust the volume, pitch, and other properties of a sound file using XACT. 5. How do you pause and restart a sound in XNA when using XACT audio files? Chapter 6: Basic Artificial Intelligence | 439 • If you capture the Cue object from the GetCue method and play the sound from the Cue object, you can call Pause, Stop, Play, and other methods on the Cue object to manipulate playback of that particular sound. 6. What, according to Michael Scott, did Abraham Lincoln once say which is a principle that Michael carries with him in the workplace? • In the TV show The Office, during the “Diversity Day” episode, Michael Scott creates a videotape about his new organization, Diversity Tomorrow. Michael Scott [on a videotape]: “Hi, I’m Michael Scott and I’m in charge of Dunder Mifflin Paper Products here in Scranton, Pennsylvana. But I’m also the founder of Diversity Tomorrow, because ‘Today Is Almost Over.’ Abraham Lincoln once said, ‘If you are a racist, I will attack you with the North.’ And those are principles I carry with me into the workplace.” Exercise Answer 1. Try experimenting with different sounds and sound settings in XNA using XACT. Find a few .wav files and plug them into the game. Experiment with dif- ferent settings in XACT by grouping multiple sounds in a single cue. • There’s really no right or wrong answer to this exercise. Follow the steps from earlier in the chapter, add some different sounds, and play with the set- tings in XACT. It doesn’t need to sound pretty; just use this as a chance to get more familiar with XACT and all that it can do. Chapter 6: Basic Artificial Intelligence Quiz Answers 1. What is the Turing Test? • Developed by Alan Turing, the Turing Test involved having a human inter- act with a computer and another human, asking questions to determine which was which. The test was designed to determine whether a computer was intelligent. If the interrogator was unable to determine which was the computer and which was the human, the computer was deemed “intelligent.” 2. Why is artificial intelligence so difficult to perfect? • Because intelligence itself is so difficult to define. It’s something that cur- rently is not truly understood and therefore is ambiguous by nature. 3. What constitutes irrelevancy for an object in a video game? What should be done with irrelevant objects, and why? [...]... System.Collections.Generic; System.Linq; Microsoft .Xna. Framework; Microsoft .Xna. Framework.Audio; Microsoft .Xna. Framework.Content; Microsoft .Xna. Framework.GamerServices; Microsoft .Xna. Framework.Graphics; Microsoft .Xna. Framework.Input; Microsoft .Xna. Framework.Media; Microsoft .Xna. Framework.Net; Microsoft .Xna. Framework.Storage; namespace AnimatedSprites { public class SpriteManager : Microsoft .Xna. Framework DrawableGameComponent... Microsoft .Xna. Framework; Microsoft .Xna. Framework.Audio; Microsoft .Xna. Framework.Content; Microsoft .Xna. Framework.GamerServices; Microsoft .Xna. Framework.Graphics; Microsoft .Xna. Framework.Input; Microsoft .Xna. Framework.Media; Appendix: Answers to Quizzes and Exercises using Microsoft .Xna. Framework.Net; using Microsoft .Xna. Framework.Storage; namespace _3D_Madness { public class Game1 : Microsoft .Xna. Framework.Game... Microsoft .Xna. Framework; Microsoft .Xna. Framework.Audio; Microsoft .Xna. Framework.Content; Microsoft .Xna. Framework.GamerServices; Microsoft .Xna. Framework.Graphics; Microsoft .Xna. Framework.Input; Microsoft .Xna. Framework.Media; Chapter 12: 3D Collision Detection and Shooting | 461 using Microsoft .Xna. Framework.Net; using Microsoft .Xna. Framework.Storage; namespace _3D_Game { public class Game1 : Microsoft .Xna. Framework.Game... (timeSinceLastSpawnTimeChange > nextSpawnTimeChange) { timeSinceLastSpawnTimeChange -= nextSpawnTimeChange; if (enemySpawnMaxMilliseconds > 100 0) { enemySpawnMaxMilliseconds -= 100 ; enemySpawnMinMilliseconds -= 100 ; } else { enemySpawnMaxMilliseconds -= 10; enemySpawnMinMilliseconds -= 10; } } } } } } Chapter 8: Deploying to the Microsoft Zune Quiz Answers 1 What class is used to play sound files loaded into a... Chapter 10: 3D Models Quiz Answers 1 What model format(s) are supported in XNA? • XNA supports x and fbx model files 2 Why use a model when you can just draw things on your own? • Models allow you to build a model or design in a third-party tool specifically designed for artistically modeling and molding three-dimensional objects It would be nearly impossible to develop objects by hand in XNA 3D using... / 2, Game.Window.ClientBounds.Height / 2), new Point(75, 75), 10, new Point(0, 0), new Point(6, 8), new Vector2(6, 6)); for (int i = 0; i < ((Game1)Game).NumberLivesRemaining; ++i) { int offset = 10 + i * 40; livesList.Add(new AutomatedSprite( Game.Content.Load(@"imageshreerings"), new Vector2(offset, 35), new Point(75, 75), 10, new Point(0, 0), new Point(6, 8), Vector2.Zero, null, 0, 5f));... the same Here is a randomly moving sprite class: using System; using Microsoft .Xna. Framework; using Microsoft .Xna. Framework.Graphics; namespace AnimatedSprites { class RandomSprite : Sprite { SpriteManager spriteManager; //Random variable to determine when to change directions int minChangeTime = 500; int maxChangeTime = 100 0; 440 | Appendix: Answers to Quizzes and Exercises int changeDirectionTimer;... the slower you end up moving For example, if your cameraDirection vector was (10, 2, 0) when you removed the Y component, you would end up with the vector Chapter 11: Creating a First-Person Camera | 459 (10, 0, 0) and you’d move at that speed If your camera was pitched at a larger angle and your cameraDirection vector was (2, 10, 0), the resulting vector after removing the Y component would be (2, 0,... Game Development Quiz Answers 1 Does XNA use a right-handed or left-handed coordinate system? • XNA uses a right-handed coordinate system, which means that if you looked at the origin down the Z axis with positive X moving to your right, the Z axis would be positive in the direction coming toward you 2 What makes up a viewing frustum (or field of view) for a camera in XNA 3D? • The viewing frustum is made... without it? • HLSL allows developers to access hardware functions that aren’t available via the XNA Framework The reason: graphics hardware has become more and more complex, and if the XNA Framework were expanded to handle all capabilities of graphics cards, the framework would be enormous Instead, HLSL works with XNA and allows you to write code for the graphics card itself 5 How do you multiply two matrices . position Vector2 skullPosition = new Vector2( 100 , 100 ); Vector2 skullSpeed = new Vector2(4, 2); //Plus position Vector2 plusPosition = new Vector2( 200 , 200 ); 432 | Appendix: Answers to Quizzes and. enemySpawnMinMilliseconds = 100 0; int enemySpawnMaxMilliseconds = 200 0; int enemyMinSpeed = 2; int enemyMaxSpeed = 6; int nextSpawnTime = 0; int likelihoodAutomated = 75; int likelihoodChasing = 20; //This. 2), new Point(75, 75), 10, new Point (0, 0) , new Point(6, 8), new Vector2(6, 6)); for (int i = 0; i < ((Game1)Game).NumberLivesRemaining; ++i) { int offset = 10 + i * 40; livesList.Add(new