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

Microsoft XNA Game Studio Creator’s Guide- P13 pptx

30 250 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

Định dạng
Số trang 30
Dung lượng 291,26 KB

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

Nội dung

First, declara-tions in the game class are required to store the torch model object and the array for the torch’s bone transformations: Model torchModel; Matrix[] matTorch; ThisInitializ

Trang 1

1 for full life, is passed to the shader so it can be used to fade the color of the flame andshrink the size as each particle rises away from the core of the fire:

private void DrawParticles(){

// 1: declare matrices

Matrix world, translateParticle, translateGroup;

// scale the point sprite by cam distance to the group of particles Vector3 particlesPosition = new Vector3(0.0f, 0.42f, -5.0f);

// 2: initialize matrices

translateGroup = Matrix.CreateTranslation(particlesPosition);

for (int i = 0; i < NUM_PARTICLES; i++){

// translate each individual particle translateParticle = Matrix.CreateTranslation(particle[i].position);

// 3: build cumulative world matrix using I.S.R.O.T sequence // identity, scale, rotate, orbit(translate & rotate), translate world = translateGroup * translateParticle;

// 4: set shader variables pointSpriteEffectWVP.SetValue(

Trang 2

Inside theDraw()method, a call can be made to draw the fire:

DrawParticles();

Finally, as one last touch to make the example a little more interesting, we’ll add a

model torch For this to work, the torch.fbx file must be referenced from a Models

folder under the Content node in the Solution Explorer The torch.bmp texture will

also need to be placed in the Models folder in your project but doesn’t need to be

refer-enced If the torch.bmp texture is referenced from the Solution Explorer, it will be

con-fused with the torch.fbx model because they both use the same name The torch.fbx

and torch.bmp files can be found in the Models folder on this book’s website

The logic and methods used to load and draw the models are the same as explained

in Chapter 14, so the details behind these next steps will be minimal First,

declara-tions in the game class are required to store the torch model object and the array for

the torch’s bone transformations:

Model torchModel; Matrix[] matTorch;

ThisInitializeTorch()method includes the code to load the torch and set

the transformation matrix for the meshes in it Placing this in the game class allows

you to load the model:

InitializeTorch()can be called from theInitialize()method to read

in the torch.fbx file when the program begins:

InitializeTorch();

You can add this next method to your game class to draw the torch:

private void DrawTorch(Model model){

foreach (ModelMesh mesh in model.Meshes){

// 3: build cumulative matrix using I.S.R.O.T sequence

Trang 3

// identity,scale,rotate,orbit(translate & rotate),translate world = scale * translation;

foreach (BasicEffect effect in mesh.Effects){ // 4a pass wvp effect.World = matTorch[mesh.ParentBone.Index] * world; effect.View = cam.viewMatrix;

effect.Projection = cam.projectionMatrix;

// 4b set lighting effect.EnableDefaultLighting();

effect.SpecularPower = 0.01f;

} // 5: draw object mesh.Draw();

}

}

The method to draw the torch model is triggered from Draw()along with theother draw routines that are called.DrawTorch()must be called before the pointsprites are rendered to ensure that the point sprites are layered properly over the 3Dmodel:

DrawTorch(torchModel);

To observe deviant layering when ZWriteEnable is false, try callingDrawTorch()after drawing the point sprites You will notice that the flame no lon-ger appears to come from the torch, as shown in Figure 20-3

340

F I G U R E 2 0 - 3

Draw order issues for point sprites when ZWriteEnable is false

Trang 4

SettingZWriteEnablein the shader tofalseensures that the point sprites will

be blended together However, sometimes settingZWriteEnable totruelooks

good when the background is colored the same as the pixels that are supposed to be

transparent, or when the particles are small or disperse You can always experiment

to see what looks good, but remember that a PC game may be played in several

differ-ent environmdiffer-ents—on differdiffer-ent-sized windows You should consider this in your

de-cision as to whether or not to useZWriteEnable

With theDestBlendstate set to 1 in the shader, shiny blending is applied As a

re-sult, the point sprite can only be seen against darker backgrounds To ensure that you

can see the fire against the background, replace the instruction that clears the

back-ground and resets the color inside theDraw()method with this new instruction:

graphics.GraphicsDevice.Clear(Color.Black);

When you run your program, it will show a steady, ever-changing body of fire As

you back away from the fire, the size of the particles will scale properly to match the

size of the primitive ground surface and model torch At any angle the fire particles

will face the camera, so you don’t need to have any billboarding code

This is a cool effect, but it’s really only the beginning of what you can do with

point sprites and particle effects This particle effect would be ideal for creating

ex-plosions, exhaust trails from missiles, stardust, and more You could even increase

the number of textures used or the particle types to make the fire more interesting

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. Starting with the existing algorithm, create an additional particle stream to

simulate smoke from your fire

3. Modify your fire algorithm to create an explosion

Trang 5

This page intentionally left blank

Trang 6

CHAPTER 21

Keyframe Animations

Trang 7

KEYFRAME animations combine a timer and inter-polation to determine the location of

game objects The term keyframe comes from the world of hand-drawn animation.

The senior artists would draw the “key frames” and then other artists would createthe “in-betweens.” In computer games, the keyframes still define the most importantstages of the animation, but interpolation is used to fill in the frames in between Thiscan mean interpolating the position or orientation of an object For example, in a rac-ing game, you might want to include a pace car when the cars are under a cautionflag Using keyframes, you can control the course that the pace car follows as it leadsthe pack and then eventually drives off into the pit By the end of this chapter, youwill be able to use keyframes to map out a route and regulate the speed of this sort ofanimation

The proper technique is to use a timeline to control the speed of animations; thisallows the animation to be rendered at the same speed regardless of the system thatruns it Until now, the examples in this book have generated translational animations

by incrementing X, Y, and Z coordinates by a product of the increment unit and thedifference in time between the current and previous frame Interpolation is a similarprocess, but it offers other possibilities for moving objects on linear and curvedpaths For translations or rotations, a path may be defined for the object and a spe-cific duration of time may be assigned for completing the path

Interpolation can be used to project the location of a game object based on the pected time of arrival at the destination For example, if the time between the startingframe and ending frame of an object is 10 seconds, and the object is expected to travel

ex-5 units on the X plane and 10 units on the Z plane, then interpolation can be used toestimate the object’s location at any time between 0 and 10 seconds At 4 seconds, in-terpolation would project the object to be at X = 2 and Z = 4

When mapping out keyframes on your timeline, you probably won’t always wantyour vehicles traveling in a straight line You might want to use a curve to map out apath for a keyframe animation This chapter uses Bézier curves to fulfill this role, butyou could use other types of curves for the same task Most splines are calculated bysimilar methods as the Bézier curve, so the Bézier curve provides a good example ofhow this family of curves can be implemented in your game algorithms

The Bézier curves in this chapter use four points: a start point, an end point, andtwo control points (see Figure 21-1) The control points provide the user with a way

to stretch or compress the curve Stretching the control points will “push” or “pull”the curve into different shapes

Trang 8

The formula for finding a point on a Bézier curve is based on the relative position

between the start of the curve (0 percent) and the end of the curve (100 percent):

Point on Bezier Curve =

V start * (1 – fraction)3

+ V control 1 * 3 * fraction * (1 – fraction)2

+ V control 2 * 3 * fraction2 * (1 – fraction)

+ V end * fraction3

The following example puts this formula to use

This example demonstrates a timed animation that moves a model CF-18 Hornet

fighter jet on a fixed route Two parts of the route are defined by straight lines and

two parts of the route are defined by Bézier curves The CF-18 fighter jet and route

are shown in Figure 21-2

Trang 9

The code for this example starts with either the MGHWinBaseCode or theMGH360BaseCode project available on this book’s website.

A fixed period is specified for completing the combined sections The total tion time needed to complete all combined routes is 11,200 milliseconds (11.2 sec-onds) At each pass throughUpdate(), the algorithm checks to determine how faralong the path the object should be at that specific time The position of the CF-18 isprojected using the keyframes, which store the fixed end points of the lines and points

anima-on the Bézier curves

The first step is to store each route Two Bézier curves are being used, and twolines are being used The Bézier curve stores four control points:

private Vector3[] bezierA = new Vector3[4]; // route 1

private Vector3[] lineA = new Vector3[2]; // route 2

private Vector3[] bezierB = new Vector3[4]; // route 3

private Vector3[] lineB = new Vector3[2]; // route 4

This first routine will initialize the jet's route:

private void InitializeRoutes(){

// length of world quadrant

const float END = -BOUNDARY;

// 1st Bezier curve control points (1st route)

bezierA[0] = new Vector3( END+5.0f, 0.4f, 5.0f); // start

bezierA[1] = new Vector3( END+5.0f, 2.4f, 3.0f*END); // ctrl 1

bezierA[2] = new Vector3(-END-5.0f, 4.4f, 3.0f*END); // ctrl 2

bezierA[3] = new Vector3(-END-5.0f, 5.4f, 5.0f); // end

// 1st line between Bezier curves (2nd route)

lineA[0] = new Vector3(-END-5.0f, 5.4f, 5.0f); // start

lineA[1] = new Vector3(-END-5.0f, 5.4f, -5.0f); // end

// 2nd Bezier curve control points (3rd route)

bezierB[0] = new Vector3(-END-5.0f, 5.4f, -5.0f); // start

bezierB[1] = new Vector3(-END-5.0f, 4.4f, -3.0f*END); // ctrl 1

bezierB[2] = new Vector3( END+5.0f, 2.4f, -3.0f*END); // ctrl 2

bezierB[3] = new Vector3( END+5.0f, 0.4f, -5.0f); // end

// 2nd line between Bezier curves (4th route)

lineB[0] = new Vector3( END+5.0f, 0.4f, -5.0f); // start

lineB[1] = new Vector3( END+5.0f, 0.4f, 5.0f); // end

}

You call the jet initialization routine fromInitialize():

InitializeRoutes();

346

Trang 10

Next, you must add module declarations to initialize the time for the whole trip

and each individual section of the trip:

private float[] keyFrameTime = new float[4];

private float tripTime = 0.0f;

private const float TOTAL_TRIP_TIME = 11.2f;

private const int NUM_KEYFRAMES = 4;

To initialize the timeline, you will provide five values Each of the total times

be-tween keyframes is stored Also, the total trip time is stored

private void InitializeTimeLine(){

keyFrameTime[0] = 4.8f; // time to complete route 1

keyFrameTime[1] = 0.8f; // time to complete route 2

keyFrameTime[2] = 4.8f; // time to complete route 3

keyFrameTime[3] = 0.8f; // time to complete route 4

}

Call the time-initialization routine fromInitialize():

InitializeTimeLine();

The next step is to add module declarations for storing the Y rotation of the jet

model This will correct the jet so that it is always pointing in the correct direction:

Vector3 currentPosition, previousPosition;

float Yrotation;

After the jet is pointing in the proper direction, your next hurdle is keeping track of

which route the jet is currently flying Because we know how long each route will

take, it’s easy to check the time, and then figure out which route the jet is currently

following TheKeyFrameNumber()function performs this check:

private int KeyFrameNumber(){

float timeLapsed = 0.0f;

// retrieve current leg of trip

for (int i = 0; i < NUM_KEYFRAMES; i++)

Trang 11

The next function uses the Bézier curve to figure out what part of the curve yourobject is on Unlike the last function, which checked the time, this one is checking thephysical location of the jet For this example, we need two different ways of deter-mining position; the first one checks the position on the Bézier curve:

private Vector3 GetPositionOnCurve(Vector3[] bezier, float fraction){

// returns absolute position on curve based on relative return // position on curve (relative position ranges from 0% to 100%) bezier[0] * (1.0f - fraction) * (1.0f - fraction) * (1.0f - fraction) + bezier[1] * 3.0f * fraction * (1.0f - fraction) * (1.0f - fraction) + bezier[2] * 3.0f * fraction * fraction * (1.0f - fraction) +

bezier[3] * fraction * fraction * fraction;

}

The second position-checking function uses linear interpolation to figure outwhich part of a line the model jet is on:

private Vector3 GetPositionOnLine(Vector3[] line, float fraction){

// returns absolute position on line based on relative position

// on curve (relative position ranges from 0% to 100%)

Vector3 lineAtOrigin = line[1] - line[0];

return line[0] + fraction*lineAtOrigin;

}

The next function to add,UpdateKeyframeAnimation(), is the workhorse ofthis example It uses all of the logic that you have added to update the animation Thefunction determines which part of the route the fighter jet is on and then uses the ap-propriate check to find out where it should be on that route:

private void UpdateKeyframeAnimation(GameTime gameTime){

// update total trip time, use modulus to prevent variable overflow tripTime += (gameTime.ElapsedGameTime.Milliseconds/1000.0f);

tripTime = tripTime%TOTAL_TRIP_TIME;

// get the current route number from a total of four routes

int routeNum = KeyFrameNumber();

// sum times for preceding keyframes

Trang 12

float timeBetweenKeys = tripTime - keyFrameStartTime;

// calculate percentage of current route completed

float fraction = timeBetweenKeys/keyFrameTime[routeNum];

// get current X, Y, Z of object being animated

// find point on line or curve by passing in % completed

switch (routeNum){

case 0: // first curve

currentPosition = GetPositionOnCurve(bezierA, fraction); break;

case 1: // first line

currentPosition = GetPositionOnLine(lineA, fraction); break;

// get rotation angle about Y based on change in X and Z speed

Vector3 speed = currentPosition - previousPosition;

Next, you need to add the jet model to your program To start the process of

load-ing the fighter jet model, add these module declarations:

Model jetModel;

Matrix[] jetMatrix;

When you initialize the CF-18 model, make sure the cf18.x file is referenced in the

Models folder under the Content node within your project (with the matching

cf18Color.jpg file) If the Models folder is not present, you will need to add one You

can find these files in the Models folder on this book’s website Add this code to load

and initialize the jet from inside theLoadContent()method (this code is explained

in Chapter 14):

jetModel = Content.Load<Model>("Models\\cf18");

jetMatrix = new Matrix[jetModel.Bones.Count];

jetModel.CopyAbsoluteBoneTransformsTo(jetMatrix);

Trang 13

Now it’s time to actually draw the jet model Most of this code should be familiar

to you—it has been used throughout this book Lighting with theBasicEffectject is explained in Chapter 22

ob-private void DrawCF18(Model model){

// 3: build cumulative world matrix using I.S.R.O.T sequence

// identity, scale, rotate, orbit(translate & rotate), translate

world = scale * rotateX * rotateY * translate;

// set shader parameters

foreach (ModelMesh mesh in model.Meshes){

foreach (BasicEffect effect in mesh.Effects){

effect.World = jetMatrix[mesh.ParentBone.Index] * world; effect.View = cam.viewMatrix;

350

Trang 14

The keyframe animation created in this chapter is actually similar to a timeline

an-imation you would create in Macromedia Flash or chUmbaLum sOft’s MilkShape

As you can see, it’s easy to implement a keyframe animation in code

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

1. Implement the step-by-step example demonstrated in this chapter, if you

have not already done so

2. Begin with the completed airplane example from Chapter 8, and convert

this solution so that it uses three Bézier curves to move the airplane on a

path in the X, Y, and Z planes

Trang 15

This page intentionally left blank

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

TỪ KHÓA LIÊN QUAN