Microsoft XNA Game Studio Creator’s Guide- P18 potx

30 204 0
Microsoft XNA Game Studio Creator’s Guide- P18 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 488 in a SoundEffect object. A SoundEffectInstance is created from this SoundEffect ob- ject which gives you the ability to loop, pause, and resume your individual sound ef- fects. The firing audio is loaded into a SoundEffect object which is used later for playback whenever the B button is pressed. // load and play background audio backgroundAudio = Content.Load<Song>("Audio\\telemetricBeep"); MediaPlayer.Play(backgroundAudio); MediaPlayer.IsRepeating = true; // load and play engine as SoundEffectInstance for playback control engineSound = Content.Load<SoundEffect>("Audio\\engine0"); engineInstance = engineSound.Play(VOLUME, PITCH, PAN, LOOP); // load fire sound effect for playback later fireSound = Content.Load<SoundEffect>("Audio\\fire"); Lastly, inside Update(), you can add this code to trigger the firing audio whenever the B button is pressed. Thiscode will also allow your players to pause and resume the ship engine and telemetric beep whenever they press the center of the Zune pad. // get new game pad states GamePadState gpCurrent = GamePad.GetState(PlayerIndex.One); // play fire sound at each new B button press event if (gpCurrent.IsButtonDown(Buttons.B)&& gpPrevious.IsButtonUp(Buttons.B)) fireSound.Play(VOLUME, PITCH, PAN, !LOOP); // toggle engine audio pause and resume states for DPad.Down events if (gpCurrent.Buttons.A == ButtonState.Pressed && gpPrevious.Buttons.A == ButtonState.Released) if (engineInstance.State == SoundState.Playing){ engineInstance.Pause(); MediaPlayer.Pause(); } else{ engineInstance.Resume(); MediaPlayer.Resume(); } // store game pad state for next frame gpPrevious = gpCurrent; You are now ready to deploy this to the Zune for an audio-enabled experience. You may have found the process so simple that you might also decide to use this li- brary in your 2D and 3D game projects on the PC and Xbox 360 as well. 489 We are sure you will notice how much more enjoyable your games are when you add audio using any of the alternatives provided in XNA. C HAPTER 27 REVIEW EXERCISES To get the most from this chapter, try out these chapter review exercises. 1. Implement the step-by-step example in this chapter to create your own XACT audio project file. Then load your audio and play it from code. 2. Using the solution for the arcing projectiles example from Chapter 19, add in audio to handle a launch sound and a 3D audio-enabled explosion sound when the rocket hits the ground. 3. Using the solution for “Adding a Car as a Third-Person Object” from Chapter 14, add a looping noise that repeats to create a continuous engine sound whenever the car moves forward or backward. CHAPTER 27 Adding Audio to Your Game This page intentionally left blank CHAPTER CHAPTER 28 Multiplayer Multiplayer Gaming Gaming 492 WE’RE sure you can appreciate the difference between playing video games against the computer and against your friends. Whether you’re knocking baseballs over their heads, swerving in front of them to maintain a lead, or volleying rockets at them, it’s all good. Most people have a lot more fun playing against an unpredictable human opponent who puts up a tough fight and trash-talks while doing it. Until now, the examples in this book have been geared for single-player games. You can easily change this by converting your base code to enable a multiplayer envi- ronment—where up to four people at a time can take the controls in a split-screen game. This type of environment is exactly what you would expect in a 3D first-per- son shooter game or a racing game. You could actually split the screen into more than four sections, but the controller limit is four. You might want additional dimensions, though, if you were to show dif- ferent views of the world. For example, maybe you want to create a radar screen with an aerial view of your entire world in addition to the main viewer for navigation. The split-screen technique offers many useful possibilities for dividing up the graphics that are rendered in your window. The code changes required to enable a split-screen game are surprisingly simple. The Viewport class makes it easy to split your screen. And if your camera is care- fully designed, as it is in the examples this book, you can easily create separate in- stances to give each additional player control over her own viewport. V IEWPORT A viewport is a section of the window that you use to draw a scene from a specific view. As you’ll see, using the Viewport class to split the screen is actually very sim- ple. The Viewport class is used to create a viewport object: Viewport viewport = new Viewport(); Each viewport object has several properties to set the position and area covered in the game window. Each section of the window is assigned values for the starting top-left pixel, the width and height in pixels, and the depth for clipping, so your phys- ical game objects draw properly: int viewport.X // top left pixel X coordinate int viewport.Y // top left pixel Y coordinate int viewport.Width // width in pixels int viewport.Height // height in pixels float viewport.MinDepth // minimum depth of clip volume (usually 0) float viewport.MaxDepth // maximum depth of clip volume (usually 1) 492 493 The bulk of the code changes needed to convert to a multiplayer game are in han- dling a separate instance of the camera for each player. However, even this task is rel- atively simple. When your multiplayer games are rendered on the Xbox 360, your viewports may be truncated on the televisions where they are played. In fact, it is possible that up to 20 percent of the screen will be hidden. This issue can be addressed by implementing a routine to create margins that equal 10 percent of the window height at the top and bottom and 10 percent of the window width for the left and right. An example of how to do this is presented in the demonstration later in this chapter. C REATING SEPARATE CAMERAS FOR EACH PLAYER To give each user the ability to navigate through the world, a separate camera in- stance is required for each player. The camera instance gives the players the ability to change their position and view within the 3D world. Adjusting the View For the graphics engine used in this book, whenever a player moves the mouse or shifts the right thumbstick, he changes his view. In other words, his position in the world stays the same, but his Look direction changes as his view target changes. A separate view is needed for each player in the game. For example, in a racing game you might need to focus your camera to watch the contours of a hairpin turn so you don’t crash. Your friend might need to watch out for an oil slick to maintain control of the car, and yet another player might be focused on the finish line. When you assign a separate viewport for each player, every object that is drawn in the viewport must be rendered according to that player’s view. Even the base code, which draws nothing but ground, must draw the ground once for each viewport ac- cording to the viewport owner’s Look direction. To handle this need for separate views, the camera’s view matrix is updated separately for each player. Adjusting the Projection The Projection matrix transforms vector coordinates into clip space (a cone that the viewer sees through). In a split-screen window, you must also adjust the projection to match the area in each viewport. If you do not resize the perspective’s aspect ratio properly, you could end up with a viewport(s) that displays everything in a bloated manner—as if the scene were either viewed through a fish-eye lens or in a house of mirrors. The aspect ratio considers the viewport width relative to the viewport height. Until now we have used the window width over height to calculate this ratio. Now though, the current viewport’s width over height is needed. CHAPTER 28 Multiplayer Gaming To implement this modification for a split-screen environment, for each different viewport size on display, a Projection matrix is defined when the application begins with the following syntax: // parameters are field of view, viewport w/h, near clip, far clip Matrix projection = Matrix.CreatePerspectiveFieldOfView( float fieldOfView, float aspectRatio, float nearClip, float farClip) If you divide the window into top and bottom viewports, the aspect ratio be- comes this: Window.ClientBounds.Width/(Window.ClientBounds.Height/2) H ANDLING THE USER INPUT It is possible to have up to four game controllers on one Xbox 360 or PC, so you could write code to handle up to four different players and split the screen accord- ingly at run time. For the PC, you can even use the mouse and keyboard as one of these inputs. Handling the different controllers is easy with the GamePadState class because each controller is referenced by a separate instance of the class. The states for each control on the game pad can be obtained using the GetState() method with a PlayerIndex attribute as a parameter to specify each player. S PLIT-SCREEN CODE EXAMPLE This example demonstrates multiplayer 3D gaming in a split-screen environment. Two aliens will be rendered and controlled in two separate viewports. Each player has her own viewport and is given control of one alien’s spaceship, which moves with her camera as she travels. Figure 28-1 shows a split screen for two players. Each player can control her view and position inside the viewport and ultimately travel within the world independently of the other player. A multiplayer racing game or first-person shooter game uses the same code founda- tion, so converting the logic to suit a different type of 3D multiplayer game is a simple task. Converting this logic to handle more than two players is also straightforward. When you run this code on the Xbox 360, you will be able to handle two players, each with her own controller. When the code is run on the PC, you can handle either two controllers, or one controller and a mouse/keyboard combination. If you run this code on the PC with only a mouse and keyboard, you will be able to control one of the viewports, but the other viewport will be disabled until a controller is con- nected. MICROSOFT XNA GAME STUDIO CREATOR’S GUIDE 494 495 This example begins with either the MGHWinBaseCode or MGH360BaseCode project, which can be found in the BaseCode folder in the download available from this book’s website. To enable a two-player game, and to identify each player, you declare the NUMPLAYERS, ALIEN0, and ALIEN1 definitions at the top of the game class: const int NUMPLAYERS = 2; const int ALIEN0 = 0; const int ALIEN1 = 1; To give each player control to move through the 3D environment, and to allow them to view it independently, you declare an array with two separate instances for the camera. Use this revision to replace the existing camera object declaration: private Camera[] cam = new Camera[NUMPLAYERS]; CHAPTER 28 Multiplayer Gaming FIGURE 28-1 Two viewports for a two-player game. Each player controls her view of the world and can travel independently. When you’re initializing each camera, the starting position and view position for each person needs to be different. Otherwise, with just a default position and view, when the game begins, the players would all be positioned in the same place, one on top of the other. To set the players up at opposite ends of the world, and to have them looking at their opponent, each instance of the camera is initialized with parameters to set the position and view. An override to the camera constructor allows you to set the position and view of the camera when it is initialized for each player: public Camera(Vector3 startPosition, Vector3 startView){ position = startPosition; view = startView; up = new Vector3(0.0f, 1.0f, 0.0f); } To initialize the camera for the players, you pass their individual starting positions and views to the camera constructor. This is done from the Initialize() method (in the game class) at the program start: Vector3 position, view; position = new Vector3( 0.5f, 0.9f, BOUNDARY - 0.5f); view = new Vector3( 0.5f, 0.7f, BOUNDARY - 1.0f); cam[0] = new Camera(position, view); position = new Vector3(-0.5f, 0.9f,-BOUNDARY + 0.5f); view = new Vector3(-0.5f, 0.7f,-BOUNDARY + 1.0f); cam[1] = new Camera(position, view); As mentioned earlier in this chapter, because both viewport heights are half the ac- tual window height, the aspect-ratio parameter in the Projection matrix must be ad- justed. The aspect ratio for the projection becomes (width/(height/2)). To apply this to the Projection matrix, after initializing each camera, replace the call to initialize the Projection matrix in the Initialize() method: for (int player = 0; player < 2; player++) cam[player].SetProjection(Window.ClientBounds.Width, Window.ClientBounds.Height/2); Now that you have properly set up the projection matrix for a multiplayer envi- ronment, you will need to comment out the original call statement to initialize the projection matrix. You can find this call statement inside the InitializeBaseCode() method of the game class: MICROSOFT XNA GAME STUDIO CREATOR’S GUIDE 496 497 CHAPTER 28 Multiplayer Gaming // cam.setProjection(Window.ClientBounds.Width, // Window.ClientBounds.Height); A routine is needed in the game class to determine how many game controllers are connected so it can assign control to both players accordingly. The TotalControllersUsed() method needed for this example only considers a sit- uation where up to two controllers are used: int TotalControllersUsed(){ GamePadState gp0 = GamePad.GetState(PlayerIndex.One); GamePadState gp1 = GamePad.GetState(PlayerIndex.Two); if (gp0.IsConnected && gp1.IsConnected) return 2; else if (gp0.IsConnected) return 1; return 0; } The ChangeView(), Move(), Strafe(), and DrawGround() methods inside the game class need to be modified so they can be used for each player. Since each player is a viewport owner, these method headers must be adjusted to accept the player number, as follows: Vector2 ChangeView(GameTime gameTime, int player) float Move(int player) float Strafe(int player) void DrawGround(int player) The ChangeView(), Move(), and Strafe() methods are called once for each viewport owner. These methods must then select the correct input device to allow each player to control their view and position. For this example, by default, a GamePadState object is set for the first player us- ing the PlayerIndex.One parameter value regardless of whether a controller is connected or not. If zero or one controllers are connected on a PC, the mouse is desig- nated for the first player to control their viewport. If two game controllers are con- nected on the PC, the GamePadState object is set for the second player using the PlayerIndex.Two parameter. The following code must be added in the ChangeView(), Move(), and Strafe() methods after the GamePadState object, gp, is declared: bool useMouse = false; int totalControllers = TotalControllersUsed(); [...]... MAX_LOCAL_GAMERS = 4; { return MAX_LOCAL_GAMERS; } } 511 Networking C H A P T E R 512 MICROSOFT XNA GAME const int CAMERA_DATA = 0; STUDIO CREATOR’S const int NETWORK_DATA GUIDE = 1; } } Next, to track when gamers join your game and when the session ends, add the following handlers to your XNANetwork class: void GamerJoinEvent(object sender, GamerJoinedEventArgs e){ int gamerIndex = session.AllGamers.IndexOf(e.Gamer);... CODE FRAMEWORK XNA offers a very simple interface to build your network while it also allows you room to customize how it operates GamerServicesComponent A networked XNA game is enabled with the GamerServicesComponent The GamerServices namespace must be referenced from the game class to use it: using Microsoft. Xna. Framework.GamerServices; The GamerServicesComponent is added when the game begins: Components.Add(new... GamerServices framework in your game class: using Microsoft. Xna. Framework.GamerServices; You can then add in an instance of the GamerServicesComponent for the game from the game class constructor: Components.Add(new GamerServicesComponent(this)); At the top of the game class, an instance of the network is needed: XNANetwork network = new XNANetwork(); Also at the top of the game class, a Boolean variable... your session These events include GameStarted, GamerJoined, GamerLeft, GamerEnded, and SessionEnded 2 9 GamerJoined Event As the name suggests, the GamerJoined event lets you track new gamers that join your session This event handler is added on every machine that joins the current network session: NetworkSession networkSession.GamerJoined += GamerJoinEvent; The GamerJoinEvent handler used in our... void Read(LocalNetworkGamer gamer){ // read all available incoming packets while (gamer.IsDataAvailable){ NetworkGamer sender; // read single packet from network gamer.ReceiveData(packetReader, out sender); // don't read local packets if (sender.IsLocal) continue; remotePosition = packetReader.ReadVector3(); 513 Networking C H A P T E R 514 MICROSOFT remoteView XNA GAME STUDIO CREATOR’S GUIDE = packetReader.ReadVector3();... source for each gamer Here is the code to start the XNANetwork class: using System; using Microsoft. Xna. Framework; using Microsoft. Xna. Framework.Net; using System.Collections.Generic; namespace MGHGame{ public class XNANetwork{ public String public NetworkSession PacketWriter packetWriter PacketReader packetReader public Vector3 remotePosition, const int MAX_GAMERS = 16; public int MaxLocalGamers{ get... (gamer.IsLocal) Write(gamer, cameraPosition, cameraView); // update session object session.Update(); // ensure that session has not ended if (session == null) return; // read packets for remotely controlled aliens foreach (LocalNetworkGamer gamer in session.LocalGamers) Read(gamer); } Adding Network Capability to the Game Class To enable networking objects in your game, you must reference the GamerServices...498 MICROSOFT XNA GAME STUDIO CREATOR’S GUIDE // when fewer than two controllers connected use mouse for 1st player if (totalControllers . operates. GamerServicesComponent A networked XNA game is enabled with the GamerServicesComponent. The GamerServices namespace must be referenced from the game class to use it: using Microsoft. Xna. Framework.GamerServices; The. You can find this call statement inside the InitializeBaseCode() method of the game class: MICROSOFT XNA GAME STUDIO CREATOR’S GUIDE 496 497 CHAPTER 28 Multiplayer Gaming // cam.setProjection(Window.ClientBounds.Width, //. MICROSOFT XNA GAME STUDIO CREATOR’S GUIDE 488 in a SoundEffect object. A SoundEffectInstance is created from

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

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

  • Đang cập nhật ...

Tài liệu liên quan