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

Microsoft XNA Game Studio Creator’s Guide- P11 pptx

30 306 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
Năm xuất bản 2023
Thành phố Standard City
Định dạng
Số trang 30
Dung lượng 260,23 KB

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

Nội dung

Updated Look Vector = qRotation * qLook * qRotation' With the result from this product, theViewcan be updated: Updated View = Updated Look Vector + Position Now you will apply this logic

Trang 1

vector that stores a rotation around an axis Quaternion math is used to calculate anincrement to update the camera’s Look vector.

We can express the value of the Look vector like this:

Look = View - Position

By rearranging this equation we can say the following:

View = Look + Position

If the quaternion represents the updatedLookvector, then

Updated View = Updated Look Vector + Position

Updated Look VectorThe formula for calculating the updatedLookvector is:

qRotation * qLook * qRotation' (qRotation' is the conjugate of qRotation)

Each of the three operands will be discussed next

Local Rotation QuaternionThe first quaternion that is used to calculate the updatedLookvector,qRotation,

is a local rotation Quaternion theory provides a formula for computing the local tation In this case, the local rotation is generated using a direction vector for X, Y,and Z Rotations about the X axis are applied using the Lookvector Rotationsabout the Y axis are applied using theRightdirection vector The rotation anglestored in the W component is obtained from the deviation of the mouse (orthumbstick) from the center of the window With this information, we can generatethe local rotation by writing the following:

ro-qRotation.W = cos(MouseDeviationFromCenter/2)

qRotation.X = UnitDirection.X * sin(MouseDeviationFromCenter/2)

qRotation.Y = UnitDirection.Y * sin(MouseDeviationFromCenter/2)

qRotation.Z = UnitDirection.Z * sin(MouseDeviationFromCenter/2)

Using the Look Vector as a QuaternionThe next quaternion used in the formula for the updatedLookvector is based on theLookdirection:

qLook.X = Look.X qLook.Y = Look.Y qLook.Z = Look.Z qLook.W = 0

278

Trang 2

Conjugate Quaternion

A conjugate quaternion is used to calculate the updatedLookvector The conjugate

is created by negating a quaternion vector’s X, Y, and Z components:

Updating the View

The updatedLookvector is obtained using the product of local rotation, look, and

conjugate quaternions

Updated Look Vector = qRotation * qLook * qRotation'

With the result from this product, theViewcan be updated:

Updated View = Updated Look Vector + Position

Now you will apply this logic to the graphics engine to update your view

Updating the View in the Camera Class

RotationQuaternion()can be added to the camera class to generate the local

rotation quaternion based on the direction vector The first parameter of this method

represents the shift of the mouse or thumbstick from the resting position The second

parameter is a direction vector that can be either theLookorRightvector:

private Vector4 RotationQuaternion(float degrees, Vector3 direction){

Vector4 unitAxis = Vector4.Zero;

Vector4 axis = new Vector4(direction, 0.0f);

// only normalize if necessary

if ((axis.X != 0 && axis.X != 1) || (axis.Y != 0 && axis.Y != 1) ||

(axis.Z != 0 && axis.Z != 1)){

Trang 3

unitAxis = Vector4.Normalize(axis);

}

float angle = degrees * MathHelper.Pi/180.0f;

float sin = (float)Math.Sin(angle/2.0f);

// create the quaternion.

Vector4 quaternion = new Vector4(0.0f, 0.0f, 0.0f, 0.0f);

quaternion.X = axis.X * sin;

quaternion.Y = axis.Y * sin;

quaternion.Z = axis.Z * sin;

private void UpdateView(float rotationAmount, Vector3 direction)

{ // local rotation quaternion

Vector4 Q = RotationQuaternion(rotationAmount, direction);

Vector4 look = Vector4.Zero;

look.X = view.X - position.X;

look.Y = view.Y - position.Y;

look.Z = view.Z - position.Z;

// rotation quaternion * look

Vector4 Qp;

Qp.X = Q.W*look.X + Q.X*look.W + Q.Y*look.Z - Q.Z*look.Y;

Qp.Y = Q.W*look.Y - Q.X*look.Z + Q.Y*look.W + Q.Z*look.X;

Qp.Z = Q.W*look.Z + Q.X*look.Y - Q.Y*look.X + Q.Z*look.W;

Qp.W = Q.W*look.W - Q.X*look.X - Q.Y*look.Y - Q.Z*look.Z;

// conjugate is made by negating quaternion x, y, and z

Vector4 conj = new Vector4(-Q.X, -Q.Y, -Q.Z, Q.W);

// updated look vector

Vector4 Qlook;

Trang 4

Qlook.X = Qp.W*conj.X + Qp.X*conj.W + Qp.Y*conj.Z - Qp.Z*conj.Y;

Qlook.Y = Qp.W*conj.Y - Qp.X*conj.Z + Qp.Y*conj.W + Qp.Z*conj.X;

Qlook.Z = Qp.W*conj.Z + Qp.X*conj.Y - Qp.Y*conj.X + Qp.Z*conj.W;

Qlook.W = Qp.W*conj.W - Qp.X*conj.X - Qp.Y*conj.Y - Qp.Z*conj.Z;

// cap view at ground and sky

if (Qlook.Y > -0.49f && Qlook.Y < 0.49f){

// updated view equals position plus the quaternion

view.X = position.X + Qlook.X;

view.Y = position.Y + Qlook.Y;

view.Z = position.Z + Qlook.Z;

}

}

The camera class uses theChangeView()method to receive changes inView

di-rection from the game class and apply them to the camera orientation

ChangeView() checks whether the mouse or right stick has been shifted If no

movement is detected, the method exits and no changes to the view are performed

Otherwise, a relative measure for the X and Y rotations is generated based on the

de-viation of the mouse from the center of the window Rotations about the X axis are

applied using theRightvector Rotations about the Y axis are applied using theUp

vector:

public void ChangeView(float X, float Y)

{ // exit if no change to view

if (X == 0 && Y == 0)

return;

float rotationX, rotationY;

const float SCALEX = 50.0f; const float SCALEY = 2000.0f;

Vector3 look = view - position;

// tilt camera up and down

Vector3 right = Vector3.Cross(look, up);

rotationX = Y / SCALEX;

UpdateView(rotationX, Vector3.Normalize(right));

// swivel camera left and right

rotationY = X * timeLapse / SCALEY;

Trang 5

WithChangeView()in the game class, it will adjust the camera view according

to shifts of the mouse or left thumbstick A revisedSetView()method in the era class replaces the existing one to process changes to the camera’sLookdirectionfor each frame:

cam-public void SetView(Vector2 viewChange){

ChangeView(viewChange.X, viewChange.Y);

viewMatrix = Matrix.CreateLookAt(position, view, up);

}

Triggering Changes to the View from the Game Class

Back inside the game class, the camera needs to be enabled for manipulation by thegame controller, keyboard, and mouse The camera will function on the PC like afirst-person shooter, where a typical configuration uses the mouse to change the view.XNA provides theMouseandMouseStateclasses to handle the mouse on a PC.When run on the PC, the mouse has to be enabled in the game class The mousewill adjust the view by checking the distance from the center of the window to themouse At the top of the game class, aMouseStateobject is declared:

be calculated in the next frame Otherwise, the camera will use the right stick’s tion from the center to calculate the change in view:

devia-Vector2 ChangeView(GameTime gameTime){

const float SENSITIVITY = 250.0f;

const float VERTICAL_INVERSION =-1.0f; // vertical view control

// negate to reverse

// handle change in view using right and left keys

KeyboardState kbState = Keyboard.GetState();

int widthMiddle = Window.ClientBounds.Width/2;

int heightMiddle = Window.ClientBounds.Height/2;

Vector2 change = Vector2.Zero;

Trang 6

change.Y = scaleY * gp.ThumbSticks.Right.Y * SENSITIVITY;

change.X = gp.ThumbSticks.Right.X * SENSITIVITY;

To update your camera’s view from the game class (for each frame), replace the

existing call to SetView() from the Update() method with this revision that

changes the view based on how the mouse or right thumbstick is shifted:

cam.SetView(ChangeView(gameTime));

If you run your code now, your project will have a fully functional camera

en-abled To actually see it moving, you need to draw some kind of reference, such as

Trang 7

ground, a triangle, or a 3D model The camera moves and strafes with the leftthumbstick orARROWkeys It changes view with the right thumbstick or the mouse.With this camera, your game players now have full access to journey into theworld hosted by your graphics engine.

B UILDING THE BASE CODE FROM SCRATCH EXAMPLE

Not only is the camera viewer the heart of the base code, but this camera viewer cussion completes our explanation of how the base code works You can actuallybuild the base code starting with the solution from this last example When you addthe code from the “Texture Example, Part A: Adding the Grass Texture” demonstra-tion in Chapter 9, you will see the grassy ground when you run the project Then,you can follow the steps listed in Chapter 6 in “Position Color Shader Example: Ref-erencing the Shader” to add the simple shader for drawing surfaces with colored ver-tices Finally, inside InitializeBaseCode(), add the following instruction towrite the title of this book on the status bar and complete the base code:

dis-Window.Title = "Microsoft® XNA Game Studio Creator's Guide 2nd Edition";

You have just created the base code for this book If you have followed the sions behind this code, you should now be able to say you understand how the basecode works and, using this book as your reference, you can create it from scratch

discus-C HAPTER 17 REVIEW EXERCISES

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

Follow the step-by-step examples presented in this chapter, but make the ing changes

follow-1. Add an option to “invert” the camera This is a common first-personshooter game feature that allows players to reverse the direction of the Upand Down view control

2. Add an option to move the camera forward on the PC when the left mousebutton is pressed

284

Trang 8

CHAPTER 18

Collision Detection

Trang 9

COLLISION detection determines whether two objectsoverlap and therefore have collided inyour virtual world Accurate collision detection is fundamental to a solid game en-gine Without collision detection, your cars would drive off the road, your peoplewould walk through buildings, and your camera would travel through cement walls.Collision detection is also fundamental when dealing with any sort of missiles Forexample, if you had faulty detection applied to a rocket, you might successfully hityour target and not receive credit—or possibly even worse, your enemies might miss

a shot at you and be credited with a hit These sorts of problems are occasionally dent in commercial games, but to avoid player frustration, you should strive to haveexcellent collision detection This chapter shows you how to use collision detection

evi-to add boundaries around your game objects

XNA has two main types for implementing collision detection They are:

1. BoundingBox

2. BoundingSphereImplementing collision detection with these types involves encasing your physi-cal game objects either with invisible boxes or spheres Obviously, a box will bettersuit a rectangular high-rise building, while a bounding sphere offers a better fit forrounded objects such as a domed arena Together, these two collision types deliver

a powerful range of options that allow you to implement efficient collision ing in any situation

check-F INE-TUNING YOUR COLLISION DETECTION SYSTEMS

For irregular shapes—such as an alien ship—you can use a group of smaller boxes orspheres for each section Compared to boxes, spheres are easier to transform andthey use less storage space, so you’ll want to use spheres when you can

Also, XNA’s model loader exposes mesh objects in the X models and FBX els Each mesh within a model is assigned a bounding sphere with a properly sized ra-dius With this system already in place, you can load your model in a modeling toolsuch as Blender or MilkShape, and add spheres using the designer to cover the surface

mod-of your model You then need to delete your original model group(s) from this modelproject After exporting your cluster of spheres as a separate model, you can loadthem in your XNA project and extract bounding-sphere information at run time.This means you can rapidly and accurately build your collision detection systems us-ing a model design tool and the XNA Framework Figure 18-1 shows models withspheres added before the original meshes were deleted

Trang 10

E ARLY WARNING SYSTEMS

As you continue to add bounding spheres or bounding boxes to improve the accuracy

of your collision detection, you may encounter a performance decrease if too much

collision checking is required each frame For this reason, you need broad

colli-sion-checking routines to first detect if two objects are within close proximity of each

other before doing anything else These early warning systems only need to compare

a few large blunt bounding spheres or boxes to check for collisions Whenever a close

proximity between large bounding objects is established, more intensive and

accu-rate collision-checking routines can be used A decent early warning system avoids

the need to run exhaustive sets of routines every frame

C ONTAINMENTTYPE

BothBoundingSphereandBoundingBoxtypes use aContainmentTypeto

de-scribe the extent of surface overlap These containment types include Contains,

Disjoint, andIntersect This allows you to determine if your spheres or boxes

contain or intersect each other ADisjointcondition occurs when the collision

ob-jects are completely separate

Trang 11

B OUNDINGSPHERE

The use of bounding spheres is popular because spheres can easily be transformedand compared and they do not require much processing power The bound-ing-sphere method involves creating an invisible sphere around each object thatneeds collision detection If the distance between the centers of the two spheres is lessthan the sum of their radii, a collision is detected You don’t have to actually performthese calculations, though, because XNA’s accompanying methods for theBoundingSpheretype already do it for you

Initializing the Bounding Sphere

When you initialize the bounding sphere, you will specify the location of the center ofthe sphere using a three-dimensional vector and the radius of the sphere

public BoundingSphere(Vector3 center, float radius);

Intersects()

TheBoundingSphere Intersects()method has several overloads Two mon overloads allow comparisons between the current bounding sphere and either asphere or bounding box that can be passed in as parameters

com-public bool Intersects(BoundingBox box);

public bool Intersects(BoundingSphere sphere);

Contains

The bounding-sphere object offers theContains()method to compare the ing sphere with another bounding sphere, a bounding box, or a three-dimensionalposition

bound-public void Contains(ref BoundingSphere sphere,

out ContainmentType result);

public void Contains(ref BoundingBox box, out ContainmentType result); public void Contains(ref Vector3 point, out ContainmentType result);

B OUNDINGBOX

TheBoundingBoxtype offers collision checking for objects contained within angular 3D space When you initialize this type, you pass in the minimum and maxi-mum positions for the corners of your bounding box:

rect-288

Trang 12

BoundingBox boundingBox = new BoundingBox(Vector3 min, Vector3 max);

TheBoundingBoxtype in XNA is not axis aligned, so if you rotate or animate

your bounding box you will have to reinitialize it each frame to reset the new

mini-mum and maximini-mum corners This is not a practical solution because the bounding

box shape will change significantly at different angles of a rotation

In spite of limitations you might face with the bounding box, it really is a valuable

structure—especially for rectangular objects that stay in one place In the code

dem-onstration later, you will see how over one hundred spheres that line the walls of the

world are replaced with one large box for a giant leap in providing efficient collision

detection

Intersects()

Similar to the BoundingSphere Intersects() method, the BoundingBox

Intersects()method has several overloads Two common overloads allow

com-parisons between the current bounding sphere and either a sphere or bounding box

that can be passed in as parameters

public bool Intersects(BoundingBox box);

public bool Intersects(BoundingSphere sphere);

Contains()

The BoundingBox Contains() method has several variations Here are three

common ways to use theContains()method:

1. Comparing one bounding box with another:

public void Contains(ref BoundingBox box, out ContainmentType result);

2. Comparing a bounding box with a bounding sphere:

public void Contains(ref BoundingSphere sphere,

out ContainmentType result);

3. Comparing a bounding box with a single three-dimensional position:

public void Contains(ref Vector3 point, out ContainmentType result);

The secondContains()overload mentioned is very exciting because it allows

you to compare your boxes with spheres, giving you many possibilities to generate

the best fit for your objects We will show an example of this overload later in this

chapter to generate a very efficient and well-fitted collision-detection routine

be-tween the car and the box that surrounds the world

C H A P T E R 1 8

Trang 13

C OLLISION DETECTION EXAMPLE:

INITIALIZING AND DRAWING BOUNDING

This example begins with the solution from the “Adding a Car as a Third-PersonObject” example from Chapter 14 You will first modify the code by manually add-ing bounding spheres around the edge of the world Then, in a modeling tool, youwill add a group of spheres for the car and wheel Once you add your cluster ofspheres, you will delete the original model and export it to fbx format Once youhave exported your sphere group, you will load them in your project to obtain thebounding-sphere center and radius information

When you are finished working with theBoundingSphereportion of this ple, you will have a world that is divided into four quarters Four large spheres eachcircle one quarter of the smaller spheres that line the wall of the world A large spherealso surrounds the entire car, which moves with the camera If a collision is detectedbetween the large sphere around the car and one of the small spheres on the wall inthe current quarter of the world, a more exhaustive routine checks for collisions be-tween all car spheres and wall spheres within that world quadrant See Figure 18-2

exam-At the end of this demonstration—since our world is a rectangle—you will replacethe spheres that surround our world with just one bounding box for even larger per-

290

F I G U R E 1 8 - 2

Different sphere groups for varying levels of efficiency and accuracy

Trang 14

formance gains The final solution provides fast and accurate collision detection

be-tween the car and the world walls

Once you have the solution from Chapter 14 open, add a code file named Vertices.cs

to create a series ofPositionColorvertices for drawing a sphere using line strips

The vertices are arranged in a grid of slices or columns and stacks, which are rows You

need to add this code to the Vertices.cs file to generate your sphere vertices:

using System;

using Microsoft.Xna.Framework;

using Microsoft.Xna.Framework.Graphics;

namespace MGHGame{

public class SphereVertices{

private Color color;

private int numPrimitives;

private Vector3 offset = Vector3.Zero;

public SphereVertices(Color vertexColor, int totalPrimitives,

public VertexPositionColor[] InitializeSphere(int numSlices,

int numStacks, float radius){

Vector3[] position = new Vector3[(numSlices + 1)

* (numStacks + 1)];

float angleX, angleY;

float rowHeight = MathHelper.Pi / numStacks;

float colWidth = MathHelper.TwoPi / numSlices;

Trang 15

VertexPositionColor[] vertices

= new VertexPositionColor[2 * numSlices * numStacks]; // index vertices to draw sphere

for (int stacks = 0; stacks < numStacks; stacks++){

for (int slices = 0; slices < numSlices; slices++){

vertices[++i] = new VertexPositionColor(

position[stacks * numSlices + slices], color); vertices[++i] = new VertexPositionColor(

position[(stacks + 1) * numSlices + slices],

color);

} } return vertices;

} }

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

TỪ KHÓA LIÊN QUAN