1. Trang chủ
  2. » Công Nghệ Thông Tin

Microsoft XNA Game Studio Creator’s Guide- P15 ppsx

30 170 0
Tài liệu đã được kiểm tra trùng lặp

Đ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

Thông tin cơ bản

Tiêu đề Microsoft Xna Game Studio Creator’s Guide
Trường học Standard University
Chuyên ngành Game Development
Thể loại Hướng dẫn
Thành phố City Name
Định dạng
Số trang 30
Dung lượng 422,38 KB

Các công cụ chuyển đổi và chỉnh sửa cho tài liệu này

Nội dung

A custom con-tent pipeline processor will read the bulk data from your media files, process it, andthen store it in intermediate form.. If any changes are detected, when you build your g

Trang 1

DrawFonts("DPad.Up: released", ++line);

if (zunePad.DPad.Down == ButtonState.Pressed) // Down

DrawFonts("DPad.Down: pressed", ++line);

else

DrawFonts("DPad.Down: released", ++line);

if (zunePad.DPad.Left == ButtonState.Pressed) // Left

DrawFonts("DPad.Left: pressed", ++line);

else

DrawFonts("DPad.Left: released", ++line);

if (zunePad.DPad.Right == ButtonState.Pressed) // Right

DrawFonts("DPad.Right: pressed", ++line);

else

DrawFonts("DPad.Right: released", ++line);

// A - press center of Zune pad

if (zunePad.Buttons.A == ButtonState.Pressed) // A

DrawFonts("A: pressed", ++line);

else

DrawFonts("A: released", ++line);

// B - press top right button

if (zunePad.Buttons.B == ButtonState.Pressed) // B

DrawFonts("B: pressed", ++line);

else

DrawFonts("B: released", ++line);

// running finger on Zune pad

float X = zunePad.ThumbSticks.Left.X; // thumbstick X

float Y = zunePad.ThumbSticks.Left.Y; // thumbstick Y

DrawFonts("ThumbSticks.Left.X", ++line);

DrawFonts("= " + X.ToString(), ++line);

DrawFonts("ThumbSticks.Left.Y", ++line);

DrawFonts("= " + Y.ToString(), ++line);

// show user how to exit game – back button is top left button

++line; // Back button is already used to exit in the template

DrawFonts("Press Back button", ++line);

DrawFonts("to exit.", ++line);

}

With everything in place you can now trigger the code to display the input devicestatus from Draw()

ShowInputDeviceStatus();

Trang 2

When you run your code, you will see the press and release states of your controls

as well as the X and Y position of your finger on the Zune pad You can see from this

tiny example that Zune input handling is simple yet flexible enough to allow players

a full range of control over their game play

After enabling keyboard, mouse, game pad, and Zune input, you literally will

have placed control of your game engine in the hands of your players Your world is

now their oyster

To get the most from this chapter, try out these chapter review exercises

1. Try the step-by-step examples provided in this chapter, if you have not

already done so

2. If you run the solution from Exercise 1, when you left-click the mouse, the

word “Pressed” appears in the window Track the mouse state so you can

toggle between displaying pressed and released states in the game window

(A similar check exists that enables you to toggle between On and Off

states when pressing the letter T.)

3. In the “Collision Detection Using Lines and Spheres” solution from

Chapter 18, make your game pad rumble every time the camera collides

with something

Trang 4

CHAPTER 24

Content Pipeline Processors

Trang 5

Using predefined content types in XNA allows for easy deployment on your PC orXbox 360 For example, the XNA Framework offers built-in methods for loadingand accessingTexture2D, XACT(audio),XML,Effect(shaders), AutodeskFBX(model), andX(model) objects This chapter shows how to extend the content pipe-line to load files not supported out of the box by the XNA Framework

Aside from allowing you to load any graphics or data file on the PC and Xbox 360,custom content processors can also enable faster game startup times A custom con-tent pipeline processor will read the bulk data from your media files, process it, andthen store it in intermediate form This compiled binary intermediate data is stored in

an xnb file

The content processor also tracks changes to your media and to the cessing code itself If any changes are detected, when you build your game, the con-tent processor reloads the bulk data from your media files and recompiles it.Otherwise, if no changes are detected, the compiled data is read from the xnb filethat stored it Being able to read preprocessed data can be a big timesaver when largecompressed media files are loaded at game launch

content-pro-For the Quake II model loader (used in Chapter 26), setting up the model for XNA

deployment requires loading the bulk data, organizing the faces in the polygonshapes from the indexed information stored in the file, and generating the normalvectors to enable lighting This processing time can add unwanted delays to yourgame launch However, if you use a custom content processor to decompress and or-ganize your md2 data in an intermediate format, your game will not read from the

*.md2 file again Instead, the game will read the intermediate data from your piled xnb file during any consecutive run The initial data processing is only per-formed when either the original media file changes or the processor code is modified

com-In short, you will notice an improvement to your load times when using the contentprocessor

The content processor loads your external media and locates existing processor ponents All custom processors must derive from the ContentProcessor baseclass in a manner similar to the following:

com-public class MyContentProcessor : ContentProcessor<Tinput,Toutput>

{}

TinputandToutputare the user-defined input and output classes you create toinput your bulk data and output your compiled data in the required format

Trang 6

TheContentImporterclass is defined with anImportmethod to read

unpro-cessed data from your original media file The class declaration is preceded by the

ContentImporterattribute to list the file extension(s) associated with this loader

and the processor used to convert it to a compiled format Additional extensions,

separated by commas, can be added to the string

[ContentImporter(string fileExt, DefaultProcessor = string processorName)]

public class MyContentImporter : ContentImporter<TerrainContent>{

public override MyCustomContent Import(String filename,

ContentImporterContext context){}

}

Inside the Import method, the file is opened and can be read with a

Sys-tem.IO.Filemethod or through theMemoryStreamand BinaryReader

ob-jects Using these objects, you can read text and binary formats

For this example, the System.IO.File ReadAllBytes()method reads in

the bytes from the raw image However, if you were reading text input, this could be

read with theFileobject’sReadAllText()method You can also load your data

withMemoryStreamandBinaryReaderobjects to read data in specific chunks to

handle integers, floats, vectors, and many other data types

After the data has been read, it is structured according to your own custom

data-storage class You define how you want the data organized and how you want it

exported to the xnb file

ContentTypeWriter

TheContentTypeWriterclass assists in writing your intermediary data as binary

output to the xnb file Output is written with theWrite()method override The

GetRuntimeType()method returns the custom data type of the processed

con-tent TheGetRuntimeReader()reader method returns the intermediate format

reader’s location:

[ContentTypeWriter]

public class MyContentWriter : ContentTypeWriter<MyCustomContent>{

protected override void Write(ContentWriter wr,

Trang 7

public class MyReader : ContentTypeReader<MyCustomContent>{

protected override MyCustomContent Read(ContentReader input,

MyCustomContent existingInstance){} }

When theRead()method override is finished importing your managed data, itreturns this data in the format you defined in your storage class This data is thenmade available to your game project

This example demonstrates how to create a custom content processor that loads aheight map from a raw image This content processor converts the height data togenerate position and normal vectors The vertices created from this newly generateddata are used in Chapter 25 to build a rolling landscape To keep the content proces-sor demonstration in this chapter focused, the terrain is not fully implemented How-

Trang 8

ever, the height data associated with the current camera position is updated as it

moves through the world and this height information is printed in the window

XNA does not provide a code library for loading raw images, so you need an

al-ternate way to load them You can get away withBinaryReadermethods to load

them on Windows On the Xbox 360, theBinaryReadermethods will find your

.raw files if you place your media resources in the debug folder when deploying your

solution However, to handle these files more gracefully, you should create a custom

processor to load them through the content pipeline

Load performance is another reason to use the content processor to load your

ter-rain data The raw image stores an array of bytes When it is used as a height map,

each pixel stores height information between 0 and 255 The pixels from this

rectan-gular raw image are mapped to the rectanrectan-gular ground in your world To

superim-pose each pixel over the corresponding section of ground, you will need to calculate

the position vector associated with each pixel Also, to enable lighting, you will need

to calculate the normal vector associated with each pixel in the raw file

This example begins with the “Directional Lighting Example” from Chapter 22

This project can be found in the Solutions folder on this book’s website

Building a Custom Content Processor in Windows

In order to compile the content processor into a DLL that can be used either on

Win-dows or the Xbox 360, you must add a separate Content Pipeline Extension Library

project to your solution from the Solution Explorer To add it, right-click the

solu-tion name and choose Add | New Project When prompted in the Add New Project

di-alog, select Content Pipeline Extension Library The Content Pipeline Extension

project is used because it already has the proper assembly references and does not

contain the Content subproject For this example, name your content pipeline

pro-ject as TerrainPipeline

Once your new library project has been added, you will be able to see it as a

sepa-rate project in the Solution Explorer Rename the cs code file that is genesepa-rated to

TerrainContent.cs Then replace the code in this file with the following shell to

im-plement your own content processor:

Trang 9

Your custom data class is designed by you to store your data in the format you quire For this example, the user-defined classTerrainContentstores bulk heightdata from the raw file It then uses this data to generate position and normal vectorsalong with the terrain dimensions and stores these new values at the class level.TheTerrainContentclass is referenced throughout your content processor togenerate and access your height map data, so it must be made public Also, to ensurethat the height map is mapped properly to the rectangular world, the number of rowsand columns, the world dimensions, and the cell height and width are also made pub-lic This terrain-defining code belongs in the TerrainPipeline namespace ofyour TerrainContent.cs file:

re-public class TerrainContent{

public byte[] height;

public Vector3[] position;

public Vector3[] normal;

public float cellWidth, cellHeight;

// hard coded values to match height map pixel and world dimensions public int NUM_ROWS = 257;

public int NUM_COLS = 257;

public float worldWidth = 16.0f;

public float worldHeight = 16.0f;

public float heightScale = 0.0104f;

// constructor for raw data - used during bulk data import

public TerrainContent(byte[] bytes){

// sets height and width of cells made from pixels in raw file

public void setCellDimensions(){

cellWidth = 2.0f*worldWidth/(NUM_COLS - 1);

cellHeight = 2.0f*worldHeight/(NUM_ROWS - 1);

}

// generate X, Y, and Z position data where Y is the height.

private void generatePositions(){

position = new Vector3[NUM_ROWS*NUM_COLS];

Trang 10

for (int row = 0; row < NUM_ROWS; row++){

for (int col = 0; col < NUM_COLS; col++){

float X = -worldWidth + col*cellWidth;

float Y = height[row*NUM_COLS + col]*heightScale;

float Z = -worldHeight + row*cellHeight;

position[col + row*NUM_COLS] = new Vector3(X, Y, Z);

}

}

}

// generate normal vector for each cell in height map

private void generateNormals(){

Vector3 tail, right, down, cross;

normal = new Vector3[NUM_ROWS*NUM_COLS];

// normal is cross product of two vectors joined at tail

for (int row=0; row<NUM_ROWS - 1; row++){

for (int col = 0; col < NUM_COLS - 1; col++){

tail = position[col + row*NUM_COLS];

right = position[col + 1 + row*NUM_COLS] - tail;

down = position[col + (row + 1)*(NUM_COLS)] - tail;

cross = Vector3.Cross(down, right);

With theTerrainContentclass in place to store the terrain data, a derived

in-stance of theContentProcessorclass is needed as a processor interface for the

Trang 11

Extending the ContentImporter class enables the overridden Import()method to read your data from the original media file TheContentImporterat-tribute precedes theContentImporterclass definition to list the file extensionsthat can use this importer.

For this example, theReadAllBytes()method reads in the bytes from the rawimage Of course, you can use other methods to read your data:

// stores information about importer, file extension, and caching

[ContentImporter(".raw", DefaultProcessor = "TerrainProcessor")]

// ContentImporter reads original data from original media file

public class TerrainPipeline : ContentImporter<TerrainContent>{

// reads original data from binary or text based files

public override TerrainContent Import(String filename,

ContentImporterContext context){

byte[] bytes = File.ReadAllBytes(filename);

TerrainContent terrain = new TerrainContent(bytes);

return terrain; // returns compiled data object }

}

Once the data is read, it is passed to your custom data class This data initializes

a custom data object that organizes the data as you need it The data object is thenreturned to your processor so it can be written in a compiled binary format to an.xnb file

Adding the extendedContentTypeWriterclass to yourTerrainPipelinenamespace allows you to output your compiled binary custom data to an xnb file.TheWrite()method receives your integer, float, and vector data and then writes it

in binary format to the file When you write your data, you have to write it in the quence you want to retrieve it The writer/reader combination uses a “first in firstout” sequence for your data storage and access

se-AGetRuntimeType() method is included in theContentTypeWriterclass

to return the custom data type of the processed content to be loaded at run time AGetRunTimeReader()method is also added to return the intermediate contentreader’s location in the solution:

// write compiled data to *.xnb file

[ContentTypeWriter]

public class TerrWriter : ContentTypeWriter<TerrainContent>{

protected override void Write(ContentWriter cw,

TerrainContent terrain){

cw.Write(terrain.NUM_ROWS);

Trang 12

for (int row = 0; row < terrain.NUM_ROWS; row++){

for (int col = 0; col < terrain.NUM_COLS; col++){

// Sets the CLR data type to be loaded at runtime.

public override string GetRuntimeType(TargetPlatform targetPlatform){

return "TerrainRuntime.Terrain, TerrainRuntime,

Version=1.0.0.0, Culture=neutral";

}

// Tells the content pipeline about reader used to load xnb data

public override string GetRuntimeReader(TargetPlatform targetPlatform){

return "TerrainRuntime.TerrainReader, TerrainRuntime,

Version=1.0.0.0, Culture=neutral";

}

}

At run time, the Content reader reads the compiled data from the xnb file A

sepa-rate project is used for this reader To create it, right-click the solution, choose Add |

New Project, and then choose Content Pipeline Extension Library In the Add New

Project dialog, assign it the name TerrainRuntime to match the value given in the

GetRuntimeReader()method from inside the content processor For readability,

rename the project code file that is generated to TerrainReader.cs

The ContentReader is derived from the BinaryReader class and exposes

similar methods for retrieving data in the segments you need Once the data is read,

an object of your custom data class is initialized This custom data object is then

made available to your XNA game project as soon as the data is loaded:

using System;

using System.Collections.Generic;

using Microsoft.Xna.Framework;

using Microsoft.Xna.Framework.Content;

Trang 13

namespace TerrainRuntime{

public class Terrain{

// these variables store values that are accessible in game class public byte[] height;

public Vector3[] position;

public Vector3[] normal;

public int NUM_ROWS, NUM_COLS;

public float worldWidth, worldHeight, heightScale;

public float cellWidth, cellHeight;

normal = new Vector3[NUM_ROWS*NUM_COLS];

// read in position and normal data to generate height map for (int row = 0; row < NUM_ROWS; row++){

for (int col = 0; col < NUM_COLS; col++){

position[col + row*NUM_COLS] = cr.ReadVector3(); normal[col + row*NUM_COLS] = cr.ReadVector3(); }

} } }

// loads terrain from an XNB file.

public class TerrainReader : ContentTypeReader<Terrain>{

protected override Terrain Read(ContentReader input,

Terrain existingInstance){

return new Terrain(input);

} }

}

Trang 14

The game project must reference the TerrainRuntime project To reference this

as-sembly, right-click the game project’s References folder in the Solution Explorer and

choose Add Reference In the Add Reference dialog, select the TerrainRuntime

pro-ject from the Propro-jects tab and click OK You will now see this TerrainRuntime

refer-ence listed in your game project (see Figure 24-1) The game project’s Content project

needs to reference the TerrainPipeline to load the raw content To add it, right-click

the References node under the Content folder and choose Add Reference Then in the

Add Reference dialog, select the TerrainPipeline project from the Projects tab (see

Figure 24-1)

Wherever you want to use your custom data type, the new namespace for your

runtime content must be included in your original game project:

Trang 15

Next, your heightMap.raw file must be referenced in the Images folder for yourgame project You can get this file from the Images directory on this book’s website.Once the heightMap.raw file is referenced, you can set its properties to use yourcustom content processor to load it First, you need to build your TerrainPipeline andTerrainRuntime projects to see their references when setting up the heightMap.rawfile You can build each project by right-clicking each project name in the SolutionExplorer and choosing Build Then, to assign the custom content processor to readthe raw file, right-click heightMap in the Solution Explorer and select Properties.Under the Build Action property drop-down, select Compile The Content Importerattribute should be set toTerrainPipeline, and the Content Processor attributeshould be set toTerrainProcessor Figure 24-2 shows the content pipeline prop-erty settings for the heightMap.raw file.

In your game project you need an instance of the terrain object at the class level:Terrain terrain;

F I G U R E 2 4 - 2

Media file references the custom content importer and processor.

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

TỪ KHÓA LIÊN QUAN