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

Building XNA 2.0 Games- P11 doc

30 262 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 đề Building XNA 2.0 Games
Trường học Standard University
Chuyên ngành Game Development
Thể loại Thesis
Năm xuất bản 2023
Thành phố New York
Định dạng
Số trang 30
Dung lượng 896,13 KB

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

Nội dung

The initial design was to produce all of the interface-related items we would need: a health bar, score, map transitions, and a main menu.. We’ll need to implement scoring and map transi

Trang 1

flags = new String[size];

for (int i = 0; i < flags.Length; i++)

Trang 2

With our map in place using its brand-new script, run ZombieSmashers You’ll see

some-thing like Figure 9-7

Figure 9-7 Final product of this chapter

Conclusion

We’ve covered some fairly varied ground in this chapter The main goal was to introduce map

scripting, but we ended up adding quite a bit of functionality to our characters: blood sprays,

initialization and death, and rudimentary AI We know that we say this every chapter, but we’re

a lot closer to having a fleshed-out game

To recap, we accomplished the following:

• Added all sorts of blood sprays and spurts to the character editor

• Created zombie attack, decap, and bloodsplode animations

• Added initialization scripts

• Implemented the new blood effects in our game

• Implemented character initialization and death

• Added AI

• Defined a map scripting language

• Added script-editing functionality to the map editor

• Introduced map level and global level flags

• Added fog

Trang 3

In the next chapter, we’ll introduce player death, map transitions, a HUD, and game menus

As we near the completion of our game, it is important to keep our head in the game and not get distracted by the want or need to change things that are done One of the biggest prob-lems that plagues independent developers is their constant desire to fix old code, no matter how well it works

The best thing to do at this point is finish the game first, and then go back

Trang 4

■ ■ ■

Menus, a HUD, and Deployment

At Last, the Coveted Xbox 360

Deployment

We’ll warn you right off the bat: this is going to be another odds-and-ends chapter The

initial design was to produce all of the interface-related items we would need: a health bar,

score, map transitions, and a main menu However, since these tie in with the constraints we’ll

be dealing with on the Xbox 360, and because thus far we haven’t touched the thing, it seemed

like a perfect time to introduce the concept of deployment

If you don’t have an Xbox 360 and/or an XNA Creators Club membership, you can

bliss-fully skip the deployment section of this chapter But, honestly, if you’ve gotten this far in the

book and still don’t have any intention of playing around with an Xbox 360, you’ve got some

issues Granted, they might be good issues (thriftiness?), but they are issues nonetheless

Here’s the rundown of what we’ll be doing in this chapter:

• Add a player HUD to display the health and score We’ll need to implement scoring and

map transitions, and add scripting functionality to support map transitions

• Add a menu system

• Implement player death We’ll need to have a menu system in place to deal with this

• Dive into Xbox 360 deployment

There will be a bit of “we need to do A, but to get there we need to have B and C in place,”

so bear with us

Adding a HUD

Our HUD will consist of a row of five hearts for our health and a score, as shown in Figure 10-1

The hearts will just be a visual representation of our integer health value, not some sort of atomic

unit of health For instance, if you have 82/100 HP, you’ll have 4.1 hearts We just thought

hearts would look cute

Trang 5

Figure 10-1. Health and score display

Creating the HUD Class

The HUD class will deal with all things related to the interface: updating the health display and fading transitions, and drawing the health, score, and transitions Just like everything else so far, we’ll be calling the Update() and Draw() functions from Game1

We’ll be using a new object, scoredraw, to draw numbers “But wait,” you may be saying,

“why not just use a text class and ToString() to draw text?” The long and the short of it is that ToString() generates a ton of garbage when used every frame; this kills performance on the Xbox 360 We’ll use a more efficient algorithm that you may have seen in a Computer Science

101 class:

ScoreDraw scoreDraw;

We will talk more about ScoreDraw in the next section

We’ll use the field heartFrame to let our hearts sort of waver in a classic comic, cutesy fashion We’re using the fHP field (think floating health points) for a sort of catch-up health bar When

we take damage or get health, we want our health bar to smoothly transition from the previous value to the current value When we call HUD.Update(), we’ll have the floating bar try to get to

Trang 6

where the real bar is Then when we Draw(), we’ll draw more prominently at the floating

posi-tion than the real posiposi-tion This technique is infinitely more professional-looking than just

drawing the current health value

float heartFrame;

float fHP;

For the constructor, we’ll just send it all of the objects it will need: the ever-present

SpriteBatch, some textures, and the Character array and Map

public HUD(SpriteBatch _sprite, Texture2D _spritesTex,

As promised, the Update() function increments our heartFrame and tries to get fHP to

match with our goal HP

public void Update()

Our Draw() method will first draw the score, then some black background hearts (our

floating health hearts), and finally our real health hearts

We’re using the same sprites texture we previously used it for smoke, flame, and muzzle

flashes, but we’ll add some hearts and numbers to it The new image is shown in Figure 10-2

Trang 7

Figure 10-2. Updated sprites texture

The hearts all start at 0, 192 and are 32 ✕ 32

public void Draw()

float prog = character[0].HP / character[0].MHP;

Trang 8

float r = (float)Math.Cos((double)heartFrame * 2.0 +

(double)i) * 0.1f;

First, we draw the dark background hearts:

sprite.Draw(spritesTex, new Vector2(

Next, we compute how much of a heart is shown, by getting the difference between the

progress value and the current heart index, and draw the floating health heart:

float ta = fProg - (float)i;

new Rectangle(i * 32, 192, (int)(32f * ta), 32),

new Color(new Vector4(1f, 0f, 0f, 75f)),

new Rectangle(i * 32, 192, (int)(32f * ta), 32),

new Color(new Vector4(.9f, 0f, 0f, 1f)),

r, new Vector2(16f, 16f), 1.25f,

SpriteEffects.None, 1f);

}

}

Lastly, we’re implementing some fade-to-black functionality We’ll have transition values

in the map soon, for entering and exiting segments, as well as for when we first start a game

Based on where the map is transition-wise, we’ll draw our nullTex over the entire screen with

an appropriate alpha value

Trang 9

(int)Game1.ScreenSize.Y), new Color(

new Vector4(0f, 0f, 0f, a)));

}

sprite.End();

}

}

Drawing the Score

We referred to a ScoreDraw class earlier Let’s define it here:

public enum Justification

Trang 10

• Draw 1, shift left a bit

• Divide 1 by 10 = 0

• Fini !

Computer science professors love to use this problem as an introduction to modulus

arithmetic

public void Draw(long score, Vector2 loc,

Color color, Justification justify)

{

int place = 0;

The obnoxiously ugly part is in left-justified text Drawing and shifting left as necessary is

fine, but if we can’t draw and shift right, we would get a reverse score Instead, we apply our

divide-by-10 loop to the score to determine the entire string width, shift our draw position

right by that much, and proceed as normal.

Trang 11

And that does it for our HUD We have updating and drawing functionality for health, score, and map transitions That leaves quite a bit of implementation to do Let’s start with map transitions!

Creating Map Transitions

As we described in Chapter 4, our game world will be made up of map segments When the

player walks all the way to the left or right on a map, the previous or subsequent segment will load An example of a segmented map is shown in Figure 10-3 For the hero in segment 1 to get

to the house in segment 4, three map transitions are necessary

Figure 10-3. Four map segments

Designating Segment Transitions

To designate segment transitions, we’ll add some scripting to our functionality to define exits and entrances We’ll use the terminology as follows:

Exit: This is the destination map we’ll transition to upon hitting a boundary For instance,

if leftexit is map1, we’ll transition to map map1 if our player hits the map segment’s left boundary If rightexit is "", there is no right exit

Entrance: This is the vector for our player when we transition to a new map For example,

if we’ve just transitioned to map1 by exiting map2 to the left, we’ll place our player at the vector defined as rightentrance

At this point, we’ll be using only leftexit, rightexit, leftentrance, rightentrance, and initentrance We’ll use initentrance to define an entrance vector for starting a new game

New Script Commands

We need to add the new script commands to our MapScript and MapScriptLine classes First, let’s define them in our MapCommands enumeration:

Trang 13

In our Map class, we’ll use an array of enumeration TransitionDirection to hold transition destinations We’re also referring to fields that we’ll add to Map We’ll get to the Map updates in the next section.

Let’s move on to our entrances:

When we set the entrances, we’re not actually setting anything We’re checking to see what

type of transition has just occurred leading up to this latest map initialization If the transition matches whichever one we’re checking for, we’ll set the player to the appropriate location, complete with the proper animation, airborne state, and so on

Trang 14

Map Transition Enum and Fields

Now, a bit out of order, we’ll define some of the fields we just talked about at the class level of

Map But first, let’s define our enumeration:

public enum TransitionDirection : int

The fields transInFrame and transOutFrame will be used to operate the map transitioning:

public float transInFrame = 0f;

public float transOutFrame = 0f;

public string[] transitionDestination = { "", "", "" };

public TransitionDirection TransDir;

When we first trigger a transition, transOutFrame will be set to 1, and as transOutFrame

decreases to 0, the screen will fade to black When transOutFrame hits 0, we’ll load the new map

(which will in turn set the player to the right entrance location), and set transInFrame to 1 As

transInFrame decreases to 0, the screen will fade in from black

Remember the GetTransVal() function we use in HUD to black out the screen? Here it is:

public float GetTransVal()

We’re just returning a value between 0f and 1f, based on transInFrame and transOutFrame

Checking for Transitions

Now we’ll define a function to check if a transition should be triggered We’ll check for

transi-tions based on player index 0’s location If it’s at the left boundary, we’ll transition left; if it’s at

the right boundary, we’ll transition right We have also started to correct a mistake that was

made in a previous chapter As we add more and more code that is dependent on the size of the

map, we want to move that value into a private variable or two Here, we define two variables:

xSize and ySize, both with a value of 20

Trang 15

public void CheckTransitions(Character[] c)

Trang 16

Uh-oh, looks like we snuck another new method in there We added Reset() to our

ParticleManager class It just iterates through all particles, setting each to null

Now we have the map transition functionality in place However, at this point in

develop-ment, there’s only one map!

Trang 17

The initialization script for our start map is as follows:

Now we need to add some transition scripting to map, as shown in Figure 10-5

Figure 10-5. Our original map with transitions

We’ll add a bit to the initialization script for this one:

Trang 18

So, start has map defined as the right exit, and map has start defined as the left exit Tedious?

We got used to it There are most likely better ways to do it, such as by incorporating adjoining

map data into the map definition, rather than the script However, for a quick solution, this

works fairly well It handled the more than 100 map segments in The Dishwasher: Dead

Samurai game easily enough

Remember that setintroentrance command? We’re getting to that main menu!

Adding Menus

We’ll create a big fat Menu class to deal with all things menu-related Our class will have menu

functionality in levels—a main level, options level, quit-are-you-sure? level, and so on—where

we can be on one level or transitioning from one level to another

We also want to be able to use our Menu class as a pause menu and a you-are-dead menu

Hitting start while in a game will bring up the menu in pause mode; dying will bring up the

menu in dead mode Each mode will carry certain restrictions For instance, hitting Start in the

main menu is functionally the same as pressing A, but hitting Start in the pause menu will

return the player to the game, because Start is meant to work as a pause toggle

Designing the Menu

We want our menu to look excellent Figure 10-6 shows a rough sketch of the look we have

in mind

Figure 10-6. Main renu, rough draft

Trang 19

Our menu options are at left, slightly staggered Our hero is at right in a prominent, wielding pose In the foreground, we have a zombie hand underfoot

wrench-We’ll use a series of layers to do this Our hero will be one image, as shown in Figure 10-7

Figure 10-7. Our hero poses in pose.png

The black foreground will pan in a slightly more exaggerated way than the hero pose, giving an illusion of depth (it’s that crazy parallax again!) Also, we can draw some fog between our hero and the foreground Figure 10-8 shows the foreground image

Figure 10-8. Pose foreground in posefore.png

On the left side of the menu will be some buttons While it would be more robust to use a text-drawing class for these buttons, it’s a lot easier (and perfectly acceptable) to use images

We put together a sprite sheet, shown in Figure 10-9

Trang 20

Figure 10-9. Game options (more to come) in options.png

We’ll set it up to have a layer of smoothly animated fog, a hero, the buttons, another layer

of fog, and the foreground, with everything slowly panning left and right in parallax Figure 10-10

shows what we’re going for

Figure 10-10. The main menu final product

Let’s get to creating the class

Trang 21

Creating the Menu Class

We’ll start with a rather lengthy list of class-level declarations, dealing with both game logic and render logic

public class Menu

{

When transitioning from one level to another, sometimes we want just the buttons to fade out, and sometimes we want everything to fade out The Trans enumeration takes care of that: public enum Trans : int

public enum Level : int

Trang 22

public enum MenuMode : int

With our enumerations out of the way, let’s use them for something!

We’ll use transFrame for level-to-level transitions, transType to define the type of transition

going on, and transGoal to specify the destination menu level Obviously, level is our current

menu level Finally, selItem is the currently selected menu item

public float transFrame = 1f;

public Trans transType = Trans.All;

public Level transGoal;

public Level level = Level.Main;

public int selItem;

While we’re using selItem to indicate which item is currently selected, we can keep track

of which item had been currently selected on all levels with levelSel[]

int[] levelSel = new int[32];

We’ll use a method called PopulateOptions(), which we’ll define later (in the “Option

Popu-lation” section), to figure out the available options for the particular menu level For instance, the

Main level could have the options New Game, Continue, Options, and Quit; the Dead level will

have End Game and Quit PopulateOptions() will populate option[] and totalOptions We’ll use

optionFrame[] to smoothly transition to the selected option

Option[] option = new Option[10];

float[] optionFrame = new float[10];

int totalOptions = 0;

For our fog particles, we’ll use fog[] We can calculate each fog particle’s location, size,

and speed by its index and some snazzy modulus arithmetic

Vector2[] fog = new Vector2[128];

We’ll use frame for our slow parallax panning

float frame;

Ngày đăng: 01/07/2014, 22:20