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

Microsoft XNA Game Studio Creator’s Guide- P13 pptx

30 249 0

Đ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

Nội dung

MICROSOFT XNA GAME STUDIO CREATOR’S GUIDE 338 pointSpriteEffect.Techniques[0].Passes[0].End(); pointSpriteEffect.End(); } The code required to draw the particle using point sprites is very similar to code that draws any textured primitive surface. Scaling for the entire group of particles is triggered once—based on the distance between the camera and the group of particles. Each fire particle is rendered individually. The group of particles is moved into posi- tion and then each individual particle is translated from the fire base to its own posi- tion in the roaring fire. The particle’s life level, which ranges between 0 for dead and 1 for full life, is passed to the shader so it can be used to fade the color of the flame and shrink 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( world*cam.viewMatrix*cam.projectionMatrix); pointSpriteEffectTexture.SetValue(particleTexture); pointSpriteEffectFade.SetValue(particle[i].life); pointSpriteEffectProjection.SetValue(cam.projectionMatrix); pointSpriteEffectViewport.SetValue( GraphicsDevice.Viewport.Height); // 5: draw object-select vertex type, primitive type, # primitives ParticleShader(vertexBuffer); } } 339 CHAPTER 20 Particle Effects Inside the Draw() 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; This InitializeTorch() 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: void InitializeTorch(){ torchModel = Content.Load<Model>("Models\\torchModel"); matTorch = new Matrix[torchModel.Bones.Count]; torchModel.CopyAbsoluteBoneTransformsTo(matTorch); } InitializeTorch() can be called from the Initialize() 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){ // 1: declare matrices Matrix world, translation, scale; // 2: initialize matrices scale = Matrix.CreateScale(0.50f, 0.50f, 0.50f); translation = Matrix.CreateTranslation(0.0f, 0.35f, -5.0f); foreach (ModelMesh mesh in model.Meshes){ // 3: build cumulative matrix using I.S.R.O.T. sequence // 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 the other draw routines that are called. DrawTorch() must be called before the point sprites are rendered to ensure that the point sprites are layered properly over the 3D model: DrawTorch(torchModel); To observe deviant layering when ZWriteEnable is false, try calling DrawTorch() 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. MICROSOFT XNA GAME STUDIO CREATOR’S GUIDE 340 FIGURE 20-3 Draw order issues for point sprites when ZWriteEnable is false 341 Setting ZWriteEnable in the shader to false ensures that the point sprites will be blended together. However, sometimes setting ZWriteEnable to true looks 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 environments—on different-sized windows. You should consider this in your de- cision as to whether or not to use ZWriteEnable. With the DestBlend state 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 the Draw() 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. C HAPTER 20 REVIEW EXERCISES 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. CHAPTER 20 Particle Effects This page intentionally left blank CHAPTER CHAPTER 21 Keyframe Keyframe Animations Animations 344 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 create the “in-betweens.” In computer games, the keyframes still define the most important stages of the animation, but interpolation is used to fill in the frames in between. This can 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 caution flag. Using keyframes, you can control the course that the pace car follows as it leads the pack and then eventually drives off into the pit. By the end of this chapter, you will be able to use keyframes to map out a route and regulate the speed of this sort of animation. The proper technique is to use a timeline to control the speed of animations; this allows the animation to be rendered at the same speed regardless of the system that runs 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 the difference in time between the current and previous frame. Interpolation is a similar process, but it offers other possibilities for moving objects on linear and curved paths. 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. I NTERPOLATION Interpolation can be used to project the location of a game object based on the ex- pected time of arrival at the destination. For example, if the time between the starting frame and ending frame of an object is 10 seconds, and the object is expected to travel 5 units on the X plane and 10 units on the Z plane, then interpolation can be used to estimate 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. C URVES When mapping out keyframes on your timeline, you probably won’t always want your vehicles traveling in a straight line. You might want to use a curve to map out a path for a keyframe animation. This chapter uses Bézier curves to fulfill this role, but you could use other types of curves for the same task. Most splines are calculated by similar methods as the Bézier curve, so the Bézier curve provides a good example of how 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, and two 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. 345 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 * fraction 2 * (1 – fraction) + V end * fraction 3 The following example puts this formula to use. K EYFRAME ANIMATION EXAMPLE 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. CHAPTER 21 Keyframe Animations FIGURE 21-1 Jet travels along Bezier curve that has four control points FIGURE 21-2 CF-18 fighter jet, animated using a series of straight lines and Bézier curves The code for this example starts with either the MGHWinBaseCode or the MGH360BaseCode project available on this book’s website. A fixed period is specified for completing the combined sections. The total anima- tion time needed to complete all combined routes is 11,200 milliseconds (11.2 sec- onds). At each pass through Update(), the algorithm checks to determine how far along the path the object should be at that specific time. The position of the CF-18 is projected using the keyframes, which store the fixed end points of the lines and points on the Bézier curves. The first step is to store each route. Two Bézier curves are being used, and two lines 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 from Initialize(): InitializeRoutes(); MICROSOFT XNA GAME STUDIO CREATOR’S GUIDE 346 347 CHAPTER 21 Keyframe Animations 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 from Initialize(): 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. The KeyFrameNumber() function performs this check: private int KeyFrameNumber(){ float timeLapsed = 0.0f; // retrieve current leg of trip for (int i = 0; i < NUM_KEYFRAMES; i++) { if (timeLapsed > tripTime) return i - 1; else timeLapsed += keyFrameTime[i]; } return 3; // special case for last route } [...]... that are accessed by the effect parameters in the game application The global values allow you to send in different values for the camera and transformation matrices, textures, point light color, and point light intensity: float4x4 float4x4 wvpMatrix; worldMatrix; 365 Lighting C H A P T E R 366 MICROSOFT float4 float4 float Texture XNA GAME STUDIO CREATOR’S GUIDE lightPosition; color; lightIntensity;... 14): jetModel = Content.Load("Models\\cf18"); jetMatrix = new Matrix[jetModel.Bones.Count]; jetModel.CopyAbsoluteBoneTransformsTo(jetMatrix); 349 Keyframe Animations C H A P T E R 350 MICROSOFT XNA GAME STUDIO CREATOR’S GUIDE 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 the BasicEffect object is explained... a key differentiator between a high-quality game and an amateur game If you’re not sure about this, walk into any arcade and look at the games around you Most likely, you will be more impressed with the games that use advanced lighting techniques By adding interesting lighting—even in small amounts—you can excite your players’ eyes with the details of your game This chapter shows you how to program... normal vector is used to calculate the intensity of the light reflected from the surface Each normal is drawn at right angles to the surface being rendered 355 Lighting C H A P T E R 356 MICROSOFT XNA GAME STUDIO CREATOR’S GUIDE When rendering complex shapes using primitive objects, you will need to calculate the normal and store it with each vertex Refer to Chapter 15 for details on how to calculate... directional lighting is implemented in a daytime setting, so there will already be a high level of ambience and diffuse lighting around to brighten the area 357 Lighting C H A P T E R 358 MICROSOFT XNA GAME STUDIO CREATOR’S GUIDE FIGURE 22-1 Before and after directional lighting With the BasicEffect class, the specular light increases the brightness of the primitive surface face Once you have the original... basicEffect.DirectionalLight0.DiffuseColor // diffuse color = new Vector3(0.2f, 0.2f, 0.2f); // rgb range 0 to 1 basicEffect.DirectionalLight0.SpecularColor // highlight color 359 Lighting C H A P T E R 360 MICROSOFT XNA GAME STUDIO CREATOR’S GUIDE = new Vector3(0.5f, 0.5f, 0.37f); // rgb range 0 to 1 basicEffect.DirectionalLight0.Direction // set normalized = Vector3.Normalize(new Vector3(0.0f,-1.0f,-1.0f));// direction... one row at a time for (int Z = 0; Z < NUM_ROWS - 1; Z++){ graphics.GraphicsDevice.DrawIndexedPrimitives( 361 Lighting C H A P T E R 362 MICROSOFT XNA GAME STUDIO PrimitiveType.TriangleStrip, Z * NUM_COLS, 0, NUM_COLS * NUM_ROWS, 0, 2 * (NUM_COLS - 1)); // // // // // // CREATOR’S GUIDE primitive type start point in vertex buffer vertex buffer offset total verts in vertex buffer index buffer offset index... reflection is brightest when the light shines in a direction directly opposite to the normal vector FIGURE 22-2 Lighting vectors used in the Phong reflection model 363 Lighting C H A P T E R 364 MICROSOFT XNA GAME STUDIO CREATOR’S GUIDE If you need to understand the math in more detail, or you need a refresher on dot products and vector math, consider reviewing Chapter 15 Calculating Point Light Because point...348 MICROSOFT XNA GAME STUDIO CREATOR’S GUIDE The next function uses the Bézier curve to figure out what part of the curve your object is on Unlike the last function, which checked the time, this one is checking the physical... route the fighter jet is on and then uses the appropriate 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 . MICROSOFT XNA GAME STUDIO CREATOR’S GUIDE 338 pointSpriteEffect.Techniques[0].Passes[0].End(); pointSpriteEffect.End(); } The. that the flame no lon- ger appears to come from the torch, as shown in Figure 20-3. MICROSOFT XNA GAME STUDIO CREATOR’S GUIDE 340 FIGURE 20-3 Draw order issues for point sprites when ZWriteEnable. end } You call the jet initialization routine from Initialize(): InitializeRoutes(); MICROSOFT XNA GAME STUDIO CREATOR’S GUIDE 346 347 CHAPTER 21 Keyframe Animations Next, you must add module declarations

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