Subscribe

RSS Feed (xml)

Powered By

Powered by Blogger

Google
 
xnahelp.blogspot.com

Jumat, 04 April 2008

Creating a Split Screen

Now that we know how to set up our camera and accept input, we can look into how our
code will need to change to handle multiple players in a split-screen game. To start, we
need to make a copy of the InputDemo project we just finished. We can rename the
project SplitScreen. After we have our solution and projects renamed (complete with our
assembly GUID and title) we can look at the code we will need to change to accomplish a
split-screen mode of play.
To create a split screen, we need to two different viewports. We have only been using one
up until now and we actually retrieved it in our camera’s Initialization method. We
simply grabbed the GraphicsDevice.Viewport property to get our camera’s viewport.
Because we want to display two screens in one we need to define our two new viewports
and then let the cameras (we will need two cameras) know about them so we can get the
desired effect. To start we will need to add the following private member fields to our
Game1.cs code:
private Viewport defaultViewport;
private Viewport topViewport;
private Viewport bottomViewport;
private separatorViewport;
private bool twoPlayers = true;
private FirstPersonCamera camera2;
Then at the end of our LoadGraphicsContent method we will need to define those viewports
and create our cameras and pass the new values. We do this in the following code:
if (twoPlayers)
{
defaultViewport = graphics.GraphicsDevice.Viewport;
topViewport = defaultViewport;
bottomViewport = defaultViewport;
topViewport.Height = topViewport.Height / 2;
separatorViewport.Y = topViewport.Height – 1;
separatorViewport.Height = 3;
bottomViewport.Y = topViewport.Height + 1;
bottomViewport.Height = (bottomViewport.Height / 2) - 1;
camera.Viewport = topViewport;
106 CHAPTER 5 Input Devices and Cameras
camera2 = new FirstPersonCamera(this);
camera2.Viewport = bottomViewport;
camera2.Position = new Vector3(0.0f, 0.0f, -3.0f);
camera2.Orientation = new Vector3(0.0f, 0.0f, 1.0f);
camera2.PlayerIndex = PlayerIndex.Two;
Components.Add(camera2);
}
We discussed briefly that we would need more than one camera to pull this off. This is
because we have our view and projection matrices associated with our camera class
(which we should). It makes sense that we will have two cameras because the camera is
showing what the player is seeing. Each player needs his or her own view into the game.
Our initial camera is still set up in our game’s constructor but our second camera will get
added here. Our first camera gets the default viewport associated with it. The first thing
the preceding code is doing is checking to see if we are in a two-player game. For a real
game, this should be determined by an options menu or something similar, but for now
we have just initialized the value to true when we initialized the twoPlayer variable.
Inside of the two-player condition the first thing we do is set our default viewport to what
we are currently using (the graphic device’s viewport). Then we set our top viewport to
the same value. We also initialize our bottomViewport to our defaultViewport value. The
final thing we do with our viewports is resize them to account for two players. We divide
the height in two (we are making two horizontal viewports) on both. We then set our
bottom viewport’s Y property to be one more than the height of our bottom. This effectively
puts the bottom viewport right underneath our top viewport.
While still in the two-player condition we change our first camera’s viewport to use the
top viewport. Then we set up our second camera by setting more properties. Not only
do we set the viewport for this camera to the bottom viewport we have, but we also
set a new camera position as well as the orientation of the camera. Finally, we set the
player index.
None of these properties is exposed from our camera object, so we need to open our
Camera.cs file and make some changes to account for this. First, we need to add a new
private member field to hold our player index. We just assumed it was player 1 before. We
can set up our protected (so our FirstPersonCamera class can access it) index as an
integer as follows:
protected int playerIndex = 0;
Now, we can actually modify our input code that controls our camera to use this index
instead of the hard-coded value 0 for our game pads. In the camera’s Update method we
can change any instance of input.GamePads[0] to input.GamePads[playerIndex]. We also
need to do the same for the FirstPersonCamera object. We did not update the keyboard
code and will not for the sake of time. However, to implement multiple users where both
can use the keyboard we should create a mapping for each player and check accordingly.
In general, it is a good practice to have a keyboard mapping so that if gamers do not like
Creating a Split Screen 107
5
the controls we have defined in our games then they have a way to change them so it
works more logically for them. The same can be said about creating a mapping for the
game pads but many games simply give a choice of a couple of layouts. Because the code
does not implement a keyboard mapping, the only way for us to control the separate
screens differently is by having two game pads hooked up to our PC or Xbox 360.
After we have changed our camera to take the player index into consideration before
reading values from our game pad, we can add the following properties to our code:
public PlayerIndex PlayerIndex
{
get { return ((PlayerIndex)playerIndex); }
set { playerIndex = (int)value; }
}
public Vector3 Position
{
get { return (cameraPosition); }
set { cameraPosition = value; }
}
public Vector3 Orientation
{
get { return (cameraReference); }
set { cameraReference = value; }
}
public Vector3 Target
{
get { return (cameraTarget); }
set { cameraTarget = value; }
}
public Viewport Viewport
{
get
{
if (viewport == null)
viewport = graphics.GraphicsDevice.Viewport;
return ((Viewport)viewport);
}
set
{
viewport = value;
InitializeCamera();
}
}
108 CHAPTER 5 Input Devices and Cameras
We are simply exposing the camera’s position, orientation (reference), and target variables.
For the player index property we are casting it to a PlayerIndex enumeration type.
The final property is the Viewport property. We first check to see if our viewport variable
is null and if so we set it to the graphics device’s viewport. When we set our Viewport
property, we also call our InitializeCamera method again so it can recalculate its view
and projection matrices. We need to set up a private member field for our viewport. We
will allow it to have a default null value so we can declare it as follows:
private Viewport? viewport;
Because we are utilizing the Viewport type we will need to add the following using statement
to our code:
using Microsoft.Xna.Framework.Graphics;
The only thing left for us to do now is to actually update our game’s drawing code to
draw our scene twice. Because we are going to have to draw our scene twice (once for
each camera) we will need to refactor our Draw code into a DrawScene method and pass in
a camera reference. Our new code for the new Draw method is as follows:
protected override void Draw(GameTime gameTime)
{
graphics.GraphicsDevice.Viewport = camera.Viewport;
DrawScene(gameTime, camera);
if (twoPlayers)
{
graphics.GraphicsDevice.Viewport = camera2.Viewport;
DrawScene(gameTime, camera2);
//now clear the thick horizontal line between the two screens
graphics.GraphicsDevice.Viewport = separatorViewport;
graphics.GraphicsDevice.Clear(Color.Black);
}
base.Draw(gameTime);
}
We took all of the code that was inside of this method and put it into a new method
DrawScene(GameTime gameTime, Camera camera). The code we put into the DrawScene
method did not change from how it looked when it resided inside of the Draw method.
The first thing we do with the preceding code is set our graphics device’s viewport to be
what our camera’s viewport is. We then draw the scene passing in our camera. Then we
check to see if we have two players; if so we set the viewport appropriately and finally
draw the scene for that camera. We can run our application and see that it is using a split
screen! The screen shot of this split screen demo can be seen in Figure 5.1.
Creating a Split Screen 109

0 komentar: