You are on page 1of 388

Foreword

Back in 2006, the XNA team started working on a technology that would
evolve into the product youll soon be reading about XNA Game
Studio 3.0. At the heart of all the technical efforts we had going on, such
as prototyping, designing, and testing, we had a vision that we were
trying to achieve. That vision was to enableanyone to create games for
the Xbox 360 console, even if it was only one person and he or she
didnt have much programming experience. In essence, we wanted to
lower the barrier to entry for game development and, to put it simply,
bring back some of the fun of playing the roles of designer, artist, and
programmer on your own game.
For me, this vision brings back many fond memories of game
development and some of the reasons I wanted to become a game
developer in the first place. Like so many others, though, it was all
sparked by playing some great games. Role-playing games (RPGs) are
one of my favorite video game genres (no offense intended to my other
favorites the platformers and adventure games). I spent countless
nights with my Game Boy playing SquaresFinal Fantasy Legend II,
which is one of my favorites. To me there is something really incredible
about RPGs in that they pull together music, story, and gameplay in a
way that brings you fully into the games world.
As I continued to play more RPGs like Shadowrun and Final Fantasy
Mystic Quest on the Super Nintendo, andUltima on the PC, I found
myself wanting to tell my own stories. This was around the time I began
to learn programming in school, and my best friend and I worked on
stories for games that would make good RPGs. I loved being able to
incorporate aspects of my own life or experiences into a game that was
humorous and fun to play, such as an RPG I wrote that took place in our
middle school. All of my favorite teachers were hero characters, and

well, you probably know the other side. (Note that I am now mature
enough to say that all teachers are heroes!) These games were
entertaining to playeven if only for myself and my close friends.
While playing RPGs had the ability to capture my imagination and
attention, developing RPGs brought things to another level, and I was
completely captivated by the process. When I wasnt in class, I was
programming or creating content for my games. And when I was in
class, or otherwise not in front of my computer, I was writing down story
ideas or code that would allow me to have work queued up for when I
was back at my computer. For me, this created a perfect storm where I
was learning skills, creating something amazing, and having a lot of fun
every time I made something cool happen. This eventually led to my
career in game development, where I get to have fun as part of my job,
but has never truly allowed me to relive the same magical moments I had
while watching my own game come together.
As we continue to develop XNA Game Studio and the XNA Framework,
these kinds of memories are what inspire me and the rest of the team to
make XNA Game Studio better and easier to use for both professional
and hobbyist game developers. Were always working towards making
the process of getting your ideas into playable form as engaging and
easy as possible.
As you begin your journey into game development, using this book and
the RPG genre as a jumping-off point, I hope that you tap the creativity
and passion that is crucial to creating a successful game. More important
than commercial success, however, I hope you have fun and enjoy the
process of learning a new development technology and creating your
own games.
It is truly a great time (again) to be a game developer!
Michael Klucher, Program Manager

XNA Platform and Tools


Microsoft Corporation

Acknowledgments
A lot of people had direct or indirect influence on this book. First, much
thanks has to go to the XNA Team for making such a fantastic product
and service available to game developers small and not-so-small. The
possibility of getting a game on a major console that anyone in the world
can buy is a huge step for the game development industry. As XNA
Game Studio matures, I can see it and Xbox LIVE Community Games
working together to become the YouTube of games thats been quoted
many times.
A huge thanks to my wife, Nancy, and son, Stephen, for their patience,
understanding, and support during the development of this book, without
which it would most likely never have seen the light of day.
Thanks also to Wordware for giving me the opportunity to take this
concept thats been brewing for years and get it into a form where it can
hopefully help other developers. Its been a pleasure working with
everyone.
To the XNA community thanks for giving us some great games as
well as supporting those who are getting their feet wet in the game
development waters. Its been an exciting and interesting journey so far
and Im sure the time ahead will be even more so.

Introduction
It seems almost everyone who wants to try their hand at game
development wants to create either a regular RPG (role-playing game) or
an MMORPG (massively multiplayer online role-playing game).

However, many do so without fully understanding what it takes to make


even the smallest game of any type, let alone an RPG, which usually has
tons of content. All this content takes considerable time and effort by
many different people artists, level designers, audio engineers, voice
actors, writers, producers, and programmers to tie all the content
together. With XNA Game Studio making game development easier
than ever, its almost inevitable that many will try to develop an RPG
using their knowledge of playing RPGs. Unfortunately, playing an RPG
doesnt mean you have a full understanding of what it takes to create
one. Those new to game development are usually frustrated once they
realize that theyve gotten in over their head.
As an avid RPG player myself, I love seeing interesting and fun RPGs
released. Other players have an idea of what makes them fun and
interesting, but not enough knowledge to create them from the ground
up. My desire to write this book is therefore somewhat selfish in that I
want to see more games that I can play. Hopefully this book will give
those who want to try RPG game development enough knowledge to
make the games they see in their minds.

Who Should Read This Book?


Although this book is geared specifically toward developing RPGs,
anyone who is interested in game programming for the PC and/or the
Xbox 360 will benefit from it because the skeleton of almost every type
of game is the same. You should have a good understanding of the C#
language in order to take full advantage of the material in this book. If
youre comfortable with VB.NET, C++, or Java, you should be able to
quickly pick up the nuances of C#. If you have no experience with any
of the languages mentioned, you might want to pick up a good book on
C# programming before diving into this book. Even if youre not an

experienced programmer, well discuss plenty of game development


techniques that will help increase your knowledge of the field.
Experienced game developers who havent looked at XNA Game Studio
will gain from this book since it shows how XNA Game Studio can be
used to quickly and more easily get the basics of a game up and running,
allowing the developer to concentrate more on specific gameplay code
than the code needed to create the skeleton onto which the gameplay
code is built.

Conventions
The C# language will be used exclusively throughout this book. The
coding conventions for the .NET Framework will be followed with only
minor changes due to the style preferences of the author. These
conventions can currently be found at the following location
http://msdn2.microsoft.com/en-us/library/ms229042(VS.80).aspx.
Its recommended that, if you havent already done so, you adopt a set of
coding conventions and stick to them. It makes your code easier to read
and follow, especially if youre looking at code that youve put aside for
a while and gone back to. It will also make it easier for the people you
work with to follow your code.

System Requirements
The following is required to run XNA Game Studio:
Microsoft Windows XP SP2 or Windows Vista (Windows Server
2003 and older operating systems are not currently supported)
At least the DirectX 9.0c runtime (the SDK is not needed)
A video card that supports at least Shader Model 1.1 (2.0 support is
recommended as many samples and starter kits require it)
Visual C# Express 2008 or Visual Studio 2008

Installing and Using the Code

All code for the book can be downloaded


from http://www.wordware.com/files/XNARPG. Youll find links there
for other relevant downloads and information as well. Extract the
downloaded file(s) onto your hard drive. After the code has been placed
on the hard drive of your PC, you can simply navigate to the appropriate
folder for a chapter and open the solution file in XNA Game Studio.
Steps for installing XNA Game Studio can be found on the Creators
Club site http://creators.xna.com/en-US/quickstart_main.

Support for This Book


Support for the material covered in this book, including updates and
errata, can be obtained from the publishers web site
at www.wordware.com/files/XNARPG.
Any questions or comments about the book can be emailed to the
following address xnarpg@jbpub.com. The author welcomes
feedback and will reply when possible.

Chapter 1
RPG Basics
What is an RPG? In a role-playing game, the player assumes the role of
a character, or avatar, controlling his or her every aspect. Where he goes,
what he does its all up to the player. A character could spend all his
time traveling the countryside, sitting in a bar, farming, or engaging in
any number of other activities. Normally, though, a character will be
wandering through some type of dungeon, battling all manner of
creatures. While the player is the person who decides what the character
does, the developer is the person who decides what activities the player

has to choose from. At the very least, as a developer you need to give the
player some places for the character to explore, creatures to fight, and
treasure to find. These things are usually bound together in quests or
missions. (The name may vary depending on the genre of the game
quests in fantasy-based RPGs or missions in sci-fi RPGs, for example.)
A characters abilities in a role-playing game are usually based on stats
and skills. Stats are such things as Strength, Dexterity, and Intelligence.
These stats are represented by a number, which indicates how developed
that stat is. The higher a characters Strength stat, for example, the more
he can lift and the more damage he can cause with melee weapons. The
higher his Intelligence stat, the easier he can learn things such as spells
or languages. Most RPGs have these stats in one form or another, and
almost all have additional stats, such as Constitution, Agility, Wisdom,
and Charisma. You could also consider things like Health and Mana.
Mana is the source of supernatural power or the characters ability to use
this power. The definition can be whatever you make it inner power,
a magical aura in the world that the character taps into, psionic or mental
power in a sci-fi based RPG, etc. Its a fairly standard term in RPGs.
Skills are such things as using a sword, firing a gun, and walking a
tightrope. Almost every action the character performs, except normal
activities like walking and talking, will usually involve using a skill.
There are different ways these skills are represented in an RPG, but like
stats, skills are usually represented by some numeric value that indicates
how well the character can perform that skill. When performing a skill, a
value is also usually assigned to the difficulty of the effort. For example,
walking a tightrope is difficult. Doing so in a windstorm is much more
difficult. Doing so in a windstorm while being shot at by several enemies
is insanely difficult. Some activities will be so simple that they
automatically succeed. The sum of the characters skill score and the

value of the difficulty factor are used to determine if the effort succeeds.
Computer role-playing games (CRPGs, but called RPGs from this point
on) sometimes hide both stat and skill values, but most allow you to at
least see the stats and skills and determine how the character develops by
improving them.

A (Relatively) Brief History of Computer RPGs


When gamers talk about the beginnings of RPGs, whether computer or
pencil and paper, theyll usually point atDungeons and Dragons (D&D)
as the ultimate sire of the genre. While its true that the genre really
gained steam with the release of D&D in 1974, you could say that
computer RPGs also have games like Zork and Myst in their lineage.
These were games in which the actions of a person, not a creature or
object, in the game were dependent on the players decisions. One early
RPG that many people cite is Akalabeth: World of Doom, by Richard
Garriot. However, you can go back to the world of mainframes and find
examples of simple (and not so simple) RPGs.
The same year that Gary Gygax released Dungeons and Dragons, games
started appearing on some mainframe systems. Probably the first of these
was a game called pedit5. It featured such RPG staples as dungeons,
monsters, treasure, and a magic system. Because many administrators
deleted games whenever they could, its not totally clear if this was the
first mainframe game, but its the first for which we have some clear
record.
Other notable games during this period were dnd, Dungeon,
and Rogue. dnd featured a level-up system based on experience points,
a store where players could buy equipment, and an actual story and quest
killing a dragon to get an orb. Dungeon allowed the player to control
an entire party of characters instead of the single adventurer in previous
games. Rogue included randomly generated dungeons and ASCII-based

graphics and also featured complicated gameplay. Games that are termed
Roguelike can still be found today.
Around 1979 the next era of RPGs began with the release of at least two
commercially published games. One is the aforementioned Akalabeth:
World of Doom, which featured first-person perspective and graphics
using wireframe for objects and the dungeon itself. The other
was Dunjonquest: Temple of Apshai.
Temple of Apshai was somewhat unique in that it used an on-screen
room number that could be looked up in the games manual to provide
the player with a description of the room. This description could give the
player hints about monsters that might be in the room before the player
enters or hidden objects in the room, such as secret doors. The game
spawned two add-ons, Upper Reaches of Apshai and Curse of Ra, which
were later packaged with the original as one game, The Temple of Apshai
Trilogy, featuring improved graphics and sound.
In 1980 gamers saw the release of Ultima I: The First Age of Darkness.
It was the first in the Ultima series, which would become one of the
premier series in the genre. The Wizardry series also debuted around this
time. Other games appeared during the next couple of years, but these
are probably the two most well known.
The rest of the 80s was a great time for RPG players. The Ultima series
continued, The Bards Tale series debuted, and Strategic Solutions, Inc.
(SSI) released several good games, including its Phantasie series.
As an aside, one of my personal favorites among the earlier computer
RPGs and the earliest I remember playing was The Bards Tale for the
Commodore 64. You viewed the world in kind of a first-person 3D
perspective, although the sprites were 2D as shown in Figure 1-1.
Like most RPG players, I spent hundreds of hours playing these early
RPGs and enjoyed almost every minute of the time. Having my

characters die suddenly was a bit frustrating, but it made advancing


through the game feel like more of an accomplishment because Id
actually earned the rewards instead of just picking them up along the
way, as is the case with many RPGs these days.

Figure 1-1
In 1988 the so-called Gold Box series of games saw its first release
with Pool of Radiance. SSI had managed to snag the very coveted
AD&D (Advanced Dungeons & Dragons) license and this game was the
first that used it to officially ship.
After Pool of Radiance came three sequels Curse of the Azure
Bonds, Secret of the Silver Blades, and Pools of Darkness. The same
engine that drove these games was also used on a series of games based
on the Dragonlance novels, several games set in the Forgotten Realms
world, and a pair of games set in the universe of Buck Rogers.
1992 saw the end of the engine used to drive the Gold Box games,
although game compilations were still released. And in 1993, SSI
published a tool created by MicroMagic called Unlimited
Adventures that players could use to create their own adventures. In the
meantime, SSI went on to release a new series of games, starting
with Eye of the Beholder in 1991.
Earlier we noted that fantasy-based RPGs werent the only game in
town. Science-fiction games also appeared in many different forms. In

1985 a game called Autoduel was released. Based on a pencil and paper
game called Car Wars, published by Steve Jackson Games, it had stats
for cars and players had skills like driving, mechanics, and
marksmanship. This was basically the beginning for games like Grand
Theft Auto and was a very popular andsuccessful game. And like all
popular and successful games it spawned similar games.
Autoduels post-apocalyptic setting was used in many other games
during this time, one of which was Wasteland. The very
popular Wasteland was the progenitor of what is thought by many to be
the most famous post-apocalyptic RPG (and possibly RPG in general) of
all time, Fallout. Wasteland was set in a world devastated by World War
III. Players controlled characters that had to overcome obstacles in an
interesting game world that could be developed using a fairly intricate
system. Characters learned from a set of 27 skills such as metallurgy,
lock picking, and sleight-of-hand and could use them to accomplish the
same task in more than one way.
The late 1980s saw the increase in popularity of games that used an
interface similar to that in The Bards Tale. Games like Dungeon
Master, released in 1987, and the aforementioned Eye of the
Beholder were highly successful and spawned follow-ups. Like many
advances in computer gaming, the increase in hardware power allowed
developers to do things that werent possible previously and gamers, for
the most part, snapped up the games that were released. There were a
few less-than-terrific games, but RPG fans were in general experiencing
games with increasingly complex stories, RPG systems, and graphics.
Probably the three most successful RPG series in the history of computer
gaming were released during these years. Theres probably no RPG fan
that hasnt at least heard of Ultima, Wizardry, and Might and Magic.
Between these series, several dozen games fed gamers RPG habit. Not

all of them were great, but the name alone was usually enough to ensure
the continued development of games in the series. The games brought
new elements to RPGs, such as the morality-based Ultima games.
Players didnt develop their character by assigning numbers to stats.
Instead, the direction the character took was based on answers to
questions about moral dilemmas. Much speculation has arisen as to why
Richard Garriot, the creator of the series, took this direction. No matter
the reason, this new direction was a hit with both players and reviewers
alike.
The Wizardry series took a different, if not as unique, approach in its
fourth installment. Rather than controlling a hero, players controlled a
villain, an evil wizard named Werdna (the wizard that players set out to
defeat in the first game in the series). Arguably the most difficult RPG
ever created, Wizardry IV: The Return of Werdna wasnt really an
evolution of the series except for this difference in the character being
controlled by the player.
The Might and Magic series, on the other hand, contributed several new
features to the RPG genre. The first game featured a huge world in
which players could wander around. There were over 4,000 locations
and 55 areas in the game, and players could explore it however they
wanted. Most other RPGs of the time guided the players through the
game in a much more fixed manner.
Also unique at the time was the element of having the race and gender of
the character affect the gameplay. Certain areas would not allow a party
if the members were all male or if they were of a certain alignment (i.e.,
good, neutral, or evil). This made the game more of a challenge, but the
overall difficulty of the game was less than that of its peers so this
element appealed to many who found other games too difficult to get
through.

1992 saw the release of Ultima Underworld: The Stygian Abyss.


Developed by Blue Sky Productions, the game had an advanced 3D
engine that pushed the boundaries of hardware at that time. Although it
wasnt a huge financial success, its technological advances let gamers
immerse themselves more fully into the world of Britannia, the setting
for the Ultima games. It was successful enough, however, to have a
sequel released in 1993, Labyrinth of Worlds. This sequel added digital
sound effects and a larger viewing area but wasnt really innovative
technologically. It did, however, have a more complex storyline and was
closer to the main Ultima series. It was also a huge game as the main
character traveled through eight dimensions during the course of the
game.
The main Ultima series also saw a new release in the same year that The
Stygian Abyss came out. Ultima VII: The Black Gate is thought by some
to be the best game in the series, although others believe Ultima III to be
better. In any case, Ultima IV stands out as the first to use real-time
gameplay and have the ability to be completely controlled using a
mouse. It also provided much interactivity with the game world, going
so far as to allow the player to change a babys diaper.
The next several Ultima games failed to maintain the high standards
of The Black Gate, severely disappointing fans. These releases were bugridden, seemed to have been rushed to market, and, somewhat puzzling,
deviated from the gameplay that had made the series a huge hit.
While Origin was enjoying the success of its Ultima series, SSI was
spiraling downhill with the TSR license. Lackluster graphics and
animations, bugs, and other problems couldnt keep fans playing, despite
games based on TSRs Ravenloft campaign and one of the companys
most famous characters, the dark elf Drizzt DoUrden.

Raymond E. Feists Riftwar saga, a major fantasy novel series, was


given the RPG treatment starting in 1993 withBetrayal at Krondor.
Developed by Dynamix, the game utilized a turn-based combat system
and the character developed by increasing his skills rather than using the
popular level-based development of other games. The sequel, Return to
Krondor, was released in 1998 and was considered by fans to be better
than the original, most notably due to that games subpar graphics.
The first couple of years of the 90s saw dozens of RPGs some as
good as weve seen, some merely okay, and some bad. Gamers certainly
werent lacking for games to play. Once id Software released the
blockbuster hitDoom in 1993 though, RPG makers struggled to make
their games look as good as Doom and still play as well as the previous
hit games. That would change in 1994 with the release of the first game
in the Elder Scroll series,Arena.
Although far from perfect, Arena raised the bar for other games that
followed. The size of the world and the open-ended gameplay made the
game one in which the experience lasted as long as the player wanted,
although the main quest was still fairly linear. The combat system was
also unique in that the position of the mouse determined which of eight
different attacks the character would utilize.
The main problems with the game were that it had a lot of bugs and it
required a pretty high-end machine for the time, thus limiting the gamers
who could play.
After Arena, two spinoffs were released along with several
sequels, Daggerfall and Morrowind. The latter game allowed the player
to switch between first- and third-person perspective, something new to
the series. Another new feature in Morrowind was the splitting of the
leveling system into two groups primary stats and secondary abilities.
Players could improve their characters secondary abilities by using

them and increase skills by paying for training or finding and reading
books.
The one big problem, if you choose to look at it that way, was that
eventually the player could develop his character to a level sufficient to
make enemies no challenge for the character, even the most powerful
ones. There were also ways to level the character in ways not considered
normal, otherwise known as exploits. The player could make his
character more powerful without danger, eventually to a point where he
could only have died by not doing anything.
Two expansions for Morrowind were released in 2002 and 2003, both of
which had good reviews. The next game in the series, Oblivion, was
released in 2006 and was an overwhelming success. A new Might and
Magic game,Might and Magic VI: The Mandate of Heaven, showed up
in 1998, following the gameplay style of the Elder Scrolls games, but
with two major differences the player controlled four characters
instead of just one and the combat could be resolved in either real-time
or turn-based modes. The leveling system also deviated in that the player
could spend skill points in any way he wanted, distributing them
between four areas weapon, armor, magic, and miscellaneous.
Although the leveling system made character development a bit
different, it still required the player to spend money in order to train his
character to reach a new level. Since money wasnt easily obtained,
some thought had to go into how best to advance your character
should something be bought, such as a new weapon or magic scroll, or
should the money be spent to level the character?
One other way in which Might and Magic VI differed was in the relative
absence of bugs. This wasnt to last, however. The next game in the
series, For Blood and Honor, was released soon after the previous one,
with only a few improvements. The next game, Day of the Destroyer,

which was released in 2000, suffered from many issues including


unbalanced gameplay (mostly due to the ability to add a dragon to the
players party which, although interesting and unique, did nothing good
for the gameplay).
Considering how bad Day of the Destroyer was, you would think
another game in the series would have gotten more testing and had more
time spent on development. This wasnt to be the case, however. In
2002, Might and Magic IX was released with a slew of problems.
Even though several companies slid downhill with their sequels, at least
one started out strong and only got better. Any RPG (or real-time
strategy) fan probably drools a little when you mention the name
Blizzard, in an almost Pavlovian manner, and with good reason.
Although Warcraft: Orcs and Humans wasnt the first game the
company released, its the game that started Blizzard on its journey to
becoming one of the most solid and successful game development
companies in the industry. RPG fans snatched up Diablo when it was
released in 1996, and its still seeing action today, although its sequel
and the Lord of Destruction expansion are more popular.
Diablo and its sequel boiled down RPG gameplay to the core,
simplifying almost every aspect of the RPG experience. Only three
classes were playable in the first game and Diablo II featured five. Only
four stats were used in the game strength, magic, dexterity, and
vitality. While a skill tree was used, it was fairly simple and not as deep
as the more hardcore RPGs.
Another unique feature was the fact that the dungeons in the game were
all randomly generated and populated. Some fans said this greatly
increased the replay value of the game, but others said it was not as well
constructed as the set-in-stone dungeons of other games.

After a long wait by fans, Blizzard announced Diablo III at the Blizzard
Entertainment Worldwide Invitational in June 2008. The announcement
spawned a flurry of activity on the Internet, most of which centered
around the change in artistic direction. Many fans were extremely upset
by the change and an online petition was even started to try to convince
Blizzard to return to the style of its previous games.
The success of the Diablo series games meant the inevitable release of
clones, some bad, some good, and some greatly improving on the
gameplay, although the latter in at least one case, Sacred by developer
Encore, goes so far beyond that it almost changes the Diablo model. The
fantasy world wasnt the only setting for this style of game. Irrational
Games Freedom Force took a superhero turn on the style of play and
was fairly well received. It even spawned a sequel in 2005, Freedom
Force vs. the 3rd Reich.
One of the more popular of the action-RPG (as the gameplay style
became known) games was Dungeon Siege by Gas Powered Games.
Released in 2002, the game used a real-time 3D engine that allowed the
entire world to be traversed without any loading of data to be necessary.
The game also used a skill-based system for leveling the character,
meaning the player was free to change how the character developed at
any point in the game. The player could equip the character with a
different weapon or have him start using spells and the character would
eventually become proficient with whatever he used.
Another interesting feature of the game was the use of a mule as one of
maximum of eight the party members. This allowed the player to carry
more loot at the expense of a more skilled combat character (the mule
was capable of defending himself, although not well).
A lukewarm reception of the expansion Legends of Aranna the following
year didnt kill off the series. Dungeon Siege II was released in 2005,

featuring a Diablo II style skill tree. An expansion, Broken World,


followed in 2006.
Although it seemed like real-time gameplay might be the way the genre
was to go after the Diablo series and its successors and clones, Interplay
showed that turn-based games still had some life in them. Released in
1997,Fallout did for post-apocalyptic RPGs what Diablo did for the
fantasy genre. It was rich in style, featuring almost morbid bits of humor
and references to many bits of pop culture. Even normally boring
elements like interfaces for leveling a character were made interesting by
the use of illustrations graphically depicting skills. Indeed, the manual
resembled a survival guide created as a government publication.
The inevitable sequel appeared the following year, and was as well
received as its predecessor. Although there were slight improvements to
the graphics engine and gameplay, the company wisely seemed to follow
the motto If it aint broke, dont fix it. Several other releases that take
place in the Fallout universe saw the light of day but werent nearly as
well received.
As early as 2004, Fallout 3 was mentioned, but it wasnt until 2007 that
information really started to become available. Bethesda Softworks
developed the game using the same engine that
powered Oblivion. Fallout 3 was released in October 2008, and based on
reviews, did justice to the series.
Not long after the release of Diablo, a company that has gained at least
as huge a following as Blizzard released what some consider one of the
best, if not the best, RPG ever released. The company was BioWare and
the game was Baldurs Gate, released in 1998. Picking up the valuable
TSR AD&D license, BioWare pumped life back into the franchise,
bringing to life a game that plays almost exactly like a pencil and paper
game of Dungeons & Dragons.

Letting the player control only one character, but with the ability to
recruit up to five other characters, means that the player gets all the fun
of an adventuring party without the need for any other real persons. The
characters even interact depending on their different outlooks, going so
far as to be able to betray the group. For the true RPGer, this is part of
what its all about.
The game goes from real-time to a turn-based hybrid during combat,
which allows the player plenty of flexibility in how battles are fought.
The player could press the Spacebar to pause the game in the middle of
combat, specify actions for characters that they might not have otherwise
performed, and then let combat continue. This system appeals to both
novice and more experienced gamers, letting them manage the character
to whatever degree they want.
The game did include a multiplayer mode that allowed friends to take the
place of the AI characters in the party, but it was buggy and felt almost
tacked on. It did make the game attractive to the Diablo crowd that had
been using Blizzards servers for online gaming.
A year later an expansion pack was released. Tales of the Sword
Coast added new locations, spells, and items, and some gameplay
improvements. It also added new quests, the staple of RPGs. Like most
expansions, it served to tide gamers over until a true sequel came along.
Baldurs Gate II: Shadows of Amn was released in 2000 and became a
huge hit. An enhanced graphics engine upped the resolution to 800 x 600
and many new features were added. Additionally, several of the
characters from the first game made it into the new one. Creating a game
in which players form an attachment to the characters can help entice
fans into buying sequels to that game. Many people still
consider Baldurs Gate II the best RGP ever made.

The game picked up where the first one left off, which meant that if you
hadnt played the first game and enjoyed the sequel, you just might want
to go back and see how the characters got to where they were. It also
meant that players of the first game got to enjoy more of the story that
they had already experienced.
Like the first game, Baldurs Gate II received the expansion pack
treatment a year later with Throne of Bhaal. If you played either of the
first two games, this was almost a required purchase in order to get the
final chapter of the story. More new spells, items, and skills were added
along with a new dungeon that could even be accessed during part of the
original game.
Like Blizzard, BioWare has become known for solid, fun, and
interesting RPGs. So solid was the engine that drove the Baldurs Gate
series games that BioWare licensed it to Black Isle, the company that
made Fallout 2. Released in 1999, Black Isles Planescape:
Torment wasnt the huge hit that Baldurs Gate was, but it was a solid,
fun game that gained fans. Like the Ultima games, Planescape had a lot
to do with getting the player to think about morality, as the character had
the opportunity to join one of several factions and doing so gained him
friends as well as enemies. None of the factions could be labeled good or
bad; they were more varying shades of gray, which might have been the
whole point.
One point that could be looked at as a negative was the use of the abused
character suffering from amnesia device. Fortunately, it was done well
enough that it didnt drive away players. Another often used element
was to inject some comedic aspects into the game which, like the
amnesia device, was handled very well and probably was one of the
reasons the game did as well as it did. Getting the right mix of humor
and seriousness is difficult, butPlanescape managed to find it.

Black Isle struck again in 2000 with the release of Icewind Dale, again
set in TSRs Forgotten Realms. The big difference with this game was
the ability of the player to create not just one but six of the characters in
his group, a major difference from every game before it. Of course, this
added some pressure since the game was very combat-oriented, so a very
balanced party meant the difference between defeat and victory.
Unfortunately, Icewind Dale wasnt the rousing success that other games
using the BioWare Infinity Engine were. In focusing so much on
combat, the rich story of previous games was neglected. In addition, the
smash hits Diablo II and Baldurs Gate II provided stiff competition in
the RPG arena. Icewind Dale must have made a profit, however, as the
expansion pack Heart of Winter was released the following year. The
expansion was a quality product that was recommended for fans of the
game.
The 2002 release of Icewind Dale II was better received due to
improvements throughout the game as well as the move to the 3rd
Edition AD&D ruleset. It was still a mostly combat focused hack-andslash affair, but a worthy addition to the genre.
The Infinity Engine powered games mentioned so far were the only
TSR-licensed games to be released around this time period, but they
were better than several others that appeared. The bug-ridden,
plodding Pool of Radiance: Ruins of Myth Drannor, released in 2001 by
Ubisoft, and the more successful 2003 release by Troika of The Temple
of Elemental Evil: A Classic Greyhawk Adventure proved that a good
license isnt a guarantee of success. The latter has received some patches
even though the developer is no longer with us.
Although many dont consider it a true RPG, Bullfrogs Dungeon
Keeper (released in 1997) and the sequel,Dungeon Keeper 2 (1999) were
good games that had one major distinction from the rest of the crowd

the player was the bad guy. You could guess from the title what the
player did during the game create his or her own dungeon but that
was just the start. The player also had to defend his dungeon against
invading parties of adventurers. This unique twist on the classic
gameplay of the genre was intriguing enough to make the game a
relative success compared to monster hits like the Diablo games.
In 2000, Westwood released Nox, a quirky action/RPG mix that received
only average review scores. It starts out unlike any other RPG Ive seen.
The players character lives in a backwater Florida trailer park not
your typical hero. A wormhole opens up and sucks him into the world of
Nox. The player gets to choose from one of three different character
classes in his quest to defeat the evil sorceress Hebubah. One nice
feature of the game was an included multiplayer feature. This blend of
action and role-playing would become more and more popular
throughout the next half-dozen or so years.
BioWare continued its trend of quality releases in 2002
with Neverwinter Nights. Using a fully 3D engine dubbed the Aurora
Engine, the game was another to use the 3rd Edition ruleset and came
with an incredible toolset that allowed players to create their own
complete adventures that were limited only by their imaginations. If you
havent heard of Neverwinter Nights you should probably turn in your
RPG members card now.
The game received the expansion treatment with three packs released
from 2003 to 2005 Shadows of Undrentide, Hordes of the Underdark,
and Kingmaker. This is in addition to the tons of player-released
adventures. You could probably still be playing today if you tried to
make it through everything thats been released for the game.
Neverwinter Nights 2 was released in 2006, but didnt quite hit the bar
set by its predecessor (82.1% ranking compared to 88.8%, according

to GameRankings.com). Whether or not this is due to the decision to


allow another developer (Obsidian Entertainment) to create it is
anyones guess, but most fans were disappointed with the game. Even
so, it was still good enough that three expansion packs, Mask of the
Betrayer, Mysteries of Westgate, andStorm of Zehir, were released in
2007, 2008, and 2009.
Another BioWare hit quickly followed Neverwinter Nights. Star Wars:
Knights of the Old Republic was published in 2003. It averaged 93.6%
on GameRankings.com, blowing away BioWares previous effort and
continuing its trend as one of the best, if not the best, RPG developers
ever.
Taking place before the events portrayed in the movies, the player
controls a Jedi character. Throughout the 30-some hours of gameplay,
decisions are made that affect which side of the Force the character
follows.
Again, Obsidian Entertainment was called on to create the
sequel, Knights of the Old Republic II: The Sith Lords, and again, didnt
quite blow away critics and players like the first game in the series.
In 2004 Peter Molyneuxs highly hyped Fable hit the shelves.
Unfortunately, the hype was so great that its doubtful any game could
have lived up to it. Many features that Molyneux had talked about didnt
make it into the final game. The features that did make it, however, made
the game a success.
The player controls a young boy known only as Hero. After his village
is raided and destroyed, the character joins the Heroes Guild to train.
The main quest of the game involves the characters journey to discover
the reason behind the destruction of his village.
As with several other RPGs, the decisions made by the player influence
the games ending. In the case of Fable, it also influences the appearance

of the character, one of the best features in my opinion. Play the game as
a do-gooder and the character eventually takes on an angelic appearance,
glowing with light. Be a rotten, dirty scoundrel and the character will
become demon-like, even growing horns. The character is even affected
by eating and drinking, becoming overweight or getting sick and
vomiting. The townspeople also respond to the characters appearance,
which affects what happens during the game.
Fable won more than 50 awards and spawned the inevitable expansion
in 2005, Fable: The Lost Chapters, and it was only a matter of time
before a sequel was announced as well. Again highly hyped, Fable
II was supposed to be everything that Molyneux promised with the first
game and more. After its release in October 2008, it won three Best
Game awards and a Best Original Score award and had overall scores
of 89% and 88.7% on review aggregate websites Metacritic
and GameRankings.com, respectively.
Almost unknown outside of its native Poland, CD Projekt burst onto the
RPG world in October 2007 with the release of The Witcher. For a first
effort (the company mainly had done translations and localizations for
Polish gamers) the game succeeded spectacularly overall, even earning
an RPG Game of the Year award from PC Gamer. Reactions varied
around the globe, but with a GameRankings.com average of 81% and
user score of 9.1, it can be safely said that the game was a hit. Thats not
to say that the game didnt have problems. The biggest seemed to be the
use of a controversial copy protection system that modified the game
content to make it unwinnable. The problem was the systems conflict
with certain software and drivers, which caused it to run against even
legitimate copies of the game. Although a fix exists, its not perfect and
the game has to be started over in some cases.

Another problem involved the game running a check of the systems


hardware when first launched (as opposed to the normal check when the
game is installed) and not running if the system didnt meet the
requirements for the game. Although a patch was released in December
2007 that allowed the check to be bypassed, gamers were left with no
option until then other than upgrading their hardware.
The Witcher used a heavily modified version of BioWares Aurora
Engine (the same engine that powered the original Neverwinter
Nights and a modified version of which was used in Knights of the Old
Republic). This almost guaranteed that the graphics quality of the game
would be excellent. That the gameplay matched the graphics made it a
game every RPG fan should take a look at.
More and more, the line between RPG and first-person shooters (and
even RTS) is becoming increasingly blurred. Some of the top games of
the past several years easily fit into both categories. BioShock, released
in 2007 by 2K Games on both PC and Xbox 360, won dozens of awards
for its incredible environment, sound, and story. It wasnt without its
flaws, however; most notably its Vita Chambers, the recovery system
that brought back the character at half-health but left the health of the
enemies unchanged, allowing the player to defeat enemies by attrition.
BioWare was back on the scene in 2007, releasing its science-fiction
epic Mass Effect. One of the few games to earn a 10/10 by Official Xbox
Magazine (BioShock was another), Mass Effect is an adventure spawning
multiple worlds where the player encounters many different alien life
forms (and can even romance them!). In only a couple of years it won
approximately 80 awards and became one of the most critically
acclaimed games of any genre.
Not only does the player have to save the world, he has to save an entire
galaxy. He wont have to do it alone though, as other characters will join

the player during the journey. As usual, choices change the game and
there are a lot of them to make. Hidden behind the conversation system,
the choices make the game one that you can truly play over and over
again.
Even with the perfect scores and awards, reviewers had some minor
criticism. Item and squad management was overly complex, the player
has limited save slots (although I dont consider this a drawback as I
cant see returning to a point more than 10 saves ago), and the AI of the
players squad could have been better. Still, if youre a true RPG fan,
this is a must-have game. More than likely, the recently announced Mass
Effect 2, due out in 2010, will enjoy the same success.
Hellgate: London was released in 2007 and is kind of a cross between a
single-player and MMORPG. It was another highly hyped game and
with the pedigree of the developers working on it (former Blizzard
employees, some of whom worked on the Diablo, Warcraft, StarCraft,
and World of Warcraft games were behind Flagship Studios), there was
good reason to think it would be a smash hit. However, launch problems
caused concern among players and reviewers, as did the seeming
incompleteness of the game. Financial problems and legal issues caused
the company to shut down the games servers at the end of January
2009, closing off the online portion of the game.
The games weve looked at in this section range anywhere from kind of
similar to completely different in how they look and play. All RPGs,
however, have a lot of similar features when you open up the hood and
take a look inside. In the next sections, well look at these features and
figure out how theyll work in the game well build throughout this
book.

What Makes Up an RPG?

When you think of an RPG from a programming point of view, what


types of objects come to mind? Unless youre really familiar with the
workings of an RPG, you might not see as many at first glance as youd
think. Here are a couple of the more obvious ones:
The player character(s), NPCs, and creatures
Weapons and armor
Items such as treasure, scrolls, potions, etc.
Areas in the game world such as towns, woods, caves, etc.
Stats
Some of the less obvious objects might include:
Tiles Sections that make up a map, usually of a specific type of
terrain and possibly with multiple layers and properties like triggers or
events. The contents could include buildings, items, or creatures.
Conversations Most RPGs allow the player to talk to townspeople
to get an idea of whats going on in the area. This sometimes leads to
quests that the player can complete. There are also usually people like
store owners who will buy and sell items that the player can use and
craftsmen like blacksmiths who will fix equipment that gets damaged
during combat.
Skills Although skills involve performing actions, you can also
think of them as objects attached to an entity.
Spells Like skills, spells usually are thought of in terms of their
effects but, again, theyre objects that are attached to the entity.
Quests Maybe youre getting the picture by now. Anything that
belongs to, is attached to, or can be contained by something else can
usually be designed and coded as an object.
Scripts Youll usually have scripts in files, and loading them into
an object could make them easier to deal with.

Some of these objects are represented on the screen by graphics, but all
are chunks of memory that the programmer manipulates as the game
progresses. They all work together to make the game an interesting, fun,
and exciting experience. If you get one of them wrong, it could ruin the
entire game.

Designing an RPG
In my opinion, designing and creating an RPG is one of the more
involved tasks you can undertake as a game developer. There are many
pieces that must be made to fit together, just like a jigsaw puzzle. Get a
single piece wrong and a good-sized chunk of the rest of the puzzle will
go unsolved. One of the best ways to ensure that youve covered every
aspect of the game is to have a complete design document done before
you even start writing code.

The Design Document


There are different types of design documents and many ways to put
together each type. A good design document template written by Chris
Taylor is available on the Internet. You can also find this template in the
companion files for this chapter. There are a lot of areas in the document
that might not apply to your game, but you can simply remove those.
Just remember to update the document every time something in your
design changes, and specify what those changes are in the history
section. When you want to know later why something changed, youll
thank yourself for doing so. Well delve into the details of the design
document shortly.

Decisions to Make
There is no one correct way to design an RPG, but here are some things
youll need to think about:
Turn-based or real-time combat Real-time is becoming the
standard, but I believe there is still room for a good turn-based RPG.

Some people dont like the click until the monster is dead or click on
the monster and watch the fight type of RPGs. They would rather plan
out each attack that the character makes. Of course, a turn-based RPG is
more interesting if a character has more than one type of attack to choose
from and the type of attack affects the characters defense or other areas.
If I use this attack and hit, the creature should be dead, but if I miss Im
leaving myself wide open. This just isnt something you have the
ability to do with most real-time RPGs.
Along with the type of combat, you may want to consider other aspects
like fatigue and breakage factors for items. Youll need to decide
whether to include these types of things when you make the decision
about what type of combat system to use. The more things you include
in your combat system, the more interesting or realistic it will become.
The downside is that it will take longer to develop and test with each
item you add. Youll have to take into consideration the number of
people you have working on the game and their experience level.
Graphics engine This decision will be made based on your skill
level and preference. I opted for 2D isometric for both this book and the
RPG Im working on. It was the style that was used when RPGs started
to become hits in the industry and, in my opinion, they look the best with
a minimum of work. Other types are 2D (top down using
square/rectangular or hex tiles), and 3D (first person or isometric). 3D
RPGs are starting to become the norm. Eventually I believe all PC,
noncasual games will be 3D, just to take advantage of the eye candy 3D
SDKs give you access to. This will occur when low-end, cheap
computers are equipped with good graphics cards. Many companies that
mass-produce PCs still use a graphics chipset on the motherboard, which
means less power and graphical features. For the independent developer,
2D still works just fine, and many people still play 2D games. One big

advantage is that it doesnt take a top-end system to run 2D games, so


your potential audience is greater.
Casual games are usually low-budget, less graphically rich (usually 2D)
games that dont require long-term time commitments or special skills to
play and usually have simple rules. The sessions or time to complete a
single instance of a casual game are usually around 5 to 15 minutes.
Theyre typically played in web browsers, although theyre also
becoming popular on consoles in special sections like Xbox LIVE
Arcade. Typical genres would be puzzle-based, card, board, and word
games.
Related to the graphics engine is the camera. This is the window or
viewport into the game world. A decision that you can make here is
whether you want a moveable or fixed camera. A moveable camera
allows the player to look at an area of the game away from the
characters position. While it might be a nice feature, its not vital and, in
my opinion, breaks the immersion factor of the game. The player is
supposed to be the character, and allowing him to shift the focus away
from the character breaks that illusion. There will always be things that
break the illusion, but adding things that dont directly relate to the
gameplay is probably something you want to stay away from.
RPG system Decide on the RPG system that is used. This includes
the type of stats for entities, the combat system, and the magic system.
All three must work together to form a cohesive, balanced game. If your
magic system is too powerful, no player will play a melee character.
Conversely, if a mage is so weak at the beginning that hes unable to
survive combat with your weakest creature, everyone will play a fighter
character. It will take much testing to ensure everything is balanced, so
plan accordingly. Along with this decision is the type of RPG you want
to do standard fantasy based, realistic medieval period, present-day

spy adventure, near or far future sci-fi epic, or even a superhero-based


game. Almost anything you can come up with will have its fans.
Fantasy-based RPGs are still the big seller, but superhero games have
been released and done fairly well (Freedom Force, Marvel
Superheroes, and the MMORPG City of Heroes and its expansions), and
the sci-fi RPG Mass Effect was a huge hit. Most present-day and future
time period games that have been released are action/shooters (some
with elements of an RPG, la Deus Ex), so a game set in one of these
periods that gets it right could do well for a while.
Another aspect of the RPG system youll have to think about is whether
or not you want to have the characters belong to a class, such as fighter,
mage, cleric, etc. If you dont use a class-based system, youll probably
use something like a skill-based system. Both have their pluses and
minuses. Both also have their share of players that prefer that system
(usually very vocal players if you give them a forum to express their
preference). I think either system is equally difficult to implement
correctly, so the choice will probably boil down to what you want to do
and what system you like in an RPG. Well use a hybrid class and skillbased system in this book, but completely class-based or skill-based
systems are also options.
Type of adventure Will the game be a straightforward dungeon
romp or will there be a full, rich backstory and/or multiple quests for the
player to complete? Both types of games can be huge hits. The games in
the Diablo series are examples of hack-and-slash dungeon adventures.
There was a bit of a story there, but it was pretty much peripheral to the
action. Dungeon Siege went a little further with the story element, but it
was still more action oriented. Neverwinter Nights concentrated more on
the story/plots and quests than on the combat aspect of the game. All of
the games were pretty big hits, so theres obviously an audience for

either type of game. Youll likely end up developing the type of game
you enjoy, and thats probably a good thing to do.
Save system How will the game save the players progress? RPGs
typically take anywhere from several dozen to hundreds of hours to
complete. Obviously this isnt going to happen in one session of play.
The player is going to want to quit at some point and be able to come
back and pick up where he left off. Youll have to decide if you want the
player to be able to save at any point during the game or if the progress
can only be saved at certain points (for example, only in noncombat
situations). Also, if you choose the latter, how often will the progress be
saved? If its not often enough, the player could get annoyed at having to
retrace his steps. If you allow the player to choose when he saves, how
many slots will he have to save to? If you give him unlimited slots you
run the risk of having the player save every couple of minutes, which
means theres really no risk in doing dangerous things. If you give him
only a certain number of slots, hell have to overwrite the older ones,
which could mean more risk if he needs to revert back to a time before
his oldest save.
Personally Im more in the let the player save to limited slots camp.
There may be times when the player has to stop playing at an
inconvenient time, like right before a save point, which means a lot of
retracing of progress. This reason alone is sufficient for me. I know if I
were the one playing Id be very annoyed at losing all that progress.
Tools Develop the tools for creating the game. Although not
necessary, certain tools could make the creation of the game much
easier. This could include a map editor at a minimum. Other tools might
be a script compiler or character editor. Well create a basic map editor
later on in the book. Youll have to evaluate this area carefully. Some
time spent up front may save you time in the end, but too much time

wasted on tools might mean that you never get anything done on the
game itself.
One thing to consider when developing your tools is whether or not you
want to release them to the public and allow players to create mods for
your game. It seems that almost every game out there is allowing players
to add content to the basic game. This is a good thing in that it draws
more people in since many players want this ability and will play a game
with mod capability over one without. The downside is that it usually
takes a good chunk of time to add this capability to a game. If your
toolset is not user-friendly, youll never hear the end of it from the
players. You also have to design the game to have the ability to use
player-created content. This could present some problems if not done
correctly.
My feeling is, since you have to design the tools anyway, why not try to
give the player more reasons to play your game by designing them well
enough that a player can use them with a minimum of problems. Some
companies have actually hired people based on mods that theyve
created for games. You may find someone that youll be able to work
with on a future game if you give the players the ability to show their
stuff.
Scripting system Along with the tools, you may want to decide if
youll include a scripting language with the game. I mention this outside
of the tools since its a huge task to develop even a basic scripting
system. You can use a scripting system for several different things,
depending on how deep you make it. In-game cut-scenes are one thing
that can be done with a scripting system. A scripting system can also be
used for things like conversations with NPCs, dynamic quests, and AI.
All of these can be done without a scripting system, but it may be more
difficult. Depending on how deep and rich you want to make your RPG,

youll have to weigh the costs carefully. We wont be implement a


scripting system in this book, but the game that well develop at the end
of the book will have quests and basic AI as well as a very limited
conversation system.

Our Design Document


The sample game that well develop in this book will be fairly simple,
containing only three areas and one quest. However, it will demonstrate
how to develop just about every part of the systems found in most RPGs
today. The player will be able to select the class type for his character,
which will enable him to select different skills and, if applicable, spells.
We wont need most of the sections of the design document template
that was mentioned earlier, so well just skip over those parts. What we
will need is discussed in the following sections.
Game World Overview
The game world will consist of three different areas a small town
where the player receives his initial quest and can buy and sell items, a
wilderness area where random encounters may occur, and a small
dungeon that is the target of the quest.
Time will not be considered in our game design. It will always be
daytime. This is not something that should be done in a complete game,
however. Modeling time is difficult, but makes the game more realistic
and immersive in my opinion.
Weather also will not be factored in. Like time, weather should be
incorporated in a full game. Just having weather be seen and not affect
characters, however, can be a negative. A person does not perform as
well in bad weather as in good weather. For example, tracking would be
an extremely difficult task in a hard rain. Footprints would be washed
out and any damage to foliage by the character being tracked would be
difficult to discern. It would still be a possibility, but the difficulty factor

would increase greatly. The opposite could be possible of course. A light


snow that doesnt quickly fill tracks could actually increase the
possibility of a successful tracking attempt. These two examples should
make it fairly apparent that implementing weather requires a lot of
design and testing to get correct if you want to have it affect gameplay.
Camera
The players view on the world will be the same as that used in the RPG
Starter Kit thats available on the Creators Club website
(http://creators.xna.com). Figure 1-2 shows a screenshot of the RPG
Starter Kit during gameplay.

Figure 1-2
The camera will track the character, keeping him centered on the screen
when possible, but not showing a blank area where the level ends.
The rendering system used in the game will also be similar to that of the
RPG Starter Kit. Square tiles will make up the level and some tiles will
be inaccessible for the character to walk on. Buildings and other features
will take up multiple tiles.
Full lighting will be used throughout the game. This is another area that
should probably be changed for a full game. Normally dungeons use
ambient lighting for a more realistic atmosphere.

Ambient lighting refers to using all existing light sources in the area to
calculate the degree of illumination of all objects in the area. Outdoor
areas would normally be fully lit during the daytime. Dungeon areas
would vary due to the light sources available (torches, magical lighting,
etc.). Only the areas around these light sources are fully lit, with the
intensity decreasing with distance from the source.
Game Characters
The player will control one character throughout the sample game. The
entity class will be selectable by the player. All stats for the character
will be generated randomly.
There will be one nonplayer character in the town level of the game.
This NPC will be the one that gives the player his quest.
There will be several types of creatures and monsters in the wilderness
and dungeon levels. In the wilderness, the type of creature will be
generated randomly whenever a random encounter occurs. The random
encounter will occur 25% of the time for each tile the character moves
to. Monsters in the dungeon level will be placed by hand.
User Interface
Several user interfaces will be used in the game, besides the menus that
will be modified from the Game State Management Sample.
Inventory interface This interface will show the items in the
characters inventory and allow the player to choose items for the
character to use.
Toolbar interface This interface will display the characters current
health and mana and allow the player to quickly select items (potions,
scrolls, etc.), skills, or spells to use. The number of slots will be limited
by a number to be determined.
Items

A limited number of items will be available. At a minimum there will be


one melee weapon usable for each class, and one ranged weapon for
those capable of using them.
Healing potions will be available either from the shopkeeper in town or
dropped by monsters when appropriate. The latter will be set by hand as
items to be dropped 50% of the time. Potions may also be found in
chests that will be placed at various locations in the dungeon level.
A scroll will also be available just like the healing potions. The spell on
the scroll will be generated randomly.
Music
Music will be limited to play only while the menu is displayed. Ideally,
you could have background music playing in the three different areas
mellow for the town, increasing in tempo and intensity as the player
progresses to the wilderness, and at full tempo and intensity for the
dungeon.
Single-Player Game
The game session should take no more than 5 to 10 minutes to complete,
depending on the number of random encounters that are generated as the
player moves through the wilderness. The player will not gather enough
experience to gain a level. The game ends when the player interacts with
the shopkeeper in town after having completed the quest in the dungeon
level.
Multiplayer Game
The game will not feature any multiplayer capability. See Chapter 12 for
suggestions about multiplayer enhancements.

Next Up
So now that we know what an RPG is, what pieces well need to
implement to create one, and how to ensure we dont get lost in the
process of creating our masterpiece, were ready to take our first steps
into coding. Well start with the most important piece from the players

point of view the character he controls and the people and creatures
hell run into.
If you havent already done so, you might want to download the files for
each chapter (you can find them
athttp://www.wordware.com/files/XNARPG) in order to better follow
along with the text.

Chapter 2
RPG Entities Characters, NPCs, and
Monsters
The character is the players extension into the game world.
Unfortunately (or fortunately, depending on how you choose to look at
it) hes as helpless as a baby without the player (scripts/AI
notwithstanding). The player must do everything for him tell him
where to go and what to do. His virtual life is literally in the players
hands. The player also determines his path in life. Should he be a
warrior? If so, what kind? The strong, dumb brute who plows through
everything and thinks with his sword or one who plans before going into
battle? How should he fight toe-to-toe or hit and run? Maybe he
should be a mage weak in body but with immense powers of magic at
his disposal. Maybe the player doesnt want to play as what would
normally be considered a good character. Perhaps a thief or assassin is
more his style. The possibilities can be almost endless depending on
what you give him. If you design it right, the player could even go
through the game more than once, playing as a different character each
time and having a completely different experience. You could also allow
the player to have a character with more than one class. Some paper and
pencil RPG systems allow multi-class characters, such as a fighter/mage

or mage/assassin. Some classes could be built as a multi-class type, like


a ranger or druid a fighter who specializes in nature-related magic. A
bard could also have some fighting skill and music-related magic. A
ninja could be a thief with magic relating to stealth. Theres a third
possibility the classless character. This type of character is usually
found in a skill-based system where he can do anything (albeit not well
at first) and gets better as he uses skills.
How you design the character is up to you all types have their
positives and negatives. Designing your system to be as open as possible
will allow you to go whichever way you want. Well take a middle-ofthe-road approach classes and skills. The character can do almost
anything he wants, but it will be more difficult to learn some skills than
others depending on his class. For example, a mage could learn to use a
sword, but wouldnt be as good with it as a fighter. This also allows us to
give bonuses for certain skills based on the characters class.
The code that well use to represent our character is used to represent
any entity, be it a player character, nonplayer character (NPC), or
monster. Although a character may be referred to, almost everything in
this chapter, and most of the others, will apply to all types of entities.

Stats
One of the main defining features of an entity is its stats. These are the
values that tell us how strong a character is, how intelligent he is, how
much punishment he can take in battle, etc. Here are some typical stats
that are used in many RPGs and what they mean:
Strength (STR) How strong a character is and how much weight he
can carry. It is also used for calculating damage bonuses when fighting
with melee weapons and limiting the weapons and armor a character can
use. A 98-pound weakling wouldnt be able to lift and fight with a two-

handed sword or wear full plate mail. This would be a primary stat for
melee classes like fighters.
Primary stat: A stat that should be higher than all others, allowing the
character to better perform skills related to what he does for a living.
Dexterity (DEX) This is used in determining how well a character
performs in combat and can be used to limit the weapons available to a
character. It can also be used to determine how well a character performs
skills that require manual dexterity, such as lock picking, playing an
instrument, etc. It would be a primary stat for thieves, assassins, and
monk-type characters.
Agility (AGI) While DEX is used in hitting a foe, this is used in
determining how well a character can avoid being hit and perform other
skills that require coordination of the entire body, such as tumbling.
Some systems may use one stat for both, but I prefer to split them this
way. It just seems more realistic to me and allows more flexibility. This
is another important stat for characters with a DEX primary stat.
Constitution (CON) This is a measure of how quickly a character
recovers from injury or how resistant he is to poison and disease, and
helps in calculating how much damage a character can take before losing
consciousness. This is another important stat for melee characters.
Intelligence (INT) How quickly a character can learn such things as
magic and languages and figure out problems. This would be a primary
stat for characters that use magic.
There are several other stats that could be used: Wisdom and Charisma,
for example. Some systems use Wisdom for cleric/priest type character
classes and Charisma is used in relating to people. Bards, for example,
would depend on Charisma.
To hold the information on a stat, well define a class with the following
members:

Listing 2-1

public class Stat


{
private StatType _type;
private string _name;
private string _abbreviation;
private string _description;
private string _statCalculation;

private static readonly char[] _operators = { '+', '-',


'*', '/' };

public const short MaxStatValue = (short)DieType.d100;


public const int PoundsPerStatPoint = 3;

In order to make the RPG library as flexible as possible, a developer will


be able to create whatever stats he likes. We need to have a way to easily
find one stat in the list of stats, however. Well use the _name member
as it will be unique for each stat. This will be done for some classes in
the library for which we can basically guarantee that the name is unique.
Other classes where the name member would be not so easy to deal with
(skills for example) will have another member to allow an item to be
found. Well see how this works in the next chapter.
The _type member can be one of two values:
Listing 2-2

public enum StatType


{
Regular,
Calculated
}

Some game systems have stats that are based on the values of other stats
or involve calculations such as the average of two stats. The _type and
_statCalculation members allow you to do this. Were only allowing four
operators to be used for calculated stats as you can see from the
_operators array. If you need more than this, simply add them to the
array in the declaration and add the logic to deal with them in the code
that calculates the stat.
Listing 2-3

public Stat()
{
}

public Stat(string name)


{
_name = name;
}

public StatType Type


{
get { return _type; }
set { _type = value; }
}

public string Name


{
get { return _name; }
set { if (!string.IsNullOrEmpty(value)) _name = value; }
}

public string Abbreviation


{
get { return _abbreviation; }
set { if (!string.IsNullOrEmpty(value)) _abbreviation =
value; }
}

public string Description


{
get { return _description; }
set { if (!string.IsNullOrEmpty(value)) _description =
value; }
}

public string StatCalculation


{
get { return ConstructStatCalculation(); }
set
{
if (_type == StatType.Calculated)
{
if (!string.IsNullOrEmpty(value))

{
_statCalculation = value;
}
}
else
_statCalculation = value;
}
}

Two constructors are provided for a bit of flexibility, but only the first is
required because of the way were going to handle dealing with the files
that will store the data for our stats. We have our accessors for the
members for the same reason. I chose not to make the members public
because were doing a bit of validation to ensure none of them can be set
to empty or null values in most cases. If the stat is not a calculated stat it
doesnt matter if we set it to empty or null, but if it is we have to ensure
theres a calculation there or well get an exception when we attempt to
use it.
Well be using a 1-100 range for our stats. We note this with the
MaxStatValue member, which allows code outside the Stat class to tell
what the greatest value for a stat can be. Other commonly used ranges
are 1-10, 1-18, or 1-20. I like the bigger range since it allows more
variation. In fact, well be making everything we can 1-100 based if it
makes sense, as youll see later. Although well use the 1-100 range the
most, we will have others, so well create an enum to define them:
Listing 2-4

//Enum for types of dice


public enum DieType
{

d4 = 4,
d6 = 6,
d8 = 8,
d10 = 10,
d12 = 12,
d20 = 20,
d100 = 100,
MaxDie = 100
}

You generate a number in the range by calling one of the static,


overloaded GetRandomNumber functions:
Listing 2-5

public class GlobalFunctions


{
static Random rnd = new Random();

public static short GetRandomNumber(DieType die)


{
return (short)rnd.Next(1, (int)die + 1);
}

public static int GetRandomNumber(int min, int max)


{
return rnd.Next(min, max + 1);
}
}

Well be adding more functionality to this class as we go on.

The parameters of the second version of the function allow you to


generate a number in any range. For stats, this will always be from 1 to
100, but other parts of the game will use different ranges, such as the
damage caused by a weapon.
The PoundsPerStatPoint member tells us how many pounds a character
can lift for each point in his Strength stat. Well see this used a bit later
in the chapter in a calculation.
So we have our Stat class, but we dont need to store all this data in
every entity. For that we have another class called, amazingly enough,
EntityStat:
Listing 2-6

public class EntityStat


{
private string _stat;
private short _value;
private List<Bonus> _bonuses;

public EntityStat()
{
}

public EntityStat(string stat, short value)


{
_stat = stat;
_value = value;
}

public string StatName

{
get { return _stat; }
set { if (!string.IsNullOrEmpty(value)) _stat =
value; }
}

public short CurrentValue


{
get
{
short val = _value;

foreach (Bonus bonus in _bonuses)


val += bonus.Amount;

return val;
}

set{}
}

public short BaseValue


{
get { return _value; }
set { _value = value; }
}

public List<Bonus> Bonuses


{

get { return _bonuses; }


set { _bonuses = value; }
}

public void IncreaseValue(short val)


{
_value += val;
if (_value > Stat.MaxStatValue)
_value = Stat.MaxStatValue;
}

public void ReduceValue(short val)


{
_value -= val;
if (_value < 1)
_value = 1;
}

public void AddBonus(Bonus bonus)


{
if (_bonuses == null)
_bonuses = new List<Bonus>();

_bonuses.Add(bonus);
}

public void Update(float time)


{
if (_bonuses == null)

return;

Bonus bonus;

for (int i = _bonuses.Count - 1; i >= 0; i--)


{
bonus = _bonuses[i];

bonus.ElapsedTime += time;

if ((int)bonus.ElapsedTime >= bonus.Duration)


_bonuses.Remove(bonus);
else
_bonuses[i] = bonus;
}
}
}

We have our _stat member, which will be the name of the stat, and
_value, which is the normal unmodified value of the stat. The list of
Bonus objects allows us to modify the stat for a short period of time.
This could be anything from poison, which would reduce the stat, to a
magic spell, which could increase or reduce it. If we want to check this
modified value, we use the CurrentValue function. If we want to change
the normal value, we can either set it directly using BaseValue or add to
or subtract from it using the IncreaseValue or ReduceValue methods.
Note that the two functions have validation to ensure the value of the stat
cant be set outside of the 1-100 range. The IncreaseValue function does
this by using the static MaxStatValue member of the Stat class. If you
want to change your stat range to, say, 1-20, you would change this

member, and all the code that deals with checking for maximum stat
values should work without modification. This is a good thing and
something you should do whenever possible.
The Bonus structure looks like this:
Listing 2-7

public struct Bonus


{
public BonusType Type;
public short Amount;
public int TimeStarted;
public int Duration;
public float ElapsedTime;
}

Every time through the game loop when the game is running each stats
Update method will be called, passing the elapsed time since the last
update. Well use this value to update the ElapsedTime member of every
Bonus object in the list. If the ElapsedTime member is greater than or
equal to the Duration member, the object is removed from the list.
Bonus durations must take into account when the game is paused and
unpaused or when the player quits. When the game is paused or ended,
the Update method is not called. This is done outside of the class in the
code that handles the interface and input. Well see that in action later
on.
Although bonuses are the only way stats can be affected in our game,
some systems allow stats to increase in other ways, most notably by
checking every level to see if they increase. Although some stats like
Strength or Constitution could theoretically increase during the course of
an adventure, I dont believe every stat has to have this capability. A

full-grown mans dexterity is unlikely to get significantly better just


from being involved in battles or performing skills like lock picking. A
mages Intelligence stat is unlikely to increase just from casting spells. If
you want to allow a characters Strength or Constitution stat to increase
through training, feel free to implement it. Such a thing isnt significant
in creating an entity so we wont go over it here.
Every stat is saved in its own XML file, which during development
looks like this:
Listing 2-8

<?xml version="1.0" encoding="utf-8"?>


<XnaContent>
<Asset Type="XNA_RPG_Library.Stat">
<Type>Regular</Type>
<Name>Strength</Name>
<Abbreviation>STR</Abbreviation>
<Description>The ability to lift or move objects and to
increase melee attack damage</Description>
<StatCalculation Null="true" />
</Asset>
</XnaContent>

Saving our classes to XML like this is easily done using the
IntermediateSerializer class built into the XNA Framework:
Listing 2-9

private void SaveStats()


{
try

{
XmlWriterSettings settings = new XmlWriterSettings();
settings.Indent = true;

XmlWriter writer;

foreach (Stat stat in _stats)


{
writer = XmlWriter.Create(Application.StartupPath
+
@"\Games\" + _gameName + @"\stats\" +
stat.Name +
".xml", settings);

IntermediateSerializer.Serialize(writer, stat,
null);

writer.Close();
}
_saved = true;
}
catch (Exception e)
{
MessageBox.Show(e.Message);
}
}

If you have any experience with serializing XML data, you may wonder
why the XmlSerializer class isnt being used. The IntermediateSerializer
class has the following benefits over XmlSerializer:

Compact XML representation for lists of numeric and vector types


Handles arbitrary polymorphic data without requiring subtypes to be
predeclared
Handles shared resources, for serializing cyclic data structures
Handles external references, automatically fixing up relative filename
links from one file to another
Supports dictionaries
XML representation can be customized without directly modifying the
target types (by implementing a ContentTypeSerializer)
There are some downsides to using this class, however. The main one is
that it doesnt work on the Xbox 360. If youre using the
IntermediateSerializer to save data to an XML file that will be compiled
using the content pipeline and thus read in using the ContentManager
class, this isnt much of a problem. There are a couple of other
differences between the two classes. I would refer you to Shawn
Hargreaves blog posts on the subject for more information
(http://blogs.msdn.com/shawnhar/archive/2008/07/28/intermediateseriali
zer-vs-xmlserializer.aspx). Hell give you all the information youll ever
need to know about the IntermediateSerializer.
Youll see this same code used for just about every class in our game.
Note that the stats name is used for the name of the file. This will
usually be the case for other classes as well. The EntityStat objects are
saved when the Entity object is saved, as well see shortly.
To load a stat file, another function is added to the GlobalFunctions class
that again uses the IntermediateSerializer class:
Listing 2-10

public static Stat LoadStat(string filename)


{

try
{
XmlReader reader = XmlReader.Create(
new FileStream(filename, FileMode.Open));

Stat stat = IntermediateSerializer.Deserialize


<Stat>(reader, null);

reader.Close();

return stat;
}
catch (Exception ex)
{
return null;
}
}

The code to load most other classes will look just like this; simply
change the class type thats passed and the return type of the object
thats filled with the data from the file.
That covers all the code well need for stats. Once we have some stats
saved, well be able to create races.

Races
How many fantasy or sci-fi RPGs do you know of that allow you to play
as a human only? Not many, I would imagine. Not only does it make the
game more fun and interesting when you have different races, it can also
increase the replay value of your game. Players can play through it as
one race, then start a new game as a different race and potentially have a
totally new experience. MMORPGs usually start players in different

locations based on their race, usually the main city in the area where that
race is dominant. This makes the game somewhat different for as long as
it takes the player to venture out into the rest of the world, which,
depending on how detailed the developers built that section of the world,
could be weeks or even months.
The main use of races (other than having them as part of a realistic
fantasy world) is to modify an entitys stats and skills. For instance,
elves in your world may be slight, beautiful creatures very in tune with
nature. This is probably the classic view. To represent this in your game
you may make some modifications along the following lines:
Table 2-1: Elf stats and skills

Depending on your view, elves could either be so nature-oriented that


their intelligence suffers or so disinterested in associating with other
races that they have time to dedicate themselves to studying the world
around them and all areas of knowledge. In the latter case you would
probably want to make the Intelligence bonus a positive number, say +5
or +10. You could even have several different types of elves the
intelligent type and the nature type. For the world well create as part of
our game, well go with the latter type of elf.
The full list of races and the modifications they receive are as follows:

Human Humans are the average race, neither strong nor weak at
any particular skill and having no stat modifiers and no skill bonuses.
They can be any class and alignment. This flexibility is their strength.
Elf Elves are one of the long-lived races and the embodiment of
nature, making their homes in the forests. Being a solitary race, they
have not wasted their time in the petty bickering and quarreling common
among most races and have been free to study the world around them.
They are stronger at magic than any other race but much weaker
physically. They make excellent mages and rangers.
Dwarf The hardiest of all the races, dwarves are short, stocky,
hairy, and extremely strong. Their constitution is unmatched as many
people have found out when entering into a drinking contest with a
dwarf. They arent the smartest race as a whole, but they make excellent
fighters. Dwarves are normally armed with huge battle axes, but some of
the more dexterous dwarves can be found wielding two normal axes as if
they were small hand axes. Their bonuses are shown in Table 2-2.
Table 2-2: Dwarf stats and skills

Half-Elf Usually the product of violence or a bored female elf s


dalliance with a human, half-elves are usually looked on with disdain by
both races. This means they are often solitary individuals and as such
make excellent rangers. They are not as long-lived as full elves but are
more physical. They are not quite as disciplined as their elf kin, and thus
are not quite as good at discipline-related skills. They are a good

alternative for players who dont want to play a plain human or take
the physical penalties of a full elf.
Table 2-3: Half-elf stats and skills

Halfling Distantly related to dwarves, halflings are a diluted cross


with the human race. As short as their cousins but of normal proportions,
halflings are quick and dexterous. These attributes, combined with a
natural curiosity, make them excellent thieves. They are as nonmagical
as dwarves, though a rare halfling will manifest a wild magical talent.
Table 2-4: Halfling stats and skills

This is a small sample of the races you can have in your RPG. You can
have other half races orcs, ogres, trolls or variations of the
halfling race gnomes, hobbits, etc. You can even get wild and have
creatures such as minotaurs, centaurs, and pixies. Some MMORPGs
allow the player to play as a demon or dragon. Its all up to you, limited

only by your imagination. Of course, you have to consider the time it


would take to create the graphics for each race and to balance the races
so that they are all relatively equal overall. If you dont do this, players
will probably end up playing as the most powerful race and ignore the
others. With each additional race you add, it takes exponentially longer
to balance its not a linear increase.
Well be starting players in the same location regardless of the race
selected. Since were not building a full game we dont really need to
explain why the player is starting where he is. For a full game you would
want to provide some kind of backstory to tell the player how he wound
up at the starting location.

Entity Classes
As with the EntityStat class, theres not a lot to the EntityClass class, so
lets take a look at the whole thing:
Listing 2-11

public class EntityClass


{
private string _name = "";
private string _description = "";
private DieType _hpDice;

private Dictionary<string, int> _statModifiers;

public string Name


{
get { return _name; }
set { if (!string.IsNullOrEmpty(value)) _name =
value; }

public string Description


{
get { return _description; }
set { if (!string.IsNullOrEmpty(value)) _description
= value; }
}

public DieType HPDice


{
get { return _hpDice; }
set { _hpDice = value; }
}

public Dictionary<string, int> StatModifiers


{
get { return _statModifiers; }
set { _statModifiers = value; }
}

public int StatModifiersCount


{
get { return (_statModifiers != null) ?
_statModifiers.Count : 0; }
}

public EntityClass()
{

//Empty constructor for use with the toolset.


//During the game the constructor below is used.
}

public EntityClass(string name)


{
_name = name;
}

public int GetStatModifier(string name)


{
int value = 0;

if (_statModifiers != null)
_statModifiers.TryGetValue(name, out value);

return value;
}

public void AddStatModifier(string name, int value)


{
if (_statModifiers == null)
_statModifiers = new Dictionary<string, int>();

_statModifiers.Add(name, value);
}

public void RemoveStatModifier(string name)


{

if (_statModifiers == null)
return;

_statModifiers.Remove(name);
}

public void ClearStatModifiers()


{
if (_statModifiers != null)
_statModifiers.Clear();
}

public Dictionary<string, int> GetStatMods()


{
return _statModifiers;
}
}

The _name and _description are standard here with one possible unique
feature for the name; while we wont implement it here, some RPG
systems allow a character to be more than one class at a time, such as
fighter/thief or thief/mage. This doesnt include specific examples of
these combinations like rangers (kind of a fighter/thief/mage), druids (a
fighter/mage), or paladins (a fighter/cleric).
These multi-class characters sometimes change classes at a point in time,
switching focus and training from one to another. This is usually the case
for nonspecific combinations where the first class is what the entity
began his adventuring career as and the second is what he switched to. In
some RPG systems, the character may have the skills of his previous

class decrease in effectiveness as he shifts the focus of his training and


usage to the skills of his new class.
In the case of the specific multi-class characters mentioned above, the
character normally is equally proficient in all the skills possessed by
whatever combination of classes makes up his specific class.
Feel free to add either the specific examples or the combination classes if
you wish. You could even create expansion packs for your game in
which you add new entity classes along with the skills, spells, and items
that go with the classes. This gives you the benefit of increased
replayability of your game and means you dont have to spend as much
time up front balancing all of the classes before releasing your game.
Note that a good bit of code would need to be changed in order to handle
multi-class entities.
The _hpDice member is used to give certain classes more or less hit
points than others to simulate the training or lack thereof in the physical
aspects of the character. The combat-oriented classes will usually be
tougher than the noncombat-oriented classes, and we use this member to
show that.

Entities
We now have everything we need to create an entity. There are a lot of
members, so hang on and dive in:
Listing 2-12

public class Entity


{
#region Members

private EntityType _type;

private string _name;


private string _classID;
private byte _level;
private int _experience;

private string _raceID;

private short _baseHP;


private short _curHP;

private byte _diseaseResistance;


private byte _poisonResistance;
private byte _magicResistance;

//Affects is empty for these


private List<Damager> _damageResistances;
private List<Damager> _damageWeaknesses;

//Any misc, offensive, or defensive bonuses


//(i.e., spells cast on character, items, etc.
//May be positive or negative)
private List<Bonus> _defBonuses;
private List<Bonus> _offBonuses;
private List<Bonus> _miscBonuses;

private EntityAlignment _alignment;

private EntitySex _sex;


private short _age;

private List<EntityStat> _stats;

private string _portraitFileName;

private bool _isVendor;

#endregion

Well have four types of entities in our little game, although you could
probably get by with three:
Listing 2-13

public enum EntityType


{
Character,
NPC,
Creature,
Monster
}

We need to differentiate between the players character and the


nonplayer humans that normally populate cities in the game world, so
we have two members of the enum for human and humanoid entities.
While you might be able to get away with only one additional member
for the nonhuman or humanoid (elf, dwarf, etc.) entities, you may want
to have normal, nonmagical creatures (lions, and tigers, and bears, oh
my!) in some areas and magical types (such as orcs, goblins, centaurs,
and dragons) only in places like dungeons. This is one reason for the
Creature and Monster values. Another reason might be cases in which

you have entities randomly picked for encounters in the woods. For
instance, you may only want to pick from creatures, not monsters. You
might also have characters whose interaction with animals could help or
hurt them. An example of this is if we want to penalize a ranger or druid
class character if he kills a creature. Since those classes are supposed to
be in touch with nature, they may temporarily lose some abilities or
bonuses if they kill an animal. That little bit of flexibility might make for
a more real game world.
The _name member is standard. It could be anything from something
like Jonathan the Blacksmith to Black Bear to High Demon. The
player will be entering a name, so you might want to have some kind of
validation to keep players from entering a character that doesnt make
sense, such as a symbol or number, or maybe even a vulgarity if you
have an online component to your game and youre concerned young
kids might be playing. Thiswould take a bit of work and is never perfect,
but anything may be better than nothing. Preventing the entry of symbols
and numbers is easy; simply check the keystrokes as theyre entered and
ignore anything you dont want to allow. For something like vulgarity,
you could create a list of words and validate what the player enters
against the list. If you have player registration information sent to you,
you could update the list when you see something you may have
forgotten.
The _classID and _raceID members are the _name members of the
EntityClass and Race classes selected for that entity or could be empty in
the case of creatures or monsters. This is another case where validation
could be used to ensure valid data is entered for character or NPC
entities.
The _level and _experience members work together in advancing the
character or making him more powerful. An entity could get experience

for killing other entities, finding treasure, or performing any action that
you decide. Upon reaching a certain number of experience points, an
entity would increase his level. This would give him skill points to
increase his skills, and possibly allow his stats to increase if youre using
that option. Usually the number of experience points needed to reach a
new level is a cross between a linear progression and an almost
exponential one. At first you might see something like:
Table 2-5
Level

Experience Required

1000

2000

3000

4000

5000

Once you start reaching higher levels, the amount required to reach the
next level increases greatly:
Table 2-6
Level

Experience Required

20

200000

21

210000

22

225000

23

250000

24

300000

25

325000

26

350000

27

400000

28

450000

29

500000

30

1000000

The higher the level, the more experience is required to advance, which
means the character will have to fight tougher monsters in order to get
more experience per fight. Usually the monsters have to have a level
somewhat near the characters level in order to get experience.
Sometimes the amount of experience decreases with the increase of the
difference between the monster and character level. That is, the monsters
that the character fought at level 5 probably wont give him any
experience at level 20, so he wouldnt be able to just fight them and
expect to advance.
The _baseHP and _curHP members are the characters base amount and
current amount of hit points. Hit points are a standard technique used in
RPGs to determine how much damage a character can take. When a
character reaches one-tenth of his base hit points, he becomes
unconscious. When he reaches zero hit points, he dies. This also is a bit
different from most RPGs. In some, when you reach zero you become
unconscious and a negative number means you die. In others, you never
lose consciousness; you just die when you reach zero. I dislike these for
two reasons. First, you start dealing with negative numbers when theres
no reason to. Second, dying without losing consciousness is unrealistic.
There should be an opportunity to survive an encounter by losing
consciousness. If a player is fighting an unintelligent creature that
assumes the character is dead when he loses consciousness, the player

might survive the encounter. Its a very slim chance, but at least its
there.
There are many ways to calculate an entitys hit points. The calculation
Im using is to take the average of the entitys Strength and Constitution
stats and add a random number from 1 to the DieType value for the
entitys class for each level of the character. Expressed as a formula, this
would look something like the following:

Many RPG systems only give the character a couple of hit points to start
off, especially if its a nonfighting type such as a magic user. You could
almost blow on them and they would die. Any character hardy enough to
take on the adventuring life would have to be a pretty rugged individual
if he was combat oriented. Even for noncombat characters, you would
expect them to at least be able to get bitten by a rat without dying.
The next three members of the Entity class (_diseaseResistance,
_poisonResistance, and _magicResistance) are meant to help deal with
things that you almost always encounter in RPGs, especially the last one.
A character will have a certain chance to resist the effects of disease,
poison, and magic. This chance may be modified by his race and
possibly his class. The members hold those modifiers, rather than access
the characters class and race each time and do the calculation. A druid
or ranger may be more immune to disease. A mage may be better able to
resist magic. A cleric may be better able to fight off poison due to his
healing nature. The value of the variable will be subtracted from a die
roll to determine if the character succumbs to the influence of whatever
he is facing.
Diseases and poisons can be found in many places and contracted in
many ways through plants and other environmental objects, creatures
both normal and magical (you could even call something like

zombification a disease if you want, since in most movies if you get


bitten by a zombie the effects are like a disease), and specific spells by
evil magic users. The _magicResistance member you can expect to be
used most often though. Any combat or noncombat encounter with
magic will usually provide the chance to nullify or reduce the effects or
results of spells, traps, weapons damage (if the weapon has magical
properties), or anything else with a magical component. How you come
up with a value for these members could be dependent on a number of
factors, with the stats you use for your entities likely being the biggest.
For disease and poison, you would expect an entitys Constitution stat to
figure into the value. Well make it somewhat simple and easy, dividing
the Constitution stat by 10 to use as the value for these two, and the
average of the Constitution and Intelligence stats divided by 10 for the
_magicResistance member.
The Damager structure that makes up the objects in the lists looks like
this:
Listing 2-14

public enum DamageType


{
Crushing,
Piercing,
Slashing,
Fire,
Water,
Magical,
Disease,
Poison
}

public struct Damager


{
public DamageType Type;
//Format = "n,n"
public string DamageAmount;
//The type of entity the damage affects, empty for all
types
public string Affects;
}

Well be using the Damager structure later on with items, thus the reason
for the Affects member. Since the Damager objects in the two lists are
specific to the entity, the string will be empty in these cases.
The _damageResistances and _damageWeaknesses members provide a
bit of uniqueness for entities. The items in these two lists can come from
any number of places spells cast on the entity, potions the entity
might have drunk, genetic mutations or other background explanations,
etc. Unlike bonuses, these are meant to be permanent modifiers,
although you could have bonuses that have no duration and are treated as
permanent.
It should be obvious, but for the items in the _damageResistances list,
the DamageAmount is used to reduce damage of a specific type, not
increase it. If you wanted to make sure there was no misunderstanding,
you could create a Resister struct with the same members, but that would
be a waste in my opinion so I didnt bother. I figured anyone who looked
at it would figure it out, but I felt it worth mentioning anyway.
Examples of resistances could be a skeletons resistance to piercing
weapons. As you can probably imagine, its difficult to really do damage
to a skeleton with these kinds of weapons since they dont bleed and

have no internal organs to pierce. Even if the weapon did hit a bone, the
tiny hole would probably not be noticed. Examples of weaknesses could
be werewolves being affected by silver; vampires and holy water or
sunlight (normal or magical in nature); mummies or zombies and fire;
and water-based creatures and fire or fire-based creatures and water. Just
as a skeleton might be resistant to piercing weapons, it could have a
weakness against crushing weapons.
The next three members are similar to the last two, but they apply to
specific times, two of them during combat and the other in noncombat
situations. The _defBonuses list contains bonuses that apply to an
entitys defense and the _offBonuses list applies to the offensive
capabilities. The _miscBonuses are used out of combat for things like
healing, tracking, hiding, etc. The bonuses can be the result of spells cast
on the entity, potions, or natural abilities.
The _alignment member holds a value for one of three different
alignments:
Listing 2-15

public enum EntityAlignment


{
Good,
Neutral,
Evil
}

The uses for a characters alignment are varied and depend on how
detailed you want your system to be. Alignment can affect the
experience a character gets from killing entities and might cause the
character to actually lose experience in some situations (a paladin-type
character who is noble might lose experience by attacking an entity from

behind, for example, whereas a thief or assassin might get more


experience). Alignments can affect the spells a character can learn, the
items a character can use (magical weapons with an intelligence could
have an alignment and prevent a character from taking advantage of its
abilities or actually damage the character if he attempts to wield or use
it), and the willingness of NPCs to help or interact with the character. All
of these things will have to be determined by the developer, taking into
consideration many factors time of development, realism of the
system, experience of the developers, etc. In general, alignments can be
useful in making the world more interesting and rewarding the player for
having his character perform as a real-life person of that type would.
The alignment of a character is his moral orientation and defines how a
character will conduct himself and act in certain situations.
Good and Evil are fairly straightforward. For our purposes, Neutral
describes a character that is mainly interested in himself and doing
things that benefit him. Although hes totally self-centered, he can shift
slightly to Good or Evil as the situation permits if it benefits him in the
end. Although this might seem to be the best alignment, well balance it
out by offering very little in the way of items specific to this alignment.
Also, NPCs of Neutral alignment are rare and (depending on the NPC)
will be slightly less willing to help out a Neutral character than a Good
or Evil character.
The _sex and _age members dont hold any surprises, except that the
_sex member could be ignored for nonhumanoid entities such as
creatures or monsters, no matter what you set it to. While animals
usually are either male or female, it might not matter for your game and
creating two entities where the only difference is sex might not make
sense. You could always randomly pick the sex at run time if you wish.

The age of a character is usually dependent on his race. Some races have
extremely long lives on average. Age can also affect a characters
performance in combat and other situations if you want to enhance the
combat resolution code by adding this kind of calculation. A 20-year-old
human fighter is usually more likely to win when in combat with another
human fighter who is 50 or older. On the other hand, a magician who is
40 is likely to have picked up more arcane trivia than one who is 20, and
might have a better chance of recognizing an obscure book or rune. For
the purposes of this book we wont take age into effect, but its available
for anyone who wishes to incorporate it into their system.
The _portraitFileName member is used only in your GUI. Some RPGs
display a picture of the character that the player can click on to access
information about him such as stats, equipment, skills, etc. You can see
the pictures of the characters in the group in the upper-right corner of the
following screenshot:

Figure 2-1
You might allow the player to import his own portrait. This gives him a
little more attachment to his character, which is important. If the player

doesnt feel an attachment, he may not really care about what happens to
the character and may recklessly charge into situations that could kill
him. If the player feels attached to the character and cares what happens
to him, he might play the game differently, thinking before charging in.
Something this simple could result in an entirely different experience.
Later on in the game well be adding the ability for the player to buy and
sell items at a store. In order to determine when the player is interacting
with a vendor, the _isVendor property is checked. If the value of the
property is set to true, a GUI is displayed to allow the player to buy and
sell.
You can mix and match classes, races, and alignments to restrict how a
person plays a character. For example, a good thief is kind of a
contradiction, unless you want to imagine a Robin Hood type character.
Also, a dwarf thief is probably a rarity as dwarves arent usually known
for their finesse and subtlety, two things a thief needs to be successful. I
can almost imagine a drunken dwarf thief stomping around in the dark,
cursing, and trying to sneak up on someone to mug him. Hes not likely
to surprise anyone that way. Also, a halfling fighter or ogre monk would
be a very rare thing to see. The following tables show the possible
combinations well use:
Table 2-7: Race/class combinations

Table 2-8: Race alignment combinations

Table 2-9: Class alignment combinations

Lets take a look at one additional function in our class:


Listing 2-16

public int MaxWeight()


{
int str = 0;

//find the strength stat


foreach (EntityStat stat in _stats)
{
if (stat.StatName.ToLower() == "strength")
{
str = stat.CurrentValue;
break;
}
}

return str * Stat.PoundsPerStatPoint;


}

This simply lets us know whether or not an entity can lift a particular
weight without having to access the Strength element of the Stats
collection. Code outside of the class could access the data directly and
do the calculation itself, but if you decided to change the multiplier to
another number, you would have to find every line of code that did the
lookup and calculation and change it. Helper functions like this mean
code only needs to be changed in one place. All code that calls the
function gets the updated value automatically.
The Entity class will expand as we implement other objects in coming
chapters. Things like skills, spells, and inventory items will round out
our Entity class. If you thought there was a lot of data to keep track of
with up to this point, you havent seen anything yet.

The Toolset
Throughout this book, we will construct a toolset to aid in the creation
and management of various objects that can be used in the game. The
first part of the toolset will allow the user to create and manage entities
PCs, NPCs, and creatures. Before we can do that though, we need to
create the data for stats, entity classes, and races. Heres what the toolset
will look like when its launched:

Figure 2-2
Before we can start creating our data, we need to create a game for it to
be attached to. For now, all we need to know is the name of the game
and a description for it:

Figure 2-3
Well store this data in a class, of course:
Listing 2-17

public class RPGGame


{
private string _gameName;

private string _description;

public string GameName


{
get { return _gameName; }
set { if (!string.IsNullOrEmpty(value)) _gameName =
value; }
}

public string Description


{
get { return _description; }
set { if (!string.IsNullOrEmpty(value)) _description
= value; }
}
}

Well be adding more to this class in later chapters.


All the data for the different objects will be created in folders underneath
a folder created for the game. The folder structure will look like the
following figure:

Figure 2-4
Once we have our game created, youll notice that the only button thats
enabled is the one to create stats. That makes sense since stats drive
pretty much everything in the game. Click the Show stats editor form
button (

) and youll see the following:

Figure 2-5
Well be creating five stats Strength, Dexterity, Constitution, Agility,
and Intelligence. Enter the following information (or open the files
named <stat name>.xml in the companion code, found in the Chapter
2\XNA RPG Toolset\bin\Debug\Games\Test\stats folder, clicking the
Add button after each item:
Table 2-10
Stat Name

Strength

Abbreviation

STR

Description

The ability to lift or move objects and to increase melee


attack damage

Stat Name

Constitution

Abbreviation

CON

Description

Ability to withstand and recover from damage, illness,


disease, etc.

Stat Name

Agility

Abbreviation

AGI

Description

Full body dexterity, used in dodging, tumbling, etc.

Stat Name

Dexterity

Abbreviation

DEX

Description

Manual dexterity, ability to use weapons

Stat Name

Intelligence

Abbreviation

INT

Description

Ability to learn things, such as spells, languages, etc.

After you have stats entered, you can enter races. The form to do this
looks like the following:

Figure 2-6
As with stats information, you can open the files in the various folders
under the Chapter 2\XNA RPG Toolset\bin\Debug\Games\Test folder to
see what information will be used in the demo game thats created along
the way in this book.
After races, entity classes can be added:

Figure 2-7
And, last but not least, once you have all these, youre ready to start
creating entities. A lot of information is needed, as you can see
from Figure 2-8.
Most of the data is entered by using the text boxes and combo boxes.
There are several exceptions:
Sex I chose to use radio buttons for this since there are only two
choices for human and humanoid entities. The property is set to
EntitySex.None if the entity type is set to something other than
Character or NPC. If you want to specifically set this for monsters and
creatures, I would recommend using a combo box instead.
Base/Cur HP When creating a player character, these text boxes are
disabled. When creating any other entity, you can change the values that
are calculated by generating stats.

Figure 2-8
In later chapters, well add text boxes to base and current values for skill
points (SP) and mana, which will also be disabled.
Def/Off/Misc Bonuses The entry for these stats is done in a
separate dialog that is launched by clicking the button with the ellipsis
next to the combo box. The combo boxes are used to show the data that
was entered in the dialogs. Heres the dialog thats used:

Figure 2-9
Damage Resistance/Weakness Another dialog is used to input
these:

Figure 2-10
Portrait Filename Clicking the button next to the text box displays
a standard file selection dialog. The filename that is chosen is put into
the text box.
Stats Clicking the button next to the Stats combo box displays a
form to randomly generate stats:

Figure 2-11
Any race and class modifications are passed to the form, along with any
existing stats:
Listing 2-18

private void btnStats_Click(object sender, EventArgs e)


{
Dictionary<string, int> raceStatMods = null;
Dictionary<string, int> classStatMods = null;

if (cboRace.SelectedIndex > 0)
raceStatMods = _races[cboRace.SelectedIndex
1].GetStatMods();

if (cboRace.SelectedIndex > 0)
classStatMods = _classes[cboClass.SelectedIndex
1].GetStatMods();

StatsGeneratorForm frm = new StatsGeneratorForm(_stats,


raceStatMods, classStatMods);

if (frm.ShowDialog() == DialogResult.OK)
{
_entityStats = frm.GetStats();

cboStats.Items.Clear();

for (int i = 0; i < _entityStats.Count; i++)


{
cboStats.Items.Add(((Stat)_stats[i]).Name + ": "
+
_entityStats[i].CurrentValue.ToString());
}

//get strength and constitution values


int str = 0;
int con = 0;
DieType hitDice = DieType.d6;

//default hit dice

if (cboClass.SelectedIndex > 0)
hitDice = _classes[cboClass.SelectedIndex 1].HPDice;

txtBaseHP.Text =
(GlobalFunctions.GetRandomHPDieTotal(
Convert.ToInt16(txtLevel.Text), hitDice) + ((str +
con) /

2)).ToString();

txtCurHP.Text = txtBaseHP.Text;

frm.Close();
}

Notice that you can force the random number generator to give you
values within a certain range. Youll probably want to keep the
maximum value, assuming you use the 1-100 system, but you can create
entities that have a chance of being relatively weak or strong simply by
changing the value in the Minimum Stat Amount text box. Clicking the
Generate button fills in the grid and you can see the final stat values in
the rightmost column.
As entities are added, their names are added to the combo box at the top
of the child form. Navigation from entity to entity is done using this
combo box.
Notice that you can load objects from another game using the Load
menu item on the main form or any child form. This allows you to reuse
stats, races, classes, etc., from another game.

Summary
This concludes our introduction to entities. Your game is only going to
be as interesting as the people or monsters that populate your game
world, so make sure you spend as much time as possible getting them
the way you want them.
Feel free to take a look at the sample entities that are provided in the
folder for Chapter 2 in the books downloadable files, as well be using
them in the future. Over the course of the next several chapters, well

expand the class to incorporate skills, items, and magic all the things
that make an RPG cool. Well start in the next chapter with skills, so our
entities can actually do things.

Chapter 3
Skills
A character is standing at the edge of a swift-flowing river. How is the
player going to get him across? He could swim, although it would be
risky due to the current and the weight of his armor and equipment. He
could try hopping across the stones that are lying in the river. Of course,
they may be slippery and hell risk falling and possibly injuring himself
or drowning. He could try to use the rope in his backpack to lasso a tree
stump across the river and pull himself across. If hes tied to the end of
the rope, he wont risk getting swept away.
The one common feature of these different ways for the character to try
to cross the river is that they all require him to use a skill swimming,
balancing, or rope handling. If the character cant swim well or at all,
hell drown if he tries to swim across. If hes an Olympic-caliber
swimmer, hell probably be able to swim across even if hes carrying all
of his equipment. If he can barely walk a straight line without losing his
balance, he probably wont be able to jump from rock to rock without
falling in. If he cant even tie a knot in a rope, he more than likely wont
be able to lasso a stump across the river. The better the character is at
one or more of these skills, the quicker and easier hell be able to get
across.
So how will the player know which is the best way to get the character
across? He checks the characters skill list. The skill list is built by the
player to reflect the abilities that this type of character would normally

have. A fighter would have skills with weapons such as sword, ax, and
bow, as well as armor skills, allowing him to fight in heavy armor
without difficulty. A thief would have skills in stealth, climbing,
tumbling, lock picking, and setting and detecting traps. A ranger would
have woods-based skills tracking, outdoor survival, and foraging and
animal skills such as taming, identifying footprints, etc. A mage would
probably know languages, lore related to magical items, and how to
study to learn spells easier.
Usually a characters skills get better as they are used, and they stop
increasing and possibly even decrease a little if the character doesnt use
them for an extended period of time. This is the way the games in the
Dungeon Siege series work. If the player decides during the course of
the adventure that it would be better to start using a bow instead of a
sword so enemies can be dispatched from a distance and not have his
character take damage, he can. He just has the character find or buy a
bow and start using it. He may miss a lot at first and not do much
damage when he does hit something, but after a while hell get better,
hitting his target more often for more damage and at a greater range.
Another popular method of skill advancement is to give a character a set
amount of points to buy skills after a level increase. Skills are bought in
terms of ranks a number that denotes how many times the player
has bought that skill. Each rank costs a certain number of skill points,
based on several things such as the class of the entity, stats, race, etc.
(Im using ranks here instead of levels, which you might see in some
RPGs, to avoid confusion with levels in which a character advances.)
Allowing the player buy skills means that a character could improve in
skills that he didnt even use during the adventure, depending on how
you set up your skill system. While this isnt the most realistic way of
handling skills, it is popular. Its also much easier to implement, as you

dont have to track everything the player does to determine if a skill


should go up or down. If you look at it as the character practicing a skill
during downtime between adventures, then a character learning a skill
that he doesnt already have is feasible.
One option to using a point-based system is to implement a skill tree,
requiring a character to be proficient with one skill before learning a
more complicated, related skill. A classic example of this is the Diablo
series. We can see how this works in this example of a fighters skill
tree:

Figure 3-1
Early on in the game, most of the skills are blocked. My character has
learned the Bash skill and has three ranks in it, increasing the damage he
can do with a bash attack. However, the other skills are still unavailable
as the characters level isnt high enough.
Using a skill tree means a character can only learn specific skills even
when using a point-based system. However, skill trees can be difficult to
implement and even more difficult to balance. If you create an adventure
that assumes a character will have a certain skill down one branch of the

tree and the player learns skills down another branch, the game could
become unwinnable.
Well use the point-based system without the skill tree but with some
other restrictions during the course of this book because of its ease of
implementation. But feel free to implement the usage-based method if
you feel comfortable enough in your coding skills.

The Skill Class


Well keep track of skill data with a global list of class objects:
Listing 3-1

public class Skill


{
private int _id;
private string _name;
private string _description;

private SkillType _type;

private int _opposingSkill;

private bool _alwaysOn;


private Dictionary<string, string> _costs;
private Dictionary<string, int> _classBonuses;
private List<MinMaxBonus> _levelBonuses;
private Dictionary<string, int> _raceBonuses;
private Dictionary<string, MinMaxBonus> _statBonuses;

private string _iconFilename;

[NonSerialized]
private Texture2D _icon;
}

The _name and _description members I believe are self-explanatory. A


description of the skill would be shown to the player in order for him to
determine what the skill does so hell know if its something he wants
his character to learn. Depending on the depth of your skill system, you
might implement skills with names that some players might not know,
say Spelunking.
The _id property is used as a lookup for the skills that a character knows.
Well see how that works shortly.
Well have three types of skills, shown in the SkillType enum:
Listing 3-2

public enum SkillType


{
Defensive,
NonCombat,
Offensive
}

For most RPGs, these three would probably be all you need. Im sure
you could break down noncombat skills more, but for our purposes this
is enough. The system were building is meant to be pretty generic to
allow you to use it as a base for your own systems, not as a system for
every RPG that could be developed.
Some skills will be matched up against other skills in determining the
success or failure of the action that uses the skill. For example, a thief
using his Hide skill would be opposed by the Perception skill of

anything that comes within visual range. The longer other entities are
around the hiding thief, the higher the chance that the thief will be
discovered. The _opposingSkill member will help with this. If a value
for the _opposingSkill property isnt set, we can use the opposing bonus
for the target entity (Defensive for an offensive skill and vice versa, and
Miscellaneous for noncombat skills).
The _alwaysOn member denotes a skill that the player doesnt have to
specifically select and use. The skill is always being used by the
character. The aforementioned Perception skill is a good example. The
character is assumed to be always looking around and has a chance to
notice something that hes looking for or something out of the ordinary.
In addition, you could use the Perception skill to give a character the
ability to find traps, or notice footprints or markers set by other entities
to give information to his friends (stones laid out in the shape of an
arrow to give a direction to follow, for example).
The_costs member is a list of pairs of key/value strings. The value item
tells how many skill points one rank of the skill costs. In this case, the
key is the name of an entity class, such as Fighter, which can be used to
look up information in another list. The cost for a skill can take several
forms as shown below (where <n> is a number):
<n> One rank of the skill may be bought each time the character
gains a level
<n>/* As many ranks of the skill may be bought as the player
desires (as long as the character has skill points remaining) each time the
character gains a level. Each rank costs the same amount as defined by
<n>. This allows a character to quickly gain a skill (at the cost of not
learning other skills usually). Usually skills with this type of cost are the
primary skills for an entity class melee weapons for fighters,

spellcraft for characters that use magic, or pickpocketing or lock picking


for thieves.
The _classBonuses member allows the developer to give bonuses to
entities of certain classes when using a skill. You would probably use
this for general skills like Perception rather than the primary skills for a
class since the bonuses for those skills would quickly add up and
potentially cause balancing problems. A thief or mage would probably
be better at Perception than a fighter for example, even if both had the
same ranks in the skill. You can use this member to give those classes a
bit of an edge in a skill.
The _levelBonuses member is similar to _classBonuses except it works
off the characters level. A bonus amount is specified for a level range so
you could set up a skill with a bonus of 1 for levels 1 to 5, 2 for levels 6
to 10, etc.
The _raceBonuses member works exactly like _classBonuses, and the
_statBonuses member works exactly like _levelBonuses. With all these
bonuses, theres a lot of flexibility and options for you to enhance skills.
With this flexibility, however, comes additional time that youll have to
spend balancing to make sure no skill allows the character to be
overpowered at higher levels.
Each of the five members just discussed has four accessor functions
Add<x>, Remove<x>, Get<x>, and a function to return the entire list or
dictionary. The last is needed for serialization purposes. These functions
are implemented almost exactly the same for the five members, so lets
take a look at just one, the functions for the _costs member:
Listing 3-3

public bool AddCost(string id, string cost)


{

if (_costs == null)
_costs = new Dictionary<string, string>();

if (!_costs.ContainsKey(id))
_costs.Add(id, cost);
else
return false;

return true;
}

public void RemoveCost(string id)


{
if (_costs != null)
_costs.Remove(id);
}

public string GetCost(string id)


{
string cost = "";

if (_costs != null)
_costs.TryGetValue(id, out cost);
return cost;
}

public Dictionary<string, string> Costs


{

get { return _costs; }


}

The AddCost function initializes the member if it hasnt already been


done and, if a cost for that class hasnt already been added, adds a new
Dictionary item. If a cost already exists, the function returns false;
otherwise it returns true.
The RemoveCost function and property accessor are straightforward.
GetCost is interesting only in the use of the TryGetValue method.
Instead of having to use exception handling to trap using an invalid key,
the method handles that for you. We initialize a string variable and pass
it to the method. If the key doesnt exist, we end up with an empty
string. Its up to the code that calls the function to deal with that empty
string. Since the cost could take on several forms, it has to parse the
string anyway.
The_iconFilename member will allow the skill to be accessed during the
game by specifying the name of a graphic that will be placed in the
games GUI. The player can click that graphic or press a key
corresponding to that graphics location in the GUI. When the game is
played, the _icon member will hold the loaded graphic.
The main function for the class is the Use function. Theres a lot going
on in it, so lets take a look:
Listing 3-4

public bool Use(ref Object target, ref Entity entity,


Difficulty
difficulty, out int result)
{
int roll;
int bns = 0;

roll = GlobalFunctions.GetRandomNumber(DieType.d100);

roll += (short)difficulty;

if (_opposingSkill > 0)
{
if (((Entity)target).HasSkillByID(_opposingSkill))
roll -=
((Entity)target).GetSkillValueByID(_opposingSkill);
}
else
{
switch (_type)
{
case SkillType.Defensive:
{
if (target is Entity)
roll -=
((Entity)target).GetTotalOffBonus();

break;
}
case SkillType.NonCombat:
{
if (target is Entity)
roll -=
((Entity)target).GetTotalMiscBonus();

break;
}
case SkillType.Offensive:
{
if (target is Entity)
roll -=
((Entity)target).GetTotalDefBonus();

break;
}
}
}

foreach (KeyValuePair<string,int> kvp in _raceBonuses)


{
if (entity.RaceID == kvp.Key)
{
bns += entity.Level * kvp.Value;
break;
}
}

foreach (KeyValuePair<string, int> kvp in _classBonuses)


{
if (entity.ClassID == kvp.Key)
{
bns += entity.Level * kvp.Value;
break;
}

//Calculate level bonus


if (_levelBonuses != null)
{
foreach (MinMaxBonus bonus in _levelBonuses)
{
if (bonus.IsValueInRange(entity.Level))
{
bns += bonus.Amount;
break;
}
}
}

//else
//{
//

short level = entity.Level;

//

//use default

//

switch (level)

//

//

case 1:

//

case 2:

//

case 3:

//

case 4:

//

case 5:

//

//

bns = (short)(10 * level);

//

break;

//

//

case 6:

//

case 7:

//

case 8:

//

case 9:

//

case 10:

//

//

bns = (short)(50 + (5 * (level - 5)));

//

break;

//

//

case 11:

//

case 12:

//

case 13:

//

case 14:

//

case 15:

//

//

bns = (short)(75 + (3 * (level - 10)));

//

break;

//

//

case 16:

//

case 17:

//

case 18:

//

case 19:

//

case 20:

//

//

bns = (short)(90 + (2 * (level - 15)));

//

break;

//

//

default:

//

//

bns = (short)(100 + (1 * (level - 20)));

//

break;

//
//

}
}

//}

roll += bns;

result = roll;

return (roll >= 100);

The function is passed the entity attempting to use the skill, the object
against which the skill is being used, the difficulty of the attempt, and a
reference to a variable that will hold the result of the attempt. The calling
code will use the attempt result however it wishes; all we do is calculate
the result. The difficulty of the attempt modifies the calculation by
adding the value of that difficulty from the Difficulty enum:
Listing 3-5

public enum Difficulty


{
Impossible = -50,
VeryHard = -25,
Hard = -10,
Normal = 0,
Easy = 10,

VeryEasy = 25
}

Since we are going to define a skill as having succeeded if the result of


the calculation is equal to or greater than 100, the more difficult the
attempt, the lower the number for the difficulty of that attempt. This
number is added to a random number that is generated from 1 to 100.
Next, we use the type of skill being used to get the opposite value from
the target of the attempt and subtract that value from the number rolled.
For example, for an offensive skill like an attack, we get the total value
of the _defBonuses list:
Listing 3-6

public short GetTotalDefBonus()


{
short total = 0;
Bonus bns;

if (_defBonuses != null)
{
for (short i = 0; i < _defBonuses.Count; i++)
{
bns = (Bonus)_defBonuses[i];
total += bns.Amount;
}
}

return total;
}

The Race and Entity class bonuses are calculated if they are set for the
skill. Well see how both of these are set up a bit later in the chapter, but
for now its sufficient to know that certain races and entity classes get a
small bonus (usually only 1 or 2) per level of the entity to signify the
advanced knowledge or training in that skill that a character of that race
or entity class would have. For example, an elf growing up in the woods
would normally learn tracking, moving silently, and other woodcraft
skills as part of his childhood, playing games with his friends and such.
The race bonus would allow that to be expressed in the game without
having to require a complete background of the character.
We then calculate the total of any level bonuses and add that to the
current result. If there is no level bonus specifically for that skill and you
would like to apply a generic level bonus, simply uncomment the code in
the first part of the if statement and modify it as you wish.
If the result of all these values is 100 or greater, the use of the skill
succeeds. We assign the value to the result variable and return a boolean
so the calling code knows how to apply the value in the result variable
and anything else it needs to do.
So we have a Skill class that will contain the data for the skill, but how
do we track what skills the entity has learned? This is fairly easy,
actually. Well add some new members to our Entity class, along with
functions to deal with the member that will hold these skills:
Listing 3-7

private Dictionary<int, int> _skills;

private int _curSP;


private int _baseSP;

public void AddSkill(int id, int ranks)


{
if (_skills == null)
_skills = new Dictionary<int, int>();

_skills.Add(id, ranks);
}

public void SetSkills(Dictionary<int, int> skills)


{
_skills = skills;
}

public bool HasSkill(int key)


{
if (_skills != null)
return _skills.ContainsKey(key);
else
return false;
}

The _skills member uses the _id member of the Skill class as the key,
and the value for each entry in the dictionary is the number of ranks the
character has in that skill. One modification to this setup could be to use
a structure as the Value member of the Dictionary item that contains two
integers one for the base number of ranks and one with the current
number of ranks. This would allow the number of ranks to temporarily
change, say, by magic of some type. A Potion of Battle Frenzy could
increase all the combat skills of an entity, for example. Were not going

to go to that level of intricacy in our code, but feel free to implement


something like that if you wish.
The total number of skill points for a character is calculated by dividing
each stat by 20 and adding these values together. You can adjust this
number to your liking, but it seems to give a good number of points. As
with everything in an RPG, a lot of testing will have to be done to make
sure the character has enough skills and enough ranks in those skills to
get through whatever adventure you put together.
Now that weve got some code in place to handle skills, lets take a look
at a list of skills that might be available for the player to choose from:
Melee Weapons The ability to fight and defend with a weapon.
This will be used to calculate hitting an opponent with a weapon. It
could also be used to allow a character to parry an attack, and could be
broken down into types of weapons or even specific weapons. You could
even allow a character to use a similar weapon with some or all of the
skill that he has with another weapon. For example, if a character has six
ranks of skill with a long sword, you could allow him to use a
broadsword with a percentage of the ranks he has with the long sword,
since the weapons are similar. This makes tracking the skills more
complex, but allows for a little more realism in your skill system.
Ranged Weapons The ability to use any type of bow or crossbow.
The more skill a character has in this, the better the chance of hitting a
target at a greater range. This skill could be broken down between
crossbow and regular bows since their operation is so different. For the
purposes of the game that we are creating, the two types of ranged
weapons will not be differentiated.
Armor The ability to perform actions in armor, such as fighting,
riding, climbing, etc. This will only apply to fighting in our case. A
character may fight in armor, but will do so at a penalty without Armor

skill. The heavier the armor, the more Armor skill a character will need
to offset the penalty.
Shield Use The ability to fight and block attacks with a shield. This
will add to the characters defensive ability. A character may fight with a
shield without having Shield Use skill, but will do so at a significant
penalty.
Body Development This represents a characters training to
develop his body to allow him to perform better in battle. This doesnt
represent training like weight lifting (which would increase the
characters Strength stat), but things like endurance training and the
ability to resist pain and still function. In our game, this will mean an
increase in the hit points a character has.
Unarmed Combat The ability to fight and defend without a
weapon. This skill encompasses all unarmed combat disciplines. If you
want a more realistic combat system, you could implement specific skills
for the various styles, such as karate, kung fu (I know Kung Fu!
sorry, couldnt resist), boxing, wrestling, etc. This would mean a
significant amount of testing and balancing to ensure no specific style
was over- or underpowered, however. It would also mean a lot more
work for your artist or modeler/animator to make the visuals match the
style being used.
Dodge The ability to dodge an attack, be it from either a melee or
ranged weapon. This skill will give the character a significant increase in
his defensive ability for one round of combat but will mean the character
cannot attack. It will also add a small amount during regular combat as
its assumed that even while attacking, a character will attempt to dodge,
and his Dodge skill will make him better at it than a character without
training in the skill.

Spellcraft The ability to learn and cast spells. Unlike some other
skills, a character without at least one rank in Spellcraft cannot cast
spells. The more a player invests in this skill, the less chance the spell
will fail.
Stalk The ability to follow another character without that character
noticing. This is a kind of combination Hide and Move Silently. This
requires the character to avoid the line of sight of the entity being
stalked. If the entity being stalked turned to face the direction of the
stalker he would have a chance to know hes being stalked by using his
Perception skill.
Hide The ability to avoid detection by blending into the
environment. Since a thief spends most of his time practicing this skill
where he works (cities), it may be learned by a thief for use only in a city
environment. The opposite is true for rangers, as they spend most of
their time in the woods or rural environments. You could modify this to
allow a thief or ranger to use some portion of this skill in whatever
environment they dont normally use it in, but well leave the restriction
in for our purposes.
Detect Trap The ability to notice a trap. This will give the character
a chance to notice a trap whenever he passes near it. How this skill is
displayed in your game could vary. The area around the trap might glow,
a message could be displayed, etc. For our game, well show a graphic
that the player can click on to disarm the trap. In a multiplayer game,
you could require the player to somehow inform other players of the
traps existence. If the player is playing an evil character, he might not
inform the group, leading them into it and allowing them to be weakened
or killed to allow the player to gain their loot.
Disarm Trap The ability to render a trap harmless. The character
learns how different traps work and therefore how to circumvent their

operation. Note that a trap must be detected before this skill can be used
and the character must have the proper tools to disarm the trap (for our
purpose, a universal toolset will do the job).
Move Silently The ability to move without making noise. This
includes knowing how to silence equipment that is being carried and
how to traverse terrain so that no noise is made by features of the terrain
(branches on the ground, dried leaves, creaky floorboards, etc.). This
will slow down the rate at which a character moves. This is useful for
sneaking past a guard with his back toward the character. It may be used
in conjunction with Hide to get past a guard that has line of sight of the
characters path, but will mean the character has to move at a crawl.
Pick Lock The ability to pick a nonmagically locked door, chest,
etc. This presumes that the thief has the requisite lockpicks or similar
tools available, although using the latter will incur a penalty.
First Aid The ability to stop bleeding or set broken bones, although
the specifics are not necessary to state. This will allow a character to
help another character regain a limited number of hit points.
Perception The ability to notice something. This will be used in the
game as needed to see if a character notices something out of the
ordinary traps, secret doors, etc. As with Detect Trap, how the
information is made known to the player could vary.
Many RPGs include dozens or possibly even a hundred or more skills
for a character to learn. Normally the list is automatically limited
somehow, as weve briefly touched on already, so the player isnt
overwhelmed by the total number.
Any character can attempt to learn any skill, but as well see from the
following table it will be anywhere from somewhat difficult to nearly
impossible for some characters to learn some skills depending on their
class.

Table 3-1

Lets add some race bonuses to some of the skills:


Table 3-2

Note that not all races get modifications to skills, and not all skills have
racial modifications. Next, some stat bonuses:
Table 3-3

Notice that there are bonuses as well as penalties for skills depending on
how high or low the stat is. This is only our first stab at this data. Based
on play testing, the data will more than likely need to be modified to
maintain balance.

Creating and Storing Skill Data


As usual, XML files will be used to store the data for the skills. The data
will be loaded and saved using class serialization as we did with the
Entity object in the last chapter. As with the data for classes, races, stats,
etc., these XML files will be incorporated into our sample game later on
and will be compiled by the content pipeline into binary files that the
game will use. For now, though, keeping the data in XML files will
allow us to tweak the data without needing to load it into an editor. This
will be useful during testing when the data will change to balance
everything.
To create skills, a new form is added to the toolset:

Figure 3-2
The button and menu item to access this form are only enabled if there is
class and race data available since the cost for a skill is based on the
entity class and weve established that races affect skills. Since races and
classes cant be created without the existence of stats, we dont need to
check for stats.
The form works similarly to the ones used to create the previous sets of
data. A combo box holds the skills that have been created and allows
navigation to these items if changes need to be made. The tabs holding
costs and bonuses are arranged to allow selection and entering of values
on the left and items that have been added to the current skill on the
right. For as much data as is needed for a skill, I think the interface is
fairly easy to use and allows skills to be created quickly.
Collections of the data created in each of the tabs are kept as members of
the form along with a temporary Skill object and the ID of the skill being
worked on:
Listing 3-8

private Dictionary<string, string> _costs;


private Dictionary<string, int> _classBonuses;
private List<MinMaxBonus> _levelBonuses;
private Dictionary<string, int> _raceBonuses;
private Dictionary<string, MinMaxBonus> _statBonuses;

private List<KeyValuePair<string,int>>
_opposingSkillControlSource;

private Skill _skill;

private int _curID;

This is done so that the data being stored in the controls on the form does
not have to be parsed when saving the Skill object to the list of skills.
Saving the data for the skill being worked on becomes fairly easy since
we have all the data at hand:
Listing 3-9

private void FillSkillObject()


{
_skill.Name = txtName.Text;
_skill.Type = (SkillType)cboType.SelectedIndex;
_skill.Description = txtDescription.Text;
_skill.OpposingSkill =
(int)cboOpposingSkill.SelectedValue;
_skill.AlwaysOn = chkAlwaysOn.Checked;
_skill.IconFilename = txtIcon.Text;

//add costs
foreach(string key in _costs.Keys)
_skill.AddCost(key,_costs[key]);

//add class bonuses


foreach (string key in _classBonuses.Keys)
_skill.AddClassBonus(key, _classBonuses[key]);

//add level bonuses


foreach (MinMaxBonus bns in _levelBonuses)
_skill.AddLevelBonus(bns);

//add race bonuses


foreach (string key in _raceBonuses.Keys)
_skill.AddRaceBonus(key, _raceBonuses[key]);

//add stat bonuses


foreach (string key in _statBonuses.Keys)
_skill.AddStatBonus(key, _statBonuses[key]);

private void btnAdd_Click(object sender, EventArgs e)


{

FillSkillObject();

if (_skills == null)
_skills = new List<Skill>();

_skills.Add(_skill);

cboSkills.Items.Add(_skill.Name);

_curID++;

_skill = new Skill(_curID);

SetupFormForEntry();

_saved = false;
}

Saving the list of skills looks almost exactly like saving the other
collections of data:
Listing 3-11

private void SaveSkills()


{
try
{
XmlWriter writer;

XmlWriterSettings settings = new XmlWriterSettings();

settings.Indent = true;

foreach (Skill skill in


{

_skills)

writer = XmlWriter.Create(Application.StartupPath
+
@"\Games\" + _gameName + @"\skills\" +
skill.Name +
".xml", settings);

IntermediateSerializer.Serialize(writer, skill,
null);

writer.Close();
}

_saved = true;

}
catch (Exception e)
{
MessageBox.Show(e.Message);
}
}

Loading the skills when the form is displayed is just as easy. A new
function needs to be added to the GlobalFunctions class:
Listing 3-11

public static Skill LoadSkill(string filename)


{
try
{
XmlReader reader = XmlReader.Create(new

FileStream(filename,
FileMode.Open));

Skill skill =
IntermediateSerializer.Deserialize<Skill>
(reader, null);

reader.Close();

return skill;
}
catch (Exception ex)
{
return null;
}
}

This function is then called for each skill file that exists in the skills
folder for the game:
Listing 3-12

string[] files = Directory.GetFiles(Application.StartupPath +


@"\Games\" + _gameName + @"\skills");

_skills = new List<Skill>();

foreach (string file in files)


{
Skill skill = GlobalFunctions.LoadSkill(file);

if (skill != null)
{
_skills.Add(skill);

cboSkills.Items.Add(skill.Name);

if (skill.ID > _curID)


_curID = skill.ID;
}
}

The rest of the code in the SkillsForm class is GUI navigation handling
code. The actual code to handle the data is fairly minimal, as it should
be. Working with objects helps us with keeping our code outside the
object class to a minimum.

Learning Skills
There are now skills for entities to learn, but we need a way to allow
them to learn. Two interfaces will need to be created to do this, one to
allow the developer to have NPCs, monsters, and creatures learn skills
(yes, even creatures found in the wilderness learn skills to allow them
to attack the poor, hapless player characters) and one to allow the player
to select the skills for his character during the course of the game. The
latter will be covered later on in the book once we have a game up and
running and a GUI to allow the player to select the skills for his
character. The former is fairly simple to implement; we simply add one
form and a couple of controls to the EntitiesForm we already have.
The EntitiesForm shown in Figure 3-3 has been updated to add the new
controls necessary for showing the selected skills.
The base and current number of skills points are shown above the Skills
combo box. The combo box lists the skills that have been learned and

the number of ranks for each. Clicking the button next to the combo box
displays the SkillsSelectionForm, as shown in Figure 3-4.

Figure 3-3

Figure 3-4
Simply select a skill to learn and click the >> (Add) button for each rank.
As long as the entity has enough skill points remaining to learn a rank of
the selected skill, the >> button will be enabled. Since this is a developer

tool, there might be a need to remove ranks from a skill for an entity.
Simply click the skill in the Entity Skills list box and click the <<
(Remove) button to remove ranks.
A couple of pieces of data get passed to this form in order for it to do the
necessary calculations:
Listing 3-13

private void btnSkills_Click(object sender, EventArgs e)


{
SkillsSelectionForm frm = new
SkillsSelectionForm(_skills,
_classes[cboClass.SelectedIndex - 1].Name,
_entitySkills,
Convert.ToInt16(txtCurSP.Text));

if (frm.ShowDialog() == DialogResult.OK)
{
_entitySkills = frm.SelectedSkills;
txtCurSP.Text = frm.SkillPointsLeft.ToString();

cboSkills.Items.Clear();

foreach (KeyValuePair<int, int> kvp in _entitySkills)


cboSkills.Items.Add(_skills[kvp.Key].Name + " - "
+
kvp.Value.ToString());
}
}

Since weve already loaded the skills for the current game, we simply
pass them to the form so it can show the available skills to learn. The
EntityClass value for the current entity is needed to calculate the cost for
each rank of whatever skill is selected. Any skills that the current entity
already has need to be shown, so the variable holds the collection of
current skill IDs and the number of ranks for each skill is passed.
Finally, the amount of skill points the entity currently has is needed in
order to limit what skills and the number of ranks of them the character
can learn.
If skills are selected and ranks are learned, the necessary variables and
controls are updated. When the entity is added to the entity list in the
EntitiesForm or updated if it already exists, the data in these variables
are used.

Using Skills
Okay, so we have an entity that has learned some skills. How is he going
to use them? Obviously we need to write some code to do so, but whats
the best way? If the game is to run on the Xbox 360 (and well assume
thats the case at some point down the road), note that scripting is
basically out of the question since much of the .NET Reflection
namespace we can use to execute text as code at run time is not available
in the modified compact framework that XNA GS games run under.
Also, nonmanaged code cant be run in XNA GS games, so using one of
the many scripting languages is not an option. Well need to stick with
plain C# code. The job is easily done with C#, but it means well have to
go with a less flexible solution.
Well add a SkillManager class with some stub functions that will be
filled in as we go through the upcoming chapters. The members of this
class will be used to figure out what happens when a skill use succeeds.
One function will be called and from there the specific skill will be used

to call a function specifically for that skill. The function that will be
called first looks like this at the moment:
Listing 3-14

public static void UseSkill(int key, ref Object target,


ref Entity entity, int result)
{
string name = GlobalData.Skills[key].Name;

switch (name.ToLower())
{
case "unarmed combat":
{
UseUnarmedCombat(ref target, ref entity, result);
break;
}
case "melee weapon":
{
UseMeleeWeapon(ref target, ref entity, result);
break;
}
case "ranged weapon":
{
UseRangedWeapon(ref target, ref entity, result);
break;
}
case "pick lock":
{
UsePickLock(ref target, ref entity, result);

break;
}

}
}

Well call this function from the EntityClass:


Listing 3-15

public void UseSkill(int key, Difficulty difficulty)


{
int result;
Entity entity = this;

if (GlobalData.Skills[key].Use(ref _target, ref entity,


difficulty, out result))
{
SkillManager.UseSkill(key, ref _target, ref entity,
result);
}
}

Well be keeping a static list of skills. The class that contains this list is
in the GlobalFunctions.cs file:
Listing 3-16

public class GlobalData


{
public static Dictionary<int, Skill> Skills;
}

This list will be loaded when the player is ready to start the game. The
list can contain all the skills that can be learned or just the skills that the
entities in the current level know. You would load the rest of the skills
when you need to (for example, when a character has gained a level and
wants to learn a new skill). This can be determined based on the number
of skills in your game. If you have hundreds of skills, you probably
wont want to load them all.
We pass in the result from the skill check to the SkillManager so that we
can adjust what happens if the skill use either succeeded spectacularly or
failed miserably.
We wont need functions for every skill since using some skills means
whats supposed to happen doesnt (for example, a successful Dodge
means an attack misses). Some things we can guess whats going to
happen if the skill use succeeds, so well add some commented out
placeholder code that well implement in coming chapters:
Listing 3-17

private static void UseUnarmedCombat(ref Object target,


ref Entity entity, int result)
{
int damage = 0;

//we'll adjust damage in the Combat chapter

((Entity)target).Damage(damage, DamageType.Crushing);
}

private static void UseMeleeWeapons(ref Object target,


ref Entity entity, int result)

{
//get damage from weapon entity is using
//need to figure out if weapon is piercing or slashing
//((Entity)target).Damage(damage, DamageType.);
}

private static void UseRangedWeapons(ref Object target,


ref Entity entity, int result)
{
//get damage from weapon entity is using
//((Entity)target).Damage(damage, DamageType.Piercing);
}

private static void UsePickLock(ref Object target, ref Entity


entity,
int result)
{
//((Chest).target).Locked = false;
}

You should be able to see the way were going here. Since we know
what skill is being used, we can make some assumptions in some cases
on things; like the target being passed to the UsePickLock function being
a Chest object or what should happen in the function
(UseUnarmedCombat is always going to cause crushing damage to the
target). Well also have to assume that the code calling the functions is
only going to do certain things, such as not allowing the player to attack
something thats not an entity. Since well be writing the code calling
these functions, its a pretty safe assumption. If this code were going to

be released for others to use, we might want to be a little more careful in


our assumptions.

Summary
Now that our entities have learned some skills, they need something to
use them with. In the next two chapters, well learn how to do this by
creating a magic system that allows entities to learn to cast spells and by
developing classes that allow all sorts of items to be created for entities
to use. Well then add some functionality to allow the entities to use
these spells and items on one another.

Chapter 4
Magic
Anytime you talk about a fantasy-based RPG, you will eventually get
around to talking about magic. A fantasy-based RPG wouldnt be the
same without the obligatory wizard or mage. An RPG world would
probably be pretty boring without its magic. You wouldnt have any of
the magical creatures, and some of the races wouldnt exist, such as
elves, dwarves, or halflings (depending on how you explain their
existence). All in all, it might not be much fun to run around in such a
world. Luckily for you, this chapter will give you some ideas on how to
integrate a basic magic system into your game.
There are many ways to implement a magic system. Well use a fairly
standard mana system. Mana usually exists in one of two ways
entities have an inner reserve that allows magic users to cast spells, or
the magic user is able to tap into an external source that permeates the
world. When this reserve is empty or the character exhausts himself
attempting to manipulate the external source, he must allow some time
to pass before he can cast any more spells. All characters will have some
mana, although it may be difficult for them to learn to use spells.

Some systems base a characters ability to use magic on one of its stats,
such as intelligence or wisdom. I feel this is fairly unrealistic, although
probably easier for pen and paper RPGs. An intelligent character may be
able to learn spells more easily, but I dont believe this should have any
bearing on how much mana he has. A less intelligent character may have
an innate ability to use magic, but may not be smart enough to learn any
spells. The system in this book will treat mana as another stat, although
magic-using characters will recover mana quicker. We explain this by
saying that magic-using classes have learned how magic works to some
degree and how to train their bodies to be more in tune with the magic in
the world. Classes that dont use magic may be able to cast spells, but
without this knowledge and training they wont be able to recover mana
as quickly as magic-using classes and wont learn spells as easily. This
recovery rate will be handled by the game, so all the player has to worry
about is choosing a spell for the character to cast when hes able.
First off, well look at a class that will handle every aspect of an
individual spell and a class that will manage the spells a magic-using
character has available to him (think of this class as a spell book). Well
also look at how a magic user learns his spells and how spells are used,
both in and out of combat.

The Spell Class


Listing 4-1

public class Spell


{
private int _id;
private SpellType _type;
private string _name;
private string _description;

private Difficulty _difficulty;


private string _effectAmount;
private string _range;
private string _areaEffected;
private List<string> _classesAllowed;
private string _duration;
private byte _levelRequired;
private short _manaCost;
private AlignmentFlags _alignmentsAllowed;
private SpellCastRate _castRate;
private List<Bonus> _defBonuses;
private List<Bonus> _offBonuses;
private List<Bonus> _miscBonuses;

//graphic used in the spell book in game


[NonSerialized()]
private Texture2D _spellBookGraphic;
private string _spellBookGraphicFilename;
}

The _id member is the typical identifier for doing lookups into a list of
spells from other code. The _name and _description members are also
typical. The _type member tells us the type of spell. Its an enumerated
value that can be one of the following:
Listing 4-2

public enum SpellType


{
Offensive,
Defensive,

NonCombat
}

The spell type could be broken down into various subcategories that you
see in many RPGs, but I opted for a simpler system. A full-blown RPG
would probably expand on this.
The _difficulty member could be used to specify how difficult it would
be to learn and/or cast this spell. Some RPG systems break spellcasting
down into different types, sometimes combining them. Casting a spell
could involve a verbal component, such as a word or phrase; a gesture or
series of gestures using the hands or possibly the entire body; physical
components (the old eye of newt, wing of bat kind of stuff); or
something else. Doing one of these would be difficult enough in combat.
Doing more than one would require great concentration and effort. Since
we dont really care about how the spell is cast, we can simply use a
difficulty value as a substitute.
The _effectAmount member is a string that is used to determine how
many points to apply to the target. The points can either be damaging or
beneficial, depending on the type of spell. A healing spell will restore hit
points to the target, while a fireball spell will damage as many entities as
are in its area of effect, which the _areaEffected member is used to
determine. Both members can have a format of x-y. In the case of
_effectAmount, its the range of points that affect the target. In the case
of _areaEffected, its the number of horizontal and vertical tiles that are
affected. The _effectAmount member can also be a single number that is
applied to the target after taking into account any resistances or
weaknesses.
The _range member tells the maximum range of the spell. Normally the
spell will travel this entire distance unless its blocked by something
an entity, a wall or other structure, a defensive spell, etc. If the spell is

directed at an entity and the entity dodges the attack (if possible), the
spell will continue until it reaches the _range value or its blocked. In
some cases, the caster will be able to specify where the spell goes off.
For example, a magical shield spell or one that creates a wall of ice,
stone, or fire could be set to go off directly in front of the caster or some
distance away, depending on the range of the spell.
The _classesAllowed member notes the classes that are capable of
learning and using the spell. Depending on how you want to use this, the
list can be empty to denote that all classes are allowed, or every class can
be added to the list and the length of the list compared to the number of
classes in your game. The latter case saves having to go through the
entire list every time you need to make a check.
Duration can be formatted like _effectAmount, or it can be set up as
x*level of caster. To make things easy, well assume that the actual
time value is going to be in seconds. In a larger scale game this could be
something that might last hours, which the duration member of the
bonus structure that were using is capable of handling. Since the
checking of the duration is done automatically, we just set it up and
forget it, no matter how long it lasts.
Certain spells can be very difficult to learn and may potentially have
devastating effects if used or cast improperly. The _levelRequired
member helps take care of a character attempting to learn a spell that
hes not ready for. Its declared as a byte since we wont have nearly as
many levels as a byte is capable of handling.
Certain spells are also usually usable only by certain alignments. An evil
character, for example, normally wouldnt go around tossing off
SmiteEvil spells, as that would probably be viewed as
counterproductive. The _alignmentsAllowed member handles this.
Notice that its an enum that allows multiple values to be assigned to it:

Listing 4-3

[Flags]
public enum AlignmentFlags
{
None = 0,
Good = 1,
Neutral = 2,
Evil = 4
}

Many spells will be usable by any alignment. In this case, the value
assigned to the member would be 7, which is the sum of all the
alignments.
In mana-based systems (as opposed to systems in which a caster has a
set number of spells he can cast before having to take time to memorize
his spells again), spells take energy to cast. The _manaCost member is
used to tell us exactly how tiring that will be for a character. Expect to
play with this value as you test your game to ensure that a magic-using
character cannot cast enough spells to destroy an entire dungeon without
a problem or does not run out of magic fighting a small rat and the next
rat that comes along takes him out.
If a character has a virtual ton of mana, its probably not going to help
the balance of your game if he can cast, say, a fireball every second. If
youve ever played World of Warcraft, youre probably familiar with the
cooldown period required after casting a spell. After you cast a spell
in WoW, the little toolbar icon is grayed out and slowly returns to normal
in a clockwise fashion. You can click on that icon all you want, but until
its completely back to normal nothing will happen. Well have the same
kind of thing in our game. The _castRate member will be used to tell

whether a spell is usable. It will be used with the _lastCast member of


the EntitySpell class that well look at a bit later. The values we
currently have in the enum for the member are the following:
Listing 4-4

public enum SpellCastRate


{
None = -1,

//No restrictions

Round,

//Once per round of combat

Minute,
Hour,
Day,
Week,
Month
}

Notice that we have a value specifically for combat Round. Since


theres no way to tell how long a round of combat will take, allowing a
spell to be used this way can be a little easier than having a spell become
available in the middle of a round when the character cant use it or
doesnt know when it would be available, making it more difficult to
plan what the character will do. It also provides a little more control over
a spell than just making it None. All of the values are in game time, not
real time, and dont take into account pausing the game (which should be
done automatically when the game loses focus). The latter is important
since a player could simply pause the game after casting a spell and
unpause it when the spell is ready again.
The three bonuses members should be familiar by now. The only thing
worth noting is that the bonuses apply to the target, not the caster (unless
hes the target of course).

The _spellBookGraphic member is a texture thats set using the


_spellBookGraphicFilename member. Its not stored in the entitys file,
but is loaded after the _spellBookGraphicFilename member is set.

Learning Spells
There are probably two typical but very different ways to have a
character learn a spell:
Character gains a level A fairly standard way to handle spells.
When the character gains a level, its assumed he spends time training to
merit the increases in whatever the system increases stats, skills, and
spells. This is the system well use as we touched on last chapter when
we learned about skills. When the character gains a level, hell get a
number of skill points that can be spent on learning skills and/or spells.
Magic-using characters will probably spend most of these points
learning spells.
Anywhere and anytime Given a chance to sit down and study, a
character can attempt to learn a spell whenever the player wants. If this
is allowed you usually wont be using a level-based system for learning
skills, but would instead use something more along the lines of the
Dungeon Siege series skill-based system.
With both skills and spells, there are checks to be made to determine
whether a character has learned what hes selected. Spells are a bit more
complicated than skills in this. There are several factors to take into
consideration as we saw when looking at the Spell class:
The characters class When attempting to learn a new spell you
probably will limit the players choice to only those the character is
allowed to learn (although well still do a check to verify this and the
next two factors).
The characters alignment Usually this isnt an issue with skills.

The characters level Again, usually the only way in which level
usually has any effect on skills is the bonus the character gets for how
many times it has bought that skill.
When a player has a character attempt to learn a spell, heres what
happens from a code standpoint:
Listing 4-5

public bool LearnSpell(int id, int skillPointsAllocated)


{
bool hasSpellcraftSkill = false;

foreach (int key in _skills.Keys)


{
if (GlobalData.Skills[key].Name == "Spellcraft")
{
hasSpellcraftSkill = true;
break;
}
}

if (!hasSpellcraftSkill)
return false;

EntitySpell spell = new EntitySpell();

spell.AllocatePoints(skillPointsAllocated);

_spells.Add(id, spell);

//get any bonuses for learning spells


//right now this is not used
int amount = 0;

return spell.Learn(amount);
}

An instance of the EntitySpell class is created and the points the player
allocates to learning that spell are passed as a parameter to the classs
AllocatePoints method. The instance of the class is then added to the
Entity objects _spells member, even if the character fails to learn the
spell. We do this because the skill points that are allocated to learning
the spell remain, increasing the chance that the character learns the skill
the next time he tries. Theres not much to the EntitySpell class, so lets
take a look at the whole thing:
Listing 4-6

public class EntitySpell


{
private bool _learned;
private bool _memorized;
private int _skillPointsAllocated;
private long _lastCast;
private Keys _hotKey;

public bool Learned


{
get { return _learned; }
set { _learned = value; }
}

public bool Memorized


{
get { return _memorized; }
set { _memorized = value; }
}

public int SkillPointsAllocated


{
get { return _skillPointsAllocated; }
set { _skillPointsAllocated = value; }
}

public long LastCast


{
get { return _lastCast; }
set { _lastCast = value; }
}

public Keys HotKey


{
get { return _hotKey; }
set { _hotKey = value; }
}

public void AllocatePoints(int amount)


{
_skillPointsAllocated += amount;
}

public void Memorize()


{
if (_learned)
_memorized = true;
}

public bool Learn(int bonus)


{
short roll =
GlobalFunctions.GetRandomNumber(DieType.d100);

if (roll + bonus + (_skillPointsAllocated * 5) >=


100)
{
_learned = true;
_skillPointsAllocated = 0;
}

return _learned;
}
}

Since the spells an entity has learned are stored in a dictionary with the
spell ID as the key, we dont need the ID in the class. Whenever the
entity uses the spell, well get it from the key in the dictionary entry.
To learn a spell, the entity can allocate skill points to increase the chance
of learning the spell. Each skill point currently increases the chance by
5%. This could be modified by some factors the difficulty of the spell
(remember that _difficulty member?), the amount of time the entity

spends (were not tracking time for the game created in this book), or
just about anything else you want. All the various bonuses the entity may
have are passed into the Learn function and added to the random die roll.
If the roll is 100 or greater, the character learns the spell and the _learned
and _skillPointsAllocated members are set accordingly.
Depending on your system, you might require an entity to memorize a
spell every time he wants to use it. If so, theres the _memorized
property you can use to check whether the entity has memorized the
spell before allowing him to cast it. To memorize the spell, I added a
function instead of using the property setter. This is just a personal
preference. I usually try to have actions of an entity done via a function.
The code in the function could just as easily be inside a property setter.
If you feel this makes the code cleaner, just move it and get rid of the
function.
Just about every RPG out there allows the player to create shortcuts for
doing things casting spells, attacking, etc. The _hotKey member will
allow us to do this. Usually these keys are the number keys from 1 to 0,
but they could be anything you want to allow the player to use. An
interface will also have to be created to allow this, unless you allow a
config file to be modified by the player. Of course, this wont work on
the Xbox 360 since the player doesnt have access to any files.

Using Magic
So a character has a bunch of spells memorized, but he doesnt have a
way to use them yet. There are several ways in which the player could
cast a spell, but its up to you to write the code to make these available to
him:
Hotkey Assuming youve given the player a way to assign hotkeys,
he should be able to press a particular hotkey any time the character is
capable of casting the spell. When the character is capable depends on

the spell and whether or not the player has selected a target. Some spells
could be area-of-effect, meaning they dont have a specific target. The
player simply casts the spell and the game figures out what entities are in
the affected area, which is usually a certain radius around the player or
the point selected by the player in the case of a spell that has a range.
Mouse context menu Using the right mouse button, the player
could target an enemy and bring up a context menu with the things he
can do to that enemy attack, talk, or cast spells. Neverwinter
Nights used this technique to great effect: Here the player, whose
character is the woman in the top right picture, has clicked on an NPC,
which brings up a radial menu of actions. She has selected to talk to the
NPC. If this had been an enemy, however, a different set of menu items
would have been shown and had the player been able to use magic, icons
for the different spells that could be used would be available in
submenus, shown by the arrows radiating out of some of the icons.

Figure 4-1
Mouse gestures Not widely used, this technique gives the player
more of a feeling of actually casting the spell by having him move the
mouse in a specific pattern. One of the problems with this is that the

code to capture the gesture would be fairly complex to write to ensure


that theres sufficient latitude in the accuracy expected in order to allow
the player to cast the spell even if hes slightly off with the pattern.
Spell book Although an alternative, its probably not one you
would implement. This would require the player to bring up the
characters spell book and select a spell from the book to use each time.
If you dont require the player to memorize spells, using a spell book is
more realistic than just having the player press a key or select a menu
item, but it would quickly become annoying. Think about it for a while
and see if you as a player would be happy if you had to display a
window that would probably cover most of the game world every time
you wanted to cast a spell. The original EverQuest did something like
this when the character was memorizing a spell, filling the entire
window with a graphic of the spell book, and I hated it every time I had
to do it. I mention this just to point out that more realistic is not always
better.
No matter which way you choose to implement it, casting a spell is
going to work the same for any of the above options:
The target property for the character is going to be set to the selected
enemy.
The player picks the spell to be cast and tells the character to cast it.
The character objects Cast method is called, passing the spell ID:
Listing 4-7

public bool CastSpell(int spellID)


{
if (_target != null)
{
Entity entity = this;

bool ret = false;

if (_target is Entity)
{
Entity target = (Entity)_target;
ret = GlobalData.Spells[spellID].Cast(ref target,
ref entity);
_target = target;
}
else
ret = GlobalData.Spells[spellID].Cast(ref _target,
ref entity);

return ret;
}

else
return false;

The entity finds the spell in the global spell list using the passed ID
and calls the spells Cast method, passing the _target member and itself,
in a roundabout way. Since the caster and target are passed by reference
so resolution can be performed in the Spell class, its necessary to both
create a new Entity object and set it to the player object and create a new
Entity object for the target, since it wont necessarily always be an
entity. If the target is an entity and you try to cast it as part of the call to
Cast, youll get a compile-time error.
Listing 4-8

public bool Cast(ref Entity target, ref Entity caster)


{
short mr = target.MagicResistance;
short roll =
GlobalFunctions.GetRandomNumber(DieType.d100);

if (caster.CurMana >= GlobalData.Spells[_id].ManaCost)


caster.CurMana -= GlobalData.Spells[_id].ManaCost;
else
return false;

//Get caster's skill bonus


roll += (short)caster.GetCastingSkillBonus();

//resistance not applicable for any but offensive spells


if (_type == SpellType.Offensive)
roll -= mr;

if (roll >= 100)


{
int amount = 0;

switch (_type)
{
case SpellType.Defensive:
{
//normally you would just use the _defBonuses
list

//but it can be done either way


if (_defBonuses != null)
{
foreach(Bonus bonus in _defBonuses)

((Entity)target).AddDefensiveBonus(bonus);
}
else
{
Bonus bonus = new Bonus();

bonus.Amount = Convert.ToInt16(amount);
bonus.Type = BonusType.Magic;
bonus.Duration =
Convert.ToInt32(_duration);

((Entity)target).AddDefensiveBonus(bonus);
}
break;
}
case SpellType.NonCombat:
{
if (!((Entity)target).InCombat)
{
//go through bonuses and add to target
foreach (Bonus bonus in _defBonuses)

((Entity)target).AddDefensiveBonus(bonus);

foreach (Bonus bonus in _offBonuses)

((Entity)target).AddOffensiveBonus(bonus);

foreach (Bonus bonus in _miscBonuses)


((Entity)target).AddMiscBonus(bonus);

break;
}

case SpellType.Offensive:
{
target.Damage(amount, DamageType.Magical);

break;
}
}

return true;
}

return false;
}

A random number from 1 to 100 is generated, the casters skill bonus is


added to it, any magical defensive bonus is subtracted if the spell is
offensive (if its a defensive spell it would make sense for the target to

try to resist it), and the result is checked to see if its over 100. If so, the
target either takes damage, if its an offensive spell, or has whatever
bonuses are part of the spell added to it.
Its a fairly straightforward system that should work well for most basic
RPGs. For anything else youll have to write a lot of specific code to get
the spell system to do what you want. This could include using some
kind of scripting (assuming you dont want the game to run on the Xbox
360), which would offer a great deal of flexibility at the cost of increased
development and testing. (Note that part of the reason the system is so
easy is because we want to run it on the Xbox 360, and you cant use
scripting with the Xbox.) Testing any kind of scripting system is going
to be difficult and take longer than regular testing, so be prepared to
account for this in any development schedule you might have.

The Spell Book


A magic-using character has to have some place to write down all the
spells hes learned, unless hes a cleric (its usually assumed that the
character simply prays to his god each day and it grants the ability to
cast the spells hes given), so the player is going to need a way to keep
track of what spells his character has. A spell book type of metaphor is
usually used for this. Typically, theyll look similar to the spell book
interface from World of Warcraft.

Figure 4-2
Usually the spells a player uses the most are going to be associated with
hotkeys or toolbar icons in the games interface, but at higher levels a
character may have dozens of spells and theres no way to keep them all
available. A character may have spells that are only useful in certain
circumstances and will swap out spells depending on the situation.
In order to allow the player to quickly and easily find the spells hes
looking for, some sort of organization is handy. For our purpose,
organizing the spells by type comes to mind immediately. Obviously
were not going to have World of Warcraft level art here, but it will be
functional:

Figure 4-3
The spell book will have six spells per page. The name of the spell will
be displayed next to the icon. Clicking on a tab to the left will change the
spells displayed to those for that type. Clicking on the triangles at the
bottom will turn the pages, with the page number displayed at the top.
As spells are learned, theyll show up in the next available spot for the
type of spell. The player will probably want to be able to move spells, so
well have to provide this functionality. This means well need to know
what spell is on what page. Luckily the ID of the spell will enable us to
keep track. Our spell book is pretty simple because of this:
Listing 4-9

public class Spellbook


{
private List<SpellBookPage> _offSpells;
private List<SpellBookPage> _defSpells;
private List<SpellBookPage> _miscSpells;

public const int SpellsPerPage = 6;


}

If, for some reason, we ever had another spell type, wed have to change
the class, but that would be simple enough to do. If you decide to change
the number of spells per page, at least you only have one place to change
it, the SpellsPerPage constant.
Adding a spell to the book is fairly simple:
Listing 4-10

public void AddSpell(int id, SpellType type)


{
bool ret = false;

switch (type)
{
case SpellType.Offensive:
{
if (_offSpells == null)
_offSpells = new List<SpellBookPage>();

foreach (SpellBookPage page in _offSpells)


{
if ((ret = page.AddSpell(id)) == true)
break;
}

//all the current pages are full so start a new


one
if (!ret)

{
SpellBookPage page = new SpellBookPage();
page.AddSpel l(id);
_offSpells.Add(page);
}

break;
}
case SpellType.Defensive:
{
if (_defSpells == null)
_defSpells = new List<SpellBookPage>();

foreach (SpellBookPage page in _defSpells)


{
if ((ret = page.AddSpell(id)) == true)
break;
}

//all the current pages are full so start a new


one
if (!ret)
{
SpellBookPage page = new SpellBookPage();
page.AddSpell(id);
_defSpells.Add(page);
}

break;

}
case SpellType.NonCombat:
{
if (_miscSpells == null)
_miscSpells = new List<SpellBookPage>();

foreach (SpellBookPage page in _miscSpells)


{
if ((ret = page.AddSpell(id)) == true)
break;
}

//all the current pages are full so start a new


one
if (!ret)
{
SpellBookPage page = new SpellBookPage();
page.AddSpell(id);
_miscSpells.Add(page);
}

break;
}
}
}

If there are no spells of that type in the spell book yet, the member
holding those spells will be null, so well have to create it. We then go
through each page of that member, checking for an open spot by trying
to add the spell to that page. If the AddSpell function returns false for

every page, we know that all the pages are full, so we create a new one,
add the spell to it, then add that page to the member holding the pages of
that type.
Of course we need to allow the player to move a spell from one page to
another:
Listing 4-11

public bool MoveSpell(int id, SpellType type,


int fromPage, int toPage)
{
bool ret = false;

switch (type)
{
case SpellType.Defensive:
{
//check to see if page exists
if (!(_defSpells.Count -1 < fromPage))
break;

//check to see if spell is actually on the


fromPage
if (_defSpells[fromPage].HasSpell(id))
{
//return value tells us if toPage has room
//if not, it's up to the calling code to
handle
ret = _defSpells[toPage].AddSpell(id);
if (ret)

_defSpells[fromPage].RemoveSpell(id);
}

break;
}
case SpellType.NonCombat:
{
//check to see if page exists
if (!(_miscSpells.Count-1<fromPage))
break;

//check to see if spell is actually on the


fromPage
if (_miscSpells[fromPage].HasSpell(id))
{
//return value tells us if toPage has room
//if not, it's up to the calling code to
handle
ret = _miscSpells[toPage].AddSpell(id);
if (ret)
_ miscSpells[fromPage].RemoveSpell(id);
}

break;
}
case SpellType.Offensive:
{
//check to see if page exists
if (!(_offSpells.Count-1<fromPage))

break;

//check to see if spell is actually on the


fromPage
if (_offSpells[fromPage].HasSpell(id))
{
//return value tells us if toPage has room
//if not, it's up to the calling code to
handle
ret = _offSpells[toPage].AddSpell(id);
if (ret)
_ offSpells[fromPage].RemoveSpell(id);
}

break;
}
}

return ret;
}

Several checks have to be made to ensure the function doesnt throw an


exception by assuming the parameters passed to it are valid when theyre
not. You need to check that the page from which the spell is being
moved exists, the page to which the spell is being moved exists and has
room, and the spell exists in the page from which its being moved. If all
these conditions are true, the spell is moved and the function returns
true. If any of them are not valid, the function returns false and its up to
the code calling the function to handle it in whatever way it wants.
Normally the interface wouldnt allow any of the parameters to be false

so the function should always succeed, but its good practice to never
assume anything.
The SpellBookPage class is just about as simple:
Listing 4-12

public class SpellBookPage


{
private int[] _spellIDs;

public int[] SpellIDs


{
get { return _spellIDs; }
set { _spellIDs = value; }
}

public SpellBookPage()
{
_spellIDs = new int[Spellbook.SpellsPerPage];
}

public bool AddSpell(int id)


{
bool ret = false;

for (int i = 0;i < Spellbook.SpellsPerPage; i++)


{
if (_spellIDs[i] == 0)
{
_spellIDs[i] = id;

ret = true;
break;
}
}

return ret;
}

public bool RemoveSpell(int id)


{
bool ret = false;

for(int i = 0; i < Spellbook.SpellsPerPage; i++)


{
if (_spellIDs[i] == id)
{
_spellIDs[i] = 0;
ret = true;
break;
}
}

return ret;
}

public bool HasSpell(int id)


{
bool ret = false;

for(int i = 0; i < Spellbook.SpellsPerPage; i++)


{
if (_spellIDs[i] == id)
{
ret = true;
break;
}
}

return ret;
}
}

When the page is created, the array containing the spell IDs is created to
be the size of the SpellsPerPage constant. If you want to increase the
number of spells per page, changing the constant means you wont have
to change any other code as everything is based on the constant.
The three functions in the class all work similarly they take a spell ID
as a parameter and iterate through the array to determine if what the
function is supposed to do can be done. In the case of the RemoveSpell
and HasSpell functions, the function returns true if the spell exists in the
array. In the case of the AddSpell function, it returns true if the page is
not full.

Summary
A character can now do just about whatever he wants and can defend
himself either unarmed or with spells. He would look kind of silly just
running around naked though. Well take care of that in the next chapter.
Well add the capability of having all kinds of items in the world for the
player to find and equip his character with. Those items will also have
the ability to be magical since we now have spells that items can use.

Chapter 5
Items and Loot
Whats the first thing you see when you picture a fighter in your mind?
Do you see armor, a sword and shield, or maybe the fighter shooting an
arrow from a bow? Perhaps you imagine him on horseback, charging
with a lance. Regardless of the picture you have, more than likely the
first thing you noticed wasnt the person, but his equipment. That makes
sense, since a fighter without his gear is almost useless in an RPG
(unless hes a martial artist, but thats another chapter).
Most RPGs these days have so many different items in them that a
player cant move 20 feet without stumbling over a crate thats filled
with something, even if its mostly useless junk that he just sells for a
few coins so that he can buy whatever it is he really needs. Then theres
the MMORPG type of item distribution system where rats will drop full
pieces of plate armor. While that may not be the best way to go, youll
want to get items to players in some way. I think it does make sense for
NPCs and creatures to have items that the player can pick up after
theyre defeated, but it should be items that they would really have on
them; the armor and weapons that they used against the player, money
and other trinkets that they may be carrying around, etc.
Many gamers play RPGs because they like to collect all the highpowered gear. If your RPG doesnt have some cool stuff in it, youll lose
a good number of players. And lets face it all of that cool stuff is just
fun to play with! Fortunately its not that hard to get items into your
game.
In this chapter well implement classes that will be used to handle all
types of items armor, weapons, and miscellaneous things like scrolls,
rings, and potions. Well also develop an Inventory class to manage all
of the stuff a character will end up lugging around.

The BaseItem Class


Lets start with our base class for all items, aptly named BaseItem:
Listing 5-1
abstract public class BaseItem : Object
{
protected int _id;

protected string _name;


protected string _description;
protected float _weight;
//Used for different purposes depending on the type of
derived item
protected string _tag;

protected Texture2D _picture;

//used in

inventory/vendor dialogs

The first thing to notice is that the class is declared as abstract, meaning
instances of the class cannot be created. A class has to inherit from it and
instances of that inherited class created. Well do quite a bit of that
shortly, so dont worry. The second thing to notice is that the members
are declared as protected, rather than private, which we have to do if we
want the derived classes to be able to use them.
The _id member will be our link to the item from outside code. Since we
could potentially have items with somewhat longish and interesting
names like Flaming Platinum Sword of Vengeance vs. Trolls, we cant
really use the _name member as we do with other classes.

Speaking of the name, there are several ways to handle our flaming
sword example. Many RPGs use one or more adjectives in the name of
the weapon, but that doesnt mean you have to store those adjectives in
the name. You could create sets of metadata that you attach to various
items. Some metadata might not make sense for some items, so you
could restrict certain words from being used with those items. For
example, you might not want to allow a Flaming Platinum Potion of
Vengeance vs. Trolls to be created. If you did, I dont think I would
want my character to drink it.
Metadata: Simply put, this is a fancy word that means data about data.
An entity can only lift or carry so much weight, so our items have to
have a _weight member. A player would not be allowed to add items to a
characters inventory if the combined weight of all the items in the
inventory is over the max the character can handle. Well see this later in
the chapter when we create the Inventory class. There well also see how
the _picture member is used.
The _tag member will be used in various ways. For example, its a nice
way to allow a bit more flexibility in how items are handled and used.
Only one item will be derived directly from BaseItem the Money
class:
Listing 5-2
public class Money : BaseItem
{
public const int CoinsPerPound = 10;

private int _amount;

//Overrides since the strength required changes as the

amount changes
new public byte StrengthRequired
{
get { return (byte)((_amount / CoinsPerPound) /
Stat.PoundsPerStatPoint); }
}

public static byte GetStrengthRequired(int amount)


{
return (byte)((amount / CoinsPerPound) /
Stat.PoundsPerStatPoint);
}

public int Total()


{
return _amount;
}

public Money()
{

public static int GetWeight(int amount)


{
return (int)(amount / CoinsPerPound);
}

public int TotalWeight

{
get { return GetWeight(_amount); }
}

//Called for things like buying items


public void Subtract(int amount)
{
if (amount <= _amount)
_amount -= amount;
}

//Parameter is declared as ref


//so we can modify it to let the calling code know
//that we couldn't hold the full amount.
//This should never happen, however,
//as the weight alone should limit what an entity can
carry
public void Add(ref int amount)
{
if (amount + _amount <= int.MaxValue)
{
_amount += amount;
}
else
{
amount = (int)(int.MaxValue - _amount);
_amount = int.MaxValue;
}
}

//Called for things like dropping on the ground, etc.


//Added simply for making sense in the context for which
it's used
public void Drop(int amount)
{
Subtract(amount);
}

public void Give(ref int amount, ref Entity target)


{
if (amount <= _amount)
{
target.AddMoney(ref amount);

}
}
}

We can see that, in the game world, 10 coins would weigh one pound.
This will be useful later on when we implement our inventory. Some
RPGs may allow the character to carry around millions of coins as well
as dozens of weapons, armor, and other items, but if you want to model a
realistic inventory, the CoinsPerPound member will help ensure that
characters cant carry around enough money to buy out a shopkeepers
entire inventory. Well add the capability to ignore weight into the
inventory, however, so that characters can carry around thousands of
pounds of gear if you wish to allow it.
If a developer needs to know how much strength is required to handle all
of the money a character is currently carrying or any amount of coins,

the StrengthRequired functions will tell him. There are also functions to
get the weight of the money a character is carrying or a certain amount
of coins.
The remaining four functions allow money to be given or taken away
from an entity in different situations, such as trading with or giving
money to another entity, buying or selling items, or just dropping it on
the ground.

The Item Class


All remaining types of items will be derived from the Item class:
Listing 5-3
public abstract class Item : BaseItem
{
protected ItemType _type;

protected int _cost;


protected bool _magical;
protected AlignmentBitwise _alignments;

protected bool _questItem;


protected byte _questItemPiece;
protected int _questID;
protected bool _questReward;

protected bool _droppable;


protected bool _tradeable;

protected int _baseHP;

protected List<Spell> _spells;

protected List<Bonus> _defBonuses;


protected List<Bonus> _offBonuses;
protected List<Bonus> _miscBonuses;

//Is item automatically put in character's hand when


picked up
protected bool _autoReady;

protected bool _repairable;

protected bool _unique;

//ID of the skill required to use this


protected int _skillRequired;

//All classes that derive from this one must implement


this function
public abstract bool Use(ref Object target, ref Entity
wielder);
}

The types of items well be dealing with are the following:


Listing 5-4
public enum ItemType
{
Armor,
Chest,

Key,
Potion,
Scroll,
Shield,
Weapon,
Money

//Placed out of order since we don't create

money
//in the editor
}

Of course, youll probably want to add more items for your game. The
nice thing is that you just have to add the item to this enum and youll be
able to create specific items of this type in the editor, as well see later
on in the chapter.
The _cost member is the amount in gold pieces needed to buy the item
from an NPC. The gold piece will be the standard unit of money. Many
RPGs go this route, as its easy to manage. Other RPGs and MMORPGs
use several denominations of coins. Balancing costs is much more
difficult when doing this, but gives greater flexibility.
The _magical member is set to true if an item possesses magical
qualities. This is only for items that are not normally magical, such as
weapons or armor. Scrolls, potions, and the like are already assumed to
be magical. The member will be ignored for items like these, although it
might be nice to explicitly set it to true. If the item is magical, the _spells
member is used to hold the magical properties of the item.
In some RPGs, the use of certain items is limited to specific races or
alignments. The _alignments member allows us to do this. The enum for
this member looks like this:
Listing 5-5

[Flags]
public enum AlignmentBitwise
{
None = 0,
Good = 1,
Neutral = 2,
Evil = 4
}

The next four members are used for a specific type of item one that is
the target or reward of a quest. Think King Arthurs quest to find
Excalibur to understand what these are used for. _questItem tells us if
the item is the target of a quest, _questItemPiece specifies the piece of
the quest item (say, Excalibur has been broken into pieces and has to be
found and reassembled), _questID is the ID of the quest the item belongs
to, and _questReward indicates whether the item is a reward that is given
to a character for completing a quest.
The next two members are used more often in MMORPGs than in
normal RPGs, but you might want to use the functionality in a nonMMORPG, especially if you implement multiplayer support. Rewards
from quests in MMORPGs are normally not tradeable between
characters and cannot be dropped on the ground for another character to
pick up. Once the player picks up or accepts a quest reward item, he can
use it, keep it in his inventory, or destroy it. The _droppable and
_tradeable members help implement this type of functionality.
Another feature of some RPGs is to make items wear out over time or be
able to be damaged or destroyed. In order to do the latter, we need to
know how much damage an item can take. The _baseHP member will
handle this. You may want to go even further and implement

functionality that makes the item less useful the more it gets damaged,
simulating an effect such as a sword losing its sharpness the more its
used in combat. If you do so, the _repairable member can be used to tell
whether the item can be restored to full effectiveness.
The _autoReady member will place the item either in the characters
hand if its a weapon or shield or at the proper location on the characters
body if its a piece of armor or jewelry and not just an item that exists in
that location.
The _unique member simply lets the player know if the item is the only
one of its kind in the world with those exact properties. In almost every
case, this items _droppable and _tradeable members will also be set to
false. Once the player picks up the item, he can keep it in his inventory,
put it in a private storage area (MMORPGs usually give players places
in a bank or something similar that no other player can access), or
destroy it.
The _skillRequired member should be fairly self-explanatory. There may
be cases where the player isnt quite sure whether a long sword can be
wielded one-handed, so he wouldnt know whether to train in one- or
two-handed sword skill (assuming you broke down skills that far). This
member helps alleviate any worry about that.
The Use function will be implemented in the classes that inherit from the
Item class, so well look at how each handles implementing it when we
look at those classes. For weapons, theyll be very similar, but other
types of items will differ a bit.

The Weapon Class


Lets start with weapons then. This class will look very simple, and it
should. Most of the work has been done for us in the Item class, as it
should be.
Listing 5-6

public class Weapon : Item


{
private WeaponType _weaponType;
//array of Damager objects
private List<Damager> _damagers;

public WeaponType Type


{
get { return _weaponType; }
set { _weaponType = value; }
}

public List<Damager> Damagers


{
get { return _damagers; }
set { _damagers = value; }
}

public void AddDamager(Damager item)


{
if (_damagers == null)
_damagers = new List<Damager>();

_damagers.Add(item);
}

public void AddDamager(DamageType type, DieType amount,


String affects)

{
Damager item = new Damager();

item.Affects = affects;
item.DamageAmount = amount;
item.Type = type;

if (_damagers == null)
_damagers = new List<Damager>();

_damagers.Add(item);
}

protected int GetDamage(byte damageType)


{
int damage = 0;

for(int i = 0; i < _damagers.Count; i++)


{
if (_damagers[i].Type == (DamageType)damageType)
{
damage = GlobalFunctions.GetRandomNumber(
_damagers[i].DamageAmount);
break;
}
}

return damage;
}

public override bool Use(ref Object target, ref Entity


wielder)
{

//not used as attacking with a weapon is handled


//by the combat manager

return true;
}

The members of the WeaponType enum will be simple and can easily be
expanded upon:
Listing 5-7
public enum WeaponType
{
OneHandSword,
TwoHandSword,
Dagger,
Staff,
Mace,
Bow,
Crossbow
}

There is at least one type of weapon for each entity. Both Bow and
Crossbow are included so the differences in speed and damage can be
tested and chosen between.

The _damagers collection is used to determine what type of damage the


weapon inflicts. Its a simple structure:
Listing 5-8
[Serializable]
public struct Damager
{
public DamageType Type;
//Format = "d<x> or <x>"
public string DamageAmount;
//The type of entity the damage affects, empty for all
types
public string Affects;
}

The current types of damage are as follows:


Listing 5-9
public enum DamageType
{
Crushing,
Piercing,
Slashing,
Fire,
Water,
Magical,
Disease,
Poison
}

Weapons will normally only use the first three values, but if the weapon
is magical, any of them may be added to the normal type of damage. The
Flaming Platinum Sword of Vengeance vs. Trolls we talked about
previously could deal both Piercing and Slashing damage (depending on
the type of attack used if you allow some swords to have more than one
attack type) as well as Fire damage.
The DamageAmount member can have one of two formats d<x> to
specify one of the DieType values, meaning the weapon does a random
amount of damage from 1 to some number, or <x>, meaning the weapon
does a set amount of damage if an attack with it succeeds.
The Affects member is a type of entity for our purposes (although you
could have a weapon that does special damage to inanimate objects, such
as Stonecutter from Fred Saberhagens Lost Swords series). Our
example sword would have this member set to Troll and deal the
damage specified by DamageAmount in addition to the regular damage
the weapon does.

The Armor Class


Listing 5-10
public class Armor : Item
{
private ArmorArea _location;
private short _defValue;
private bool _equipped;

public ArmorArea Location


{
get { return _location; }
set { _location = value; }

public short DefensiveValue


{
get { return _defValue; }
set { _defValue = value; }
}

public bool Equipped


{
get { return _equipped; }
}

public override bool Use(ref Object target, ref Entity


wielder)
{
//Use for this class means to equip,
//so set member if it's being equipped
short loc = (short)target;

if (loc > -1)


{
//the value tells us where it's trying to be
equipped
//so check it
//for instance, a piece is dragged onto the wrong
location
//in the character screen
if (loc != (short)_location)

_equipped = true;

}
else
_equipped = false;

return equipped;
}
}

Each piece of armor has only one location on the body where it can be
worn. The ArmorArea enum gives us the possible locations:
Listing 5-11
public enum ArmorArea
{
None=-1,
Head,
Neck,
Chest,
LeftUpperArm,
UpperArms,
LeftLowerArm,
LowerArms,
LeftWrist,
Wrists,
LeftHand,
//Could add fingers here for rings
Hands,
RightUpperArm,

RightLowerArm,
RightWrist,
RightHand,
//Could add fingers here for rings
Waist,
Groin,
LeftUpperLeg,
UpperLegs,
LeftKnee,
Knees,
LeftLowerLeg,
LowerLegs,
LeftFoot,
Feet,
RightUpperLeg,
RightKnee,
RightLowerLeg,
RightFoot,
LeftHandEquipped,

//used for the item held in the

left hand
RightHandEquipped

//used for the item held in the

right hand
}

Note that the LeftHandEquipped and RightHandEquipped values are not


for armor but for items that are being held in the indicated hand, which is
why weve put them at the end of the list.
The _defValue member indicates how much damage the piece absorbs
from a blow, subtracting the amount of damage the entity receives. This

value could decrease as the piece is damaged, perhaps by a percentage of


the remaining hit points the piece has.
The _equipped member tells us if the piece of armor is being worn by
the entity. Since the object will still be stored in the entitys inventory,
this member is needed to show what the entity is wearing. When a piece
of armor is put on, the object could be moved to another member of the
Entity object and the member done away with. Either way, to determine
if an area of the entity is covered, well still have to look at a member of
the entity class, so its just easier to me to leave it in the inventory.

The Chest Class


What would an RPG be without some chests in which to find loot?
Technically, you could use this class for just about any object that can
contain items (barrel, furniture, etc.), especially if its the type of object
that can be locked.
The class isnt very complex and could be made even simpler if you
dont need to randomly generate the items it contains or want to be able
to set a trap. (Where would the fun be in that, though; after all, thieves
need something to do to make them feel important.)
Listing 5-12
public class Chest : Item
{
private bool _locked;

//tag or name property of the key item required to open


the lock,
//set to "key" if a generic key item will open the lock
private string _keyRequired;

private bool _open;

private bool _randomlyGenerate;


private ItemType _randomType;
private int _maxValue;

private bool _trapped;


private TrapType _trapType;
private Spell _trapSpell;
private Difficulty _trapLevel;
private int _damage;

private List<Item> _items;

public bool IsOpen


{
get { return _open; }
set
{
_open = value;
if (_open)
_locked = false;
}
}

public override bool Use(ref object target, ref Entity


wielder)
{
//if the chest is already open return

if (_open)
return true;

//target in this case is null, since the chest is the


target
//wielder is the entity trying to open the chest
//call PickLock if the chest is locked
if (_locked)
{
if (!wielder.HasItemByTagOrName(_keyRequired))
return false;

_open = true;
}

return true;
}

public bool PickLock(ref Entity entity)


{
bool ret = true;

//function should never be called for an unlocked


chest
//but just in case...
if (_locked)
{
int ID = GlobalFunctions.GetIDForSkillName("Pick
Lock");

if (ID > 0)
{
if (entity.HasSkillByID(ID))
{
Object chest = (Object)this;

ret = entity.UseSkill(ref chest, ID,


_trapLevel);
}
}
}

return ret;
}

public List<Item> GetItems()


{
if (_randomlyGenerate)
{
int value = 0;
Item item = null;

do
{
//get a random item type

//get a random item of that type

//add the value of that item to the value of


the items
//in the list
value += item.Cost;

}
while (value < _maxValue);

return _items;
}
else
{
if (!(_items == null))
return _items;
else
throw (new Exception("Invalid items list"));
}
}
}

There are a couple of boolean values that indicate whether the chest is
open, locked, or trapped. If its locked, the _keyRequired member tells
what key will open up the chest. You can use either the _name or _tag
property of the key to determine what key is needed.
If there is a trap around the chest, there are a couple of members to look
at. The _trapType can be one of the following:
Listing 5-13
public enum TrapType

{
None,
Missile,

//normal missile-type

Gas,
Magic,

//spell is cast

Explosion
}

If the trap is a Magic trap, the _trapSpell member will hold the spell to
be cast if the trap is tripped. The _trapLevel member is used against the
level of the Disarm Trap skill of the person attempting to disarm the
trap. The _damage member is used if the trap is set off and it is not a
Magic trap.
The items in the chest are contained in the _items member. This member
is set either at design time or, if the _randomlyGenerate member is set to
true, when the chest is opened and inspected. The _randomType member
is the type of item to pick from. For our purposes it can be one of the
following:
Listing 5-14
public enum ItemType
{
Armor,
Chest,
Key,
Potion,
Scroll,
Shield,
Weapon,
Money

//Placed out of order since we don't create

money
//in the editor
}

Obviously, the Chest item in the enum wont be used unless the Chest
class is being used as some other kind of item. That would be up to the
level designer to determine.
The _maxValue member is used to limit the value of the items in the
chest if the contents are being randomly generated. The actual code to do
this will be filled in later once weve determined how well access items
in-game.
The Item classs Use method here is overridden to mean open the
chest. If the chest is already open, the function simply returns true. If
the chest is locked, the entity is checked to see if he has the key using the
HasItemByTagOrName function:
Listing 5-15
public bool HasItemByTagOrName(string tag)
{
foreach (Item item in _inventory.Items)
{
if (item.Name == tag || item.Tag == tag)
return true;
}

return false;
}

If the chest is locked and the entity does not have the key, the lock has to
be picked, which means the entity has to have the Pick Lock skill:
Listing 5-16

public bool PickLock(ref Entity entity)


{
bool ret = false;

//function should never be called for an unlocked chest


//but just in case...
if (_locked)
{
int ID = GlobalFunctions.GetIDForSkillName("Pick
Lock");

if (ID > 0)
{
if (entity.HasSkillByID(ID))
{
Object chest = (Object)this;

ret = entity.UseSkill(ref chest, ID,


_trapLevel);
}
}
}

return ret;
}

The EntityItem Class


Since an entity could conceivably be carrying several of an item and
there could be many entities in a level carrying the same item, we

obviously dont want to create instances of an item every time. The only
pieces of data we need are the ID and the current hit points for the item.
So we create a simple class that well store in the entitys inventory:
Listing 5-17
public class EntityItem : Item
{
private int _id;
private int _curHP;

public EntityItem(int id, int curHP)


{
_id = id;
_curHP = curHP;
}

public int ID
{
get { return _id; }
set{}
}

public int CurHP


{
get { return _curHP; }
set { if (value >= 0) _curHP = value; }
}

public bool Useable()

{
return (_curHP > 0);
}

public void Damage(int amount)


{
_curHP -= amount;

if (_curHP < 0)
_curHP = 0;
}

public void Repair(int amount)


{
_curHP += amount;

if (_curHP > GlobalData.Items[_id].BaseHP)


_curHP = GlobalData.Items[_id].BaseHP;
}

//repair to a percentage of the BaseHP


public void Repair(float percentage)
{
_curHP = (int)(GlobalData.Items[_id].BaseHP *
percentage);
}
}

If an items hit points drops to 0, the item is not usable until its repaired.
Alternatively, you could have the item be destroyed when its hit points

reaches 0 and remove it from the inventory. Additionally, the item could
be usable at a reduced effectiveness, perhaps expressed as a percentage
of _curHP to _baseHP. Many RPGs show the current state of the item in
the games GUI so the player knows when an item has to be repaired,
often turning that indicator from green to yellow to red to show the
items decreased state of repair.
Before allowing an item to be used, the Useable function should be
called. If the item is not usable, you could display a message to the
player and perhaps even move the item from being held to being stored
in the players inventory.

The Inventory Class


The player will need a way to keep track of all the loot he has, as well as
what pieces of equipment hes wearing or using. Most games use
separate GUI pieces for the two. Well include both pieces of data in one
class to try to make it a bit easier to manage, both from a code standpoint
and a GUI standpoint (as well see later on in Chapter 9).
Many games make inventory management almost a subgame, with items
having to be shuffled around in the inventory to make room for other
items that are picked up. Even if the character actually has room in his
inventory if things were shuffled around, some games will not allow you
to pick up an item or will drop the item on the ground instead of
rearranging the inventory for you. If the player isnt paying attention and
assumes the item is in his inventory when this happens, it could mean
the item may be lost forever when the player moves to a different area or
level. This makes absolutely no sense to me. Whether its a lack of
desire to code a decent inventory dialog that can automatically rearrange
items to make room as other items are picked up or something else, one
of the things I hate most about many RPGs is inventory management.
There are many ways to make it easy for the player to find and use items

in his inventory. Rather than force you to accept what I think is the best
solution, however, a generic class will be implemented that can easily be
inherited from and made to function as you think best.
Listing 5-18
public class Inventory
{
//can't use a Dictionary here because the inventory
//could contain multiples of the same item, therefore the
same id
private List<EntityItem> _items;
private Dictionary<int, int> _equippedItems; //Key is an
ArmorArea

public List<EntityItem> Items


{
get { return _items; }
set { _items = value; }
}

public float TotalWeight()


{
float weight = 0.0f;

foreach (Item item in _items)


weight += item.Weight;

return weight;
}

public void Add(EntityItem item)


{
//check to see if entity is overweight
//needs to be done in the Entity class
_items.Add(item);
}

public EntityItem Get(int id)


{
foreach (EntityItem item in _items)
if (item.ID == id)
return item;

return null;
}

public void Remove(int id)


{
//if the item is equipped remove it from the _equipped
list
if (_equippedItems.ContainsValue(id))
{
foreach (KeyValuePair<int, int> item in
_equippedItems)
{
if (item.Value == id)
{
_equippedItems.Remove(item.Key);

break;
}
}
}

_items.Remove(_items[id]);
}

public Texture2D GetArmorAreaPicture(ArmorArea area)


{
foreach (Item item in _items)
if (item.ID == _equippedItems[(int)area])
return item.Picture;

return null;
}
}

As is noted in the code comment, a List<EntityItem> object is being


used rather than a Dictionary<int, EntityItem> since a character can
carry more than one of a particular item. Using a dictionary in this case
would throw an exception when attempting to add an item that already
exists to the dictionary. One way around this would be to include a
_count member in the EntityItem class to show how many of that item
are being carried. This is certainly a viable alternative. The graphic used
to display the item in the inventory window could also have the number
drawn on top of it with the value of the _count member. If such a setup
is more to your liking, it wouldnt take long to make the necessary
changes.

The _equippedItems collection is where well use the LeftHandEquipped


and RightHandEquipped values of the ArmorArea enum. Sure, the items
being held by the character could have been tracked some other way, but
setting it up this way was quick and easy. It means two less members of
the inventory to have to deal with at the slight expense of having the
ArmorArea enum be less than accurate. Sometimes trade-offs like this
are used, and its not necessarily a wrong thing in my opinion.
When we get to Chapter 9, well create an interface that is used to
display the items in the inventory, both equipped and not, and allow the
player to move things from the inventory to a location on the characters
body. Since the Inventory class is fairly non-implementation-specific,
there could be a number of ways to create the interface.

Summary
A character can now be created to have everything he needs to survive in
the game world. Thats good because in the next chapter were going to
allow the character to be tested by implementing a combat system.

Chapter 6
Combat (or It s Clobberin Time)
Taran looked at the oncoming horde of goblins and sighed. This was the
third time theyd tried to ambush his group as they traveled through the
Darian Forest. You would have thought that they could have come up
with a better plan of attack than just rushing them from the front, even as
stupid as goblins were reputed to be. Oh well, at least theyre saving
me the time to have to come up with a strategy, he thought. He and
Karil drew back on their longbows as Farthon started chanting a spell.
Tomlin was trying to slide off to the side to get behind the group once
they closed, as he always did. Taran had never seen the halfling thief

attack an opponent head-on since hed known him. Soral was off to the
other side, lightly swinging his mace while reciting a prayer to his god.
Taran never could remember the gods name, but he always seemed to
respond to Sorals prayers, granting the group some extraordinary
power during battle. The clerics healing powers had barely been
necessary the last two times the group had encountered the bands of
creatures.
As the goblins came within range, Taran and Karil let loose with their
arrows and each quickly grabbed another arrow from his quiver to get
in another shot before the band closed to melee distance. Farthon
finished his spell at about the same time and a fireball soared over
Tarans head to explode in the midst of the group of goblins, leaving
little more than a stinking mass of burned flesh. An eerie glow
surrounded the small group of adventurers as Sorals god again granted
his blessing to the group. Two more goblins dropped from arrows as
they closed to within sword range. Taran and Karil barely had time to
pull their swords from their scabbards as the screaming goblins fell
upon them.
The fight was short and bloody, at least for the goblins. The fighters
swords chopped appendages from goblin bodies. The thief, Tomlin,
managed to fell a couple of goblins with well-placed attacks from the
rear. Sorals mace whirled around him, crushing any goblin that
happened to get close enough. Even the mage, Farthon, got into the
action, sticking his long dagger into the chest of a goblin that dared
approach him. Obviously the goblin was mistaken in his belief that the
mage was defenseless without his magic.
After catching their breath and taking care of the minor wounds they
had received during the encounter, the group continued on into the

forest, keeping an eye out for more of the creatures that stood between
them and their goal.
Since it seems that a character cant take a dozen steps in some RPGs
without encountering some type of creature or NPC that wants to bash in
his skull, a character will need to know how to defend himself at the
least and hopefully deal out some damage of his own. There are almost
as many types of combat systems as there are RPGs. Some are fairly
simple, while others are incredibly complex, almost requiring an
advanced mathematics degree to figure out. Most hide the calculations
from the player though, some even going so far as to show actual
damage on the entities and hiding the numbers, leaving the player to
figure out how badly hurt his character and opponent are in order to
determine whether to run or continue fighting. You can normally divide
them into two categories, however real time and turn based.
Real time means that characters are able to attack as fast as they can,
given the type of weapon theyre wielding and other factors. Depending
on how deep the combat system is, there could be any number of
additional factors that affect the characters rate of attack, such as the
type of armor the character is wearing (heavy armor will slow down the
character), one or more of the characters stats (Strength, Agility, and
Dexterity are some of the favorites), and the amount of skill the
character has with his weapon. With real-time combat the player
normally only has to click on the target and the character will start
attacking until that target is dead (or the character dies) unless you
intervene. Some RPGs allow you to queue up special attacks or tactics
while the character is fighting. For example, in the story at the beginning
of the chapter several characters are fighting a group of goblins.
Normally the character would only be able to attack one at a time. If the
character has the ability to attack more than one target with a small

penalty for each attack, the player may want to use this special attack
when one or more of the goblins were hurt and less able to defend
themselves. The player selects this attack at an appropriate time and as
soon as the character is able hell use the special attack, and then go back
to his normal attack. Thats assuming the character is able to use it at the
time. If only one goblin were in range, the character would just do a
normal attack. Neverwinter Nights is one example of an RPG that does
this. In the following screenshot, the actions that are queued up are
represented by icons in the upper left-hand corner.

Figure 6-1
A turn-based combat system usually means that one combatant will
attack and then the other will have his turn. The order of combat is
usually determined by a roll of the dice (called an initiative roll). This
roll can be modified by stats or some other factor. Dungeons and
Dragons worked this way. Combatants would compare their Dexterity
stat, and whichever had the highest would strike first. Combat is very
structured in a turn-based system. Usually magic spells are cast first and
then any ranged combat is resolved. Lastly, melee attacks, if possible,

are calculated. All of these actions together are called a round. In every
round a player could decide to have his character do something different
and usually has plenty of time to make that decision.
In this chapter well create a turn-based system where the order of action
for each turn is determined by multiple factors the Dexterity stat of
the entity, the type of weapon hes using and its weight, any bonuses that
are affecting the character positively or negatively, etc. Well also create
a combat simulator application that can be used to test combat without
having to start an actual game, allowing the developer to quickly finetune all the data that pertains to combat (item and entity stats, spell stats,
etc.).
In our game well represent the different actions an entity can take
during combat using an enum:
Listing 6-1

public enum AttackTypes


{
Normal,
Parry,
Riposte,
CalledShot,
LongRangeShot,
Disengage
}

If a player doesnt specify an attack type, it defaults to Normal. The


remaining attack types affect the players offensive or defensive bonus,
or both. Heres a description of the attack types:

Normal Nothing fancy, just the basic type of attack with the
weapon being wielded. The attacker is just looking to do damage but not
leave himself completely open for a counterattack.
Parry The character sacrifices his upcoming attack to attempt to
block his attackers blow. A bonus is added to the characters defensive
bonus for the current or next round, depending on when the character
attacks.
Riposte The character attempts to both block his attackers blow
and get in a quick retaliatory attack of his own. A small bonus is added
to the characters defensive bonus and a slight penalty is added to the
characters offensive bonus. While this type of attack is normally done
with a sword, well use it for any melee weapon. Note that this attack
and the Parry attack shouldnt show up with ranged weapons.
CalledShot The character attempts to attack a specific part of his
attackers body. Usually this is done against an opponent who is weaker
or when a player thinks he can kill the attacker with that shot. A
CalledShot attack is done at a sizable penalty to the offensive bonus and
leaves the character open for retaliation (a penalty to his defensive
bonus), so it is a risky maneuver.
LongRangeShot The character attempts to perform a ranged attack
at a target out of the normal range for the weapon he is using. There is a
large penalty to the offensive bonus for making this kind of attack. The
one good thing about this attack is that the character will usually get to
make at least one Normal attack before the attacker closes to within
melee range, so the character doesnt usually lose anything except the
bolt or arrow he fires. This is the only attack specifically for ranged
weapons.
Disengage The character attempts to perform an attack and retreat
so that his opponent cannot get in a counterattack. This doesnt

guarantee that his opponent will not follow the character and re-engage
him, but it gives the character the opportunity to try to get away. As with
the Parry and Riposte attacks, this attack wouldnt be used with ranged
weapons since the enemy wouldnt have been engaged yet.
There is no problem using these attack types in a turn-based system, of
course. For real-time combat, the use of attack types fits in nicely with a
queue type system, as was explained earlier. One possible problem
would be if the character performed the attack when the player wasnt
expecting it to occur. If you decide to use attack types in a real-time
combat system, you need to make sure that this doesnt occur and that
how the system works is well explained to the player.

Ready Fight
A player will initiate combat in one of several ways, but it always starts
by selecting a target, which is done by simply clicking on the sprite on
the screen. Some kind of visual indicator should be used to show the
player that the target has been selected. There are a number of ways to
do this:
Highlight the sprite Draw it with alpha blending to make it display
differently than it normally would, maybe by adding a glow around the
sprite.
Display an indicator around/under the sprite Neverwinter
Nights used this effect by placing a broken blue circle around the entity
in the middle of the screen. This is a more popular method and fairly
easy to do, especially in a tile-based system since youll easily know
where the sprite is located.
Show an icon for the sprite in the games GUI You could also
show other info about the entity: what weapon hes armed with, armor,
etc. How much you want to show is up to you. MMORPGs routinely
show the strength of a mob relative to the character so the player knows

how difficult the fight will be. This is only because the character is free
to wander into just about any area in the world, so he could end up
somewhere he shouldnt be. This isnt as much of a problem for singleplayer RPGs though.
After the player has selected a target he then usually chooses to attack,
although sometimes he can do both at once. If both actions are done
simultaneously, the attack will normally be the default for the character
using whatever weapon hes currently carrying. This could be
problematic if the player has forgotten to equip a weapon. (Ive done this
more than once!) No matter how the player initiates the fight, once it
starts youll have to change the game state to whatever combat mode the
game uses. This could be an entirely different screen, as we see in the
RPG Starter Kit thats available for XNA Game Studio:

Figure 6-2
You may choose to use the same view for combat as you do for the
noncombat state. Doing so means youll probably want to change or
disable some things such as the ability to save and/or quit the game or
perform actions that shouldnt be done in combat (such as trade items
with party members or chat with NPCs). More than likely youll find
during testing that you can do some things that you dont want the player
to be able to do during combat. Players will take advantage of whatever

bugs you miss during testing. Stories abound about bugs in MMORPGs
that allow players to cheat. A search for MMORPG exploits on the
Internet will show site after site that lists ways to use bugs to literally get
away with murder in almost every big-name MMORPG.
Assuming youre using a game state system for your RPG (and why
wouldnt you? Microsoft has even made a sample available on the
Creators Club web site that shows how to do it), simply setting the game
state to whatever value you use for combat and only allowing certain
types of input in your code that checks input devices is a start. Youll
probably want to have substates or variables that allow you to check for
things like whether it is the players turn, or whether the player has
selected an attack from the interface provided and, if so, which attack,
etc. The easiest way to do all of this is to wrap everything up into a
combat engine that gets turned on when the game state changes to
combat mode.

The Combat Engine


As stated earlier, well be creating a turn-based combat system. The
CombatEngine class will be used to resolve this combat system. Its a
fairly simple class for what it does:
Listing 6-2

public delegate void CombatEngineAttackEventHandler(


Entity attackingEntity, Entity defendingEntity);
public delegate void
CombatEngineEntityKilledEventHandler(Entity entity);
public delegate void
CombatEngineCombatCompletedEventHandler();

public class CombatEngine

{
private List<Entity> _players;
private List<Entity> _enemies;

private bool _isPlayersTurn;

//using an int here so that we can set it to 0


//to indicate an attack hasn't been selected yet
//we'll cast to AttackTypes as necessary
private int _attackSelected;

private bool _isCastingSpell;


private int _spellID;

private Random _rnd;

public event CombatEngineAttackEventHandler


AttackResolved;
public event CombatEngineEntityKilledEventHandler
EntityKilled;
public event CombatEngineCombatCompletedEventHandler
CombatCompleted;

public CombatEngine(Entity player, Entity enemy)


{
_players = new List<Entity>();
_players.Add(player);

_enemies = new List<Entity>();

_enemies.Add(enemy);

_rnd = new Random();


}

public CombatEngine(List<Entity> players, List<Entity>


enemies)
{
_players = players;
_enemies = enemies;

_rnd = new Random();


}
public string Start(bool randomStart)
{
string turnName = "";

//roll to see who goes first


//1-50 - enemy, 51-100 - player

int roll = _rnd.Next(1, 101);


_isPlayersTurn = (roll > 50);

if (_isPlayersTurn)
{
if (_players.Count == 1)
turnName = _players[0].Name;
else
turnName = "Players'";

}
else
{
if (_enemies.Count == 1)
turnName = _enemies[0].Name;
else
turnName = "Enemies'";
}

return turnName;
}

public string Start()


{
string turnName = "";

//figure out who goes first


//order of attacks is highest to lowest combination
of AGI+DEX

return turnName;
}

public void AttackSelection(AttackTypes type)


{
_attackSelected = (int)type;

ResolveAttack();

public void SpellSelected(int id)


{
_spellID = id;

ResolveAttack();
}

private void ResolveAttack()


{
_curAttacker.SelectedAttack =
(AttackTypes)_attackSelected;

_curAttacker.UseSkill(GlobalData.Items[_curAttacker.Inventory
.

EquippedItem(ArmorArea.RightHand).ID].SkillRequired,
Difficulty.Normal);

//if entity being attacked is killed, call event


if (!((Entity)_curAttacker.Target).IsAlive)
EntityKilled((Entity)_curAttacker.Target);

//reset selected attack and spell id


_attackSelected = 0;
_spellID = 0;

AttackResolved(_curAttacker,

(Entity)_curAttacker.Target);

if (_attackOrder.IndexOf(_curAttacker) ==
_attackOrder.Count-1)
_curAttacker = _attackOrder[0];
else
curAttacker = _attackOrder[
_attackOrder.IndexOf(_curAttacker) + 1];
}
}

The engine has two Start methods, but one is only really used in the
combat simulator. In a game, the nonrandom start method would be
called. I put the random start in to simulate things like sneak and surprise
attacks.
Take a look at the code for the ResolveAttack function. Surprisingly its
fairly short considering what it does. Thats because the real work is
done in the UseSkill method of the Entity class.
Listing 6-3

private void ResolveAttack()


{
_curAttacker.SelectedAttack =
(AttackTypes)_attackSelected;
_curAttacker.UseSkill(GlobalData.Items[
_curAttacker.Inventory.EquippedItem(
ArmorArea.RightHand).ID].SkillRequired,
Difficulty.Normal);

//if entity being attacked is killed call event

if (!((Entity)_curAttacker.Target).IsAlive)
EntityKilled((Entity)_curAttacker.Target);

//reset selected attack and spell id


_attackSelected = 0;
_spellID = 0;

AttackResolved(_curAttacker,
(Entity)_curAttacker.Target);

if (_attackOrder.IndexOf(_curAttacker) ==
_attackOrder.Count-1)
_curAttacker = _attackOrder[0];
else
_curAttacker = _attackOrder[_attackOrder.IndexOf(
_curAttacker) + 1];
}

Were assuming the entity was using his weapon in his right hand. If you
implement something like weapons that can be wielded in either hand or
ambidextrous entities, youll need to change this, but this will work for
our purposes.
The skill for the weapon being used is retrieved and the Entity classs
UseSkill method called. We make another assumption that the attack has
a difficulty value of Normal. This could be another area for
improvement.
If the entity being attacked is killed as a result of the attack, we notify
the form by firing the EntityKilled event. We then reset the
_attackSelected and _spellID members for the next attacker.

The AttackResolved event is fired and the current attacker in the list of
entities sorted by order of attack is incremented, resetting it to the first
entity if all the entities have attacked.

The Combat Simulator


Now that we have a combat system, we need a way to test it out. Heres
a screenshot of the combat simulator that youll find the code for in this
chapter:

Figure 6-3
Here we have Aragorn fighting a troll. Its Aragorns turn and he is
attacking using a Normal attack type with the Longsword weapon,
having 18 ranks for the Melee Weapons skill. He has hit for 24 points of
damage, even with a relatively low random die roll. We can also see that
the option for him to cast a spell is disabled as hes not a magic-using
character. If he were a magic-using character and had selected a spell,
the name of the spell would show in the Attack Selected box and the
Weapon combo box would have been filled with the offensive spells
hes learned.
You can stop combat at any time and select different combatants. The
simulator assumes the entity on the left is the player and the entity on the
right is a creature or monster. When you click the Select button, you can

select an entity in the Entities folder for either side. It doesnt matter if
you reverse the entities putting the player on the right or the creature
on the left or even if you pit player against player or monster against
creature.
Clicking either of the Start buttons creates the combat engine, passing it
the selected entities. The associated Start method of the engine is called
and the buttons are enabled or disabled appropriately.
Listing 6-4

private void btnStart_Click(object sender, EventArgs e)


{
_engine = new CombatEngine(_player, _enemy);

_engine.AttackResolved +=
new
CombatEngineAttackEventHandler(AttackResolved);
_engine.CombatCompleted +=
new
CombatEngineCombatCompletedEventHandler(CombatCompleted);
_engine.EntityKilled +=
new
CombatEngineEntityKilledEventHandler(EntityKilled);

_engine.Start(true);

btnStart.Enabled = false;
btnStop.Enabled = true;
btnClose.Enabled = false;
}

You simply select the type of attack you want the attacking entity to
make, and the combat engines ResolveAttack method is called. This is
similar to the way the RPG Starter Kit works, as we can see in Figure 64:

Figure 6-4
When an attack is resolved, the form is notified via the delegate and the
controls are updated with the results. The engine then waits for input
from the entity whose turn it is. When combat is resolved one way or the
other, the form is again notified. In an actual game, this would set the
game state back to whatever it was before combat or normal mode.
Youll probably spend a lot of time in the simulator, tweaking the
numbers until combat is fair and somewhat realistic.

Theres Always Room for Improvement


The combat system weve developed is one of the simpler kinds. Theres
lots of room to make it even better without making it overly complex
though. Here are some options:
Vary the damage done by how much over 100 the result of the
calculation is. Have a result of 100 be a normal value. For every five
points over 100, you could add one point of damage. This could simulate
hitting a vital part of the body or the hit being deeper than normal.

Right now an attack either hits or misses. If the attack misses, theres
no differentiation between the blow missing, being deflected by armor,
or being blocked. You could randomly pick one. If the entity being
attacked has a shield, the attack could be blocked with the possibility of
the shield being broken.
Allow the entity being attacked a counterattack for a very bad result,
say less than 25. You could also have other possibilities for bad results
dropped or broken weapons, the attacker stumbling and missing out
on his next attack, etc.
For an attack that succeeds by a great margin you could give the
attacker a free attack, possibly at a reduced chance or for less damage if
it hits.
Implement situations like:
Surprise The entity being attacked loses his first attack.
Stun If the entity being attacked takes more than x amount of
damage in one round, hes stunned and unable to act. The amount of
damage could be a set amount or a percentage of his current hit points.
Attacker invisible or attacking from rear Attacker gets a bonus to
his attack and/or certain defensive elements of the entity being attacked
arent considered. An attack from the rear shouldnt take a shield into
account. If you allow invisible entities to make an attack, its normal for
the invisible effect to be dispelled or for the entity to be visible for as
long as the combat lasts in the case of entities whose normal state is
being invisible (ghosts, for example, which normally reside in a different
dimension or out-of-phase state).
The possibilities are numerous. It all depends on how realistic you want
to make the system. You can always implement one feature at a time to
gradually improve the engine. Its always a good idea to plan out the
improvements on paper before actually incorporating them into your

game, however. You can usually tell how well the engine will work
without wasting time writing code.

Summary
While having the character fight it out with all kinds of creatures and
monsters is cool, an essential element is missing. The sounds of combat
the clang of a weapon on a shield or armor, the explosion of a magic
spell hitting a group of monsters, the cries of the wounded all are
important to the realism of the gameplay. We could also use some cool
music that plays while combat is taking place. Well take care of that in
the next chapter, implementing a sound manager and importing three
sounds for combat as well as some music to play when the game starts.
Once youve completed that chapter, combat will take on a whole new
dimension.

Chapter 7
Audio
You enter a dungeon and you realize you forgot to buy torches at the
shop. You cant see anything, but there are plenty of sounds that tell you
something about the area the sound of dripping water, the low growl
of some animal, the clicking of claws on stone, and the chittering of
many insects. Theres a lot of life and activity in the dungeon even
though you cant see it. Since your vision is useless you have to rely on
your sense of hearing to give you clues as to what to expect. Cautiously
you inch forward, waiting for the inevitable encounter and wondering
how youre going to fight in the dark.
All worlds are full of sound, and an RPG world is no different (at least it
shouldnt be if the developer did his job correctly). From background
sounds like a bubbling brook and birds chirping to the crackle of fire and

the crack of a lightning bolt being cast by a mage or swords ringing as


they strike armor and shields, your RPG has to have sound in order to
help further pull the player into the world. Sounds will also help the
player know what is happening in the world that he might not be able to
see voices behind a closed door to tell him hes in for a fight if he
opens it, the sounds of combat in a room down the hall to indicate where
the rest of the party is. Sound can be an extremely useful tool in your
game, but its almost always the least thought about portion of most
games.
If youve done any programming with DirectX, youre probably pretty
familiar with the portion that handles audio playback DirectSound.
Unfortunately, youll need to pretty much forget most of what youve
learned in stepping up to the XNA Framework and Game Studio. Audio
in XNA games is created using a tool called XACT (Cross-Platform
Audio Creation Tool) and played using either associated classes or a
simple API set that doesnt require XACT. If you plan on making games
for the Xbox 360 using Game Studio, youll have to use one of these two
options. On the PC youre free to use whatever sound file format and
API you wish, although I recommend using the built-in functionality that
comes with the XNA Framework as its extremely simple to set up and
use. Some of the better known formats include .wav, .mp3, and .ogg (the
Ogg Vorbis format). Some of the APIs that are available to you on the
PC include DirectSound, OpenAL, and FMOD. On the 360, the only
audio format available is .xma.
Well first look at the latter of the two options (the simple API set), as
its the easiest way to go and recommended if you dont have any special
needs for your audio playback. Well then take a look at XACT and how
to go about setting up and playing sounds using it.

Playing Sounds with the SoundEffect and


SoundEffectInstance Classes

The easiest way to play sounds that dont require any modification to the
sound itself is to use the SoundEffect and SoundEffectInstance classes.
These classes are found in the Microsoft.Xna.Framework.Audio
namespace. For most of the sounds you normally need in a game, these
two classes provide all the functionality to play a sound with the ability
to modify the volume, panning, and pitch during playback.
To play a sound using these classes, you first load the sound using the
Content Manager:
Listing 7-1

SoundEffect soundEffect;
string soundName = "kaboom";

soundEffect = contentManager.Load<SoundEffect>(soundName);

There are three overloaded Play methods of the SoundEffect class that
you can use, depending on your needs:
Table 7-1
Name

Description

SoundEffect.Play ()

Creates a new SoundEffectInstance and


plays it.

SoundEffect.Play (Single)

Creates a new SoundEffectInstance and


plays it at the specified volume.

SoundEffect.Play (Single,
Single, Single, Boolean)

Creates a new SoundEffectInstance and


plays it using the specified volume, pitch,
panning, and loop control.

You can call the Play method that takes no parameters and modify the
Volume, Pitch, and Pan properties of the returned SoundEffectInstance.

You can also call the Pause and Stop methods of the
SoundEffectInstance if you need to.
These two classes are meant only for rudimentary sound playback. If
you need more advanced sound support, including 3D audio, you will
need to use XACT, which is covered in depth later in this chapter. For
most games, though, the SoundEffect class should be enough.
So youve got sound effects working in your game and now youre
wondering about doing things like playing a song when your game starts
or allowing the player to play his own playlist in place of what you have
in your game. Luckily, XNA Game Studio 3.0 has got you covered.

Playing Songs
New to XNA Game Studio 3.0 is support for playing songs in a media
library on the PC, Xbox 360, and Zune. The classes responsible for this
functionality can be found in the Microsoft.Xna.Framework.Media
namespace. On the 360 and Zune the media library is known, and songs
that are uploaded to the device are automatically added to the library. On
the PC, before you can use the functionality in the XNA Framework to
play songs in a media library, the library first has to be compiled using
Windows Media Player to search the PC for song files to add to the
library.
The main classes that enable song playback are:
MediaLibrary Provides access to songs, playlists, and pictures in
the devices media library.
MediaPlayer Provides methods and properties to play, pause,
resume, and stop songs. MediaPlayer also exposes shuffle, repeat,
volume, play position, and visualization capabilities.
Song Provides access to a song in the song library.
MediaQueue Provides methods and properties to access and
control the queue of playing songs.

Playlist Provides access to a playlist in the media library.


Playing a song isnt much more difficult than playing a sound effect. The
following code will select a random album from the devices playlist and
play the first track of that album:
Listing 7-2

using System;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;

namespace Media_Sample
{
public class Game1 : Microsoft.Xna.Framework.Game
{
GraphicsDeviceManager graphics;
SpriteBatch spriteBatch;
MediaLibrary sampleMediaLibrary;
Random rand;

public Game1()
{
graphics = new GraphicsDeviceManager(this);
Content.RootDirectory = "Content";

sampleMediaLibrary = new MediaLibrary();

rand = new Random();

protected override void Initialize()


{
MediaPlayer.Stop(); // stop current audio
playback

// generate a random valid index into Albums


int i = rand.Next(0,
sampleMediaLibrary.Albums.Count - 1);

// play the first track from the album

MediaPlayer.Play(sampleMediaLibrary.Albums[i].Songs[0]);

base.Initialize();
}

protected override void Update(GameTime gameTime)


{
// Allows the game to exit
if
(GamePad.GetState(PlayerIndex.One).Buttons.Back ==
ButtonState.Pressed)
this.Exit();

base.Update(gameTime);

protected override void Draw(GameTime gameTime)


{
GraphicsDevice.Clear(Color.CornflowerBlue);

base.Draw(gameTime);
}
}
}

Between the new sound and song support that XNA Game Studio 3.0
offers, you should be covered. If youre not, however, you can dig into
XACT for more advanced functionality.

XACT
XACT uses compression to make sound files smaller, which is important
for Xbox games. Since your game files are stored on the Xbox hard
drive and you have limited space on it for your files, the less space your
files take up the more content you can include in your game. This isnt
as important on the PC since hard drives these days are many times
larger than the one in the 360. You also have the option of storing and
using files on CD or DVD. This isnt an option on the 360 since the
XNA Framework currently doesnt allow access to the DVD drive.
One good thing about using XACT is that it works the same for both PC
and 360, meaning you can use the same files and code for projects for
both systems. Before we get into the code though, some definitions
might be in order. The four main objects that youll be using for your
sound system are AudioEngine, WaveBank, SoundBank, and Cue, so
itll help to know what they are.

AudioEngine Fairly self-explanatory. The AudioEngine is what is


used to create wave banks and sound banks. The constructor for the class
takes as a parameter the path (including file name) to the .xgs file that is
created by XACT.
WaveBank A wave bank is a collection of wave files that can be
used to logically group similar files together. For example, all the
weapons sounds could go in one wave bank, all your voices in another,
background sounds in a third, etc. The constructor for the WaveBank
class takes as a parameter an AudioEngine instance and the path
(including file name) to the .xwb file that is created by XACT.
SoundBank A sound bank is a collection of sounds and cues. The
actual sounds are not stored in a sound bank, just references to the wave
files that are in a wave bank. The sound bank stores information on how
sounds are to be played, whether or not they loop, any distortions that
may be applied to a sound, etc. The constructor for the SoundBank class
takes as a parameter an AudioEngine instance and the path (including
file name) to the .xsb file that is created by XACT.
Cue Cues are the objects that are created by the programmer to
play sounds. A cue can contain one or more sounds. When the cue is
played, all the sounds in that cue are played in order unless the cue is
stopped.
There are some other terms that youll run across when working in
XACT, the two main ones being track andevent. A sound in a sound
bank contains one or more tracks, each of which contains at least one
event. An event is an action that is performed within a track. Every track
will have at least a Play Wave event. Other events are Stop, Volume,
Pitch, and Marker. Well look at some of these a bit later.

Creating Sounds with XACT

Before starting up XACT you might need to install the .NET Framework
1.1 Redistributable. Youll find the URL in the appendix. At the time of
this writing theres a known bug with a feature in XACT that causes an
error if the redistribution is not installed. After launching XACT, youll
be presented with a window that looks something like the following
figure:

Figure 7-1
Click the leftmost button on the toolbar (Creates a new project) and
give your project a name in the dialog that pops up. The next thing youll
need to do is create a wave bank to store the sounds for your game. Click
on the Wave Banks | New Wave Bank menu item or the New Wave
Bank button on the toolbar:

Figure 7-2
Youll also need to create a sound bank, so go ahead and click the Sound
Banks | New Sound Bank menu item or the New Sound Bank button on
the toolbar:

Figure 7-3
Click the Window | Tile Horizontally menu item to make it a little easier
to work with the Wave Bank and Sound Bank windows.
Now well add some wave files to the wave bank. We have four sounds
that were going to use an instrumental piece that well play in a loop
when the main menu is displayed, a sound for when the player character
attacks with a sword, a sound that plays when a monster attacks, and a
sound for when the players character dies. You can use either your own
sounds or the ones in the Content folder for this chapters project in the
downloadable zip file.
Just like other content, we will be referring to the sounds using the name
of the content:
Table 7-2
Original File Name

Content Name

song.wav

song

sword.wav

sword

attack.wav

attack

die.wav

die

If youre using your own sounds, just make sure theyre named properly.
Otherwise, youll have an exception thrown when you try to play the
sounds using the code well write a little later or youll end up playing
the wrong sounds.
Now that we have our wave bank, we need to add the sounds to the
sound bank. Select the four sounds and drag the items into the Cue

Name section of the Sound Bank window. You should end up with
something that looks like the following figure:

Figure 7-4
Now we want to set our title song to play repeatedly. Click on the sound
name called song in the Sound Bank window, and then click on the
Play Wave node under the Track 1 node to the right (you may need to
expand the node by clicking the plus sign to the left of Track 1 if its not
already expanded). In the properties window at the bottom left, find the
check box that says Infinite in the Looping group. Checking this will
cause the sound to loop until the cue is stopped.

Figure 7-5
Thats pretty much all we need to do for our game. Before building the
project, however, you might want to set the locations for where the files
are placed after building. Click on the Wave Bank and Sound Bank
nodes in the upper-left tree, and set the Windows Build Path property as
desired in the property window for each bank. Once youve done that
save the project by clicking the File | Save Project menu item. Build the
project by clicking the File | Build menu item or the Build button on the
toolbar:
Figure 7-6

Playing 2D Sound
The XACT project that was created can now be used to play the sounds
it contains. The first thing that needs to be done is to add AudioEngine,
WaveBank, and SoundBank objects and create them along with some
Cue objects:
Listing 7-3

AudioEngine audio;
WaveBank wavebank;
SoundBank soundbank;

GamepadState _curState;
GamepadState _lastState;

Cue songCue;
Cue swordCue;
Cue attackCue;
Cue dyingCue;

public Game1()
{
graphics = new GraphicsDeviceManager(this);
content = new ContentManager(Services);

audio = new AudioEngine("Chapter7sounds.xgs");


wavebank = new WaveBank(audio, "Wave Bank.xwb");
soundbank = new SoundBank(audio, "Sound Bank.xsb");
}

The Cue objects are loaded in the LoadContent method:


Listing 7-4

protected override void LoadContent()


{
songCue = soundbank.GetCue("song");
swordCue = soundbank.GetCue("sword");

attackCue = soundbank.GetCue("attack");
dyingCue = soundbank.GetCue("die");
}

The only other thing thats needed is some code in the Update method:
Listing 7-5

protected override void Update(GameTime gameTime)


{
_curState = Gamepad.GetState(PlayerIndex.One);

// Allows the game to exit


if (_curState.Buttons.Back == ButtonState.Pressed)
this.Exit();

if (_curState.Buttons.A == ButtonState.Pressed)
{
if (!songCue.IsPlaying)
{
songCue = soundbank.GetCue("song");
songCue.Play();
}
}

if (_curState.Buttons.B == ButtonState.Pressed)
{
if (!swordCue.IsPlaying)
{
swordCue = soundbank.GetCue("sword");
swordCue.Play();

}
}

if (_curState.Buttons.X == ButtonState.Pressed)
{
if (!attackCue.IsPlaying)
{
attackCue = soundbank.GetCue("attack");
attackCue.Play();
}
}

if (_curState.Buttons.Y == ButtonState.Pressed)
{
if (!dyingCue.IsPlaying)
{
dyingCue = soundbank.GetCue("dying");
dyingCue.Play();
}
}

if (_curState.DPad.Up == ButtonState.Pressed &&


_lastState.DPad.Up == ButtonState.Released)
{
soundbank.PlayCue("song");
}

if (_curState.DPad.Down == ButtonState.Pressed &&


_lastState.DPad.Down == ButtonState.Released)

{
soundbank.PlayCue("sword");
}

if (_curState.DPad.Left == ButtonState.Pressed &&


_lastState.DPad.Left == ButtonState.Released)
{
soundbank.PlayCue("attack");
}

if (_curState.DPad.Right == ButtonState.Pressed &&


_lastState.DPad.Right == ButtonState.Released)
{
soundbank.PlayCue("dying");
}

_lastState = _curState;

base.Update(gameTime);
}

Here we see the two different ways cues can be played. You can either
get a cue from the sound bank and keep it for playing over and over, or
you can have the sound bank play it directly.
Lets make a quick change to the buttons so that we can pause and
resume a cue. Make the following change to each button:
Listing 7-6

if (_curState.Buttons.A == ButtonState.Pressed &&


_lastState.Buttons.A == ButtonState.Released)

{
if (!songCue.IsPlaying)
{
songCue = soundbank.GetCue("title");
songCue.Play();
}
else if (songCue.IsPaused)
songCue.Resume();
else if (songCue.IsPlaying)
songCue.Pause();

Note that the order of your checks here is important. If you reverse the
checks for IsPaused and IsPlaying, youll end up pausing the sound and
never being able to get it started again, since IsPlaying will return true
when the sound is paused. We also need to check the last state of the
buttons to prevent the sound from immediately being paused. Try
removing the check of _lastState and see what happens when you press
the A button.
Lets make another modification to change the volume of the sounds.
Well replace the code in the DPad buttons to do this:
Listing 7-7

if (_curState.DPad.Up == ButtonState.Pressed)
{
volume = MathHelper.Clamp(volume + 0.01f, 0.0f, 5.0f);
}

if (_curState.DPad.Down == ButtonState.Pressed)

{
volume = MathHelper.Clamp(volume - 0.01f, 0.0f, 5.0f);
}

category.SetVolume(volume);

The category object is an AudioCategory object and the volume variable


is a float. That means we need some new declarations and some code to
get the category object:
Listing 7-8

float volume = 1.0f;


AudioCategory category;

public Game1()
{
graphics = new GraphicsDeviceManager(this);
content = new ContentManager(Services);

audio = new AudioEngine("Chapter7sounds.xgs");


wavebank = new WaveBank(audio, "Wave Bank.xwb");
soundbank = new SoundBank(audio, "Sound Bank.xsb");

category = audio.GetCategory("Default");
}

The Default category is what every sound is set to that you add to an
XACT project. You can create your own categories and group the
sounds as youd like. The one caveat here is that all the sounds in a

group are affected by the change in volume, so youll need to plan


accordingly if youre going to make volumes dynamic in your game.

Summary
Theres a lot of functionality in the Audio and Media namespaces of the
XNA Framework. With XACT and the Audio namespace you can do
things like distort sounds, create a Doppler effect on a sound, or use the
events in XACT to handle sounds differently. With the Media
namespace you can do music visualization; access song properties like
the artist, genre, and user rating; and get the albums cover art. Feel free
to explore both XACT and the Audio and Media namespaces further.
As we add functionality to the game in later chapters, we can easily add
new sounds background sounds and different songs for various
environments; sounds for every weapon, item, and spell; even vocal
versions of the text. Dont just add sounds because you can, though.
Make your sounds memorable in a good way. Itll make your game more
interesting and therefore more enticing to potential players.

Chapter 8
Creating the Tile Engine and Level
Editor
Up until now, weve been dealing only with the data and objects that
make up an RPG. Finally well actually be able to see the fruits of our
efforts. The reason Ive held off with graphics is partly because Im of
the opinion that graphics are one of the least important parts of an RPG.
A lot of people might argue that point. They can feel free to write their
own book on the topic.

Graphics in an RPG only hold my attention for

so long. If the guts on a game are weak the graphics wont hold it up.
Once the wow factor wears off, Ill get bored and possibly not even

finish it. On the other hand, I can put up with average graphics if theres
tons of data to play with stats to tweak and deciding what skills to
work on and what spells to learn. When Im about to go on an adventure
I like having to decide what items to take along, what armor to wear,
what weapons to use, and how much of what items to take.
Having said that, you have to have graphics or it would be hard to tell
where to go, what to do, or whats happening around you (unless youre
playing a text-based RPG, of course). In this chapter well implement a
fairly simple and straightforward 2D tile engine. While it wont have
cool spell effects and blood splatters from hacked up monsters and
dynamic, moving environments, itll do the job. As you learn how to do
these things, probably using shaders, you can implement them. Or you
can make the move to a full 3D engine. Several already exist in various
states of completion for use with the XNA Framework and Game Studio,
although some might not have made the upgrade to version 3.0. You can
check the links in the appendix for some sites that provide 3D engines.
Some are complete packages that include sound and network pieces as
well as the graphics engine.

Tiles
The basic building block of a tile engine is the tile, a usually square
(although sometimes rectangular, hexagonal, diamond, or octagonal
shaped) area of the level that holds information about that area, both
graphical and other. This information describes the terrain in that area as
well as whether the character can move onto or through the area,
whether an entity occupies that area, what other object might be in that
area (such as a building or items of any kind), and any other information
that affects either the world or an entity that moves into that area (a trap
of some kind, be it magical or nonmagical, an event trigger that fires
when an entity moves into the area, etc.).

In a level where the tiles were created with care and time, its usually
difficult to distinguish each individual tile. The artist must take the time
to create tiles that blend one area into another (water into a beach, beach
into grass, grass into rocky terrain, etc.).
Well represent a tile using the LevelSquare class:
Listing 8-1

public class LevelSquare


{
public int TileX, TileY;
public string TilesetName;

public bool trapped;


public Trap trap;

public bool hasTrigger;

public ObjectType type;


public short typeIndex;

public bool passable;

public string EntityID;

private List<Trigger> _triggers;

public List<Trigger> Triggers


{
get { return _triggers; }

public LevelSquare()
{
TileX = -1;
TileY = -1;
}

public bool HasTriggers()


{
bool ret = false;

if (!(_triggers == null))
ret = (_triggers.Count > 0);

return ret;
}

public void AddTrigger(Trigger trigger)


{
if (_triggers == null)
_triggers = new List<Trigger>();

_triggers.Add(trigger);

}
}

The class contains all the information well need to draw the level. The
first three members are used to get the specific tile in the tileset that was
used to set the graphical contents of this tile.
Tileset: A graphics file that contains many different individual graphics.
These graphics are stored in one file to make loading quicker and
handling the graphics when drawing easier.
Well be using three different tilesets in our editor two for buildings
and other structures and objects both man-made and not, and one for the
ground. Following are the tilesets that we have:

Figure 8-1

Figure 8-2

Figure 8-3
The background of each tileset is magenta so that the tiles can be drawn
over each other and not obscure the tile behind it. Magenta
(RGB[255,0,255]) is handled as a transparent color automatically by the
SpriteBatch object since its a color thats rarely used in sprites. Notice
that the buildings have shadows built into the graphic. This means were
somewhat restricted in the use of lighting, but thats not a big issue for

us. If you add support for an actual day/night cycle in your game, you
probably would have replaced the graphics beforehand anyway.
The next two members in the LevelSquare class are used to determine
whether or not the tile is trapped and, if so, what kind of trap is used. If
the tile is trapped, the trap member will be set to an instance of the Trap
class:
Listing 8-2

public struct Trap


{
public TrapType Type;
//use either DamageAmount from Damager or
//Level * base damage for trap type if Damager is empty
public byte Level;
public Damager TrapDamager;
public short Range;
public bool Active;
public bool SingleUse;
}

The TrapType enum contains the following values:


Listing 8-3

public enum TrapType


{
None,
Missile,

//normal missile-type

Gas,
Magic,

//spell is cast

Explosion
}

The Level and TrapDamager members are used to calculate the amount
of damage an entity suffers if he trips the trap, by either walking into the
tile or failing in an attempt to disarm the trap.
We looked at the Damager structure in an earlier chapter, but well
repeat it here for completeness:
Listing 8-4

[Serializable]
public struct Damager
{
public string Affects;
public string DamageAmount;
public DamageType Type;
}

In this case, the DamageType member of the structure is ignored. We


could have created another structure without it, but its easier to reuse
this structure. The base damage for each trap type is set in the
BaseTrapDamage enum:
Listing 8-5

public enum BaseTrapDamage


{
MissileTrap = 6,
GasTrap = 4,
MagicTrap = 10,

ExplosionTrap = 20
}

The Range member is used if the trap damage extends beyond the tile
the trap is on. This value is a number of expanding tiles outward from
the trapped tile. A Range of 2 would affect the following tiles:

Figure 8-4
The center tile is the trapped tile. An entity in the gray tiles will also take
damage. Ive colored the tiles light and dark for a reason. Its probably
not very realistic to have entities in the surrounding tiles take full
damage. In this situation, you can have entities in the dark gray tiles take
50% damage and those in the light gray tiles take 25% damage. You
would have to do calculations based on the value of the Range member
and come up with some value if its not evenly divisible, but thats up to
you to determine how best to handle.
The Active member determines if the trap is still active. If the SingleUse
member is set to true, the trap could still exist after being tripped, but the
Active member would be switched to false.
Next in the LevelSquare class is the hasTrigger member. If set to true,
the Triggers member will contain any triggers in the tile. The triggers are
used as a sort of scripting mechanism in lieu of true scripting. The
Trigger class has just a few members:
Listing 8-6

public enum TriggerType


{
SetTrap,
LockUnlock,
Message,
Spawn
}

public struct Trigger


{
public TriggerType Type;
public string SpawnName;

//if the trigger type is

spawn

//false to lock, lock is reserved so using unlock :)


public bool Unlock;
public Point TargetTile;

Currently we only have four types of triggers:


SetTrap Used to make a trap active.
LockUnlock Locks or unlocks an object on a tile. This could be a
door, chest, etc. The Unlock member is used to determine whether the
object is to be locked or unlocked.
Message Displays a message to the player. Useful for things like
reading signs, scrolls, etc.

Spawn Creates a creature or monster of the type noted in the


SpawnName member.
For every trigger type except Message, the TargetTile is where the action
occurs. This doesnt have to be the tile containing the trigger, it could be
a tile on the other side of the level. The tile does have to be in the current
level, though. It would be problematic to make it work across levels,
although not impossible.
The type and typeIndex members are used to determine what object, if
any, is in the level. Currently only two things can be in the level, as
noted by the ObjectType enum:
Listing 8-7

public enum ObjectType


{
None = -1,
Entity,
Item
}

Thats a lot of data stuffed into a tile. Put a lot of those tiles together and
you have a level.
The passable member is used in detecting collisions between an entity
and the type of terrain or object that may be on the tile. A building or an
entity standing at the bottom of a cliff would not be able to pass through
the tile. An enhancement to this collision detection could be to allow
varying types of passible tiles. Thick mud wouldnt prevent an entity
from passing through it, but would make for slow progress. Water would
require the entity to have some skill in swimming or he would drown.

The EntityID member identifies a particular entity that might be standing


on the tile. If the member is set to anything less than 1, there is no entity
on that tile. This is a less than ideal way to do this since entities will
almost always be moving around the level. For our demo this isnt a big
deal since the one person that will be in the town will always be in the
same spot and monsters will not be smart enough to move around. Ive
left this as an exercise for the reader to consider how to best enhance
this. Heres a hint: A List<int> might be useful in a different scope than
the tile level.

The Level Class


Our game world will be composed of a set of levels. A level can be just
about any size you want, limited only by the memory available on the
players machine. Given that most gamers these days have pretty beefy
machines, you should be able to create some pretty large levels. Note
that the larger the level, the longer it will take to load. Players will get
annoyed very quickly if a level takes more than 30 seconds to a minute
to load, and even thats pushing it. The trade-off between large levels
and load time is something youll have to experiment with. Note that
even a small level can take a while to load if its heavily populated.
Theres a lot of data in the Level class, in a relatively small number of
members:
Listing 8-8

public class Level


{
private string _name;
private string _description;

private int _width;

private int _height;

private int _minEntityLevel;

[ContentSerializerIgnore]
private Dictionary<string, Texture2D> _tiles;

private LevelSquare[,] _groundSquares;


private LevelSquare[,] _structureSquares;

private Dictionary<string, Texture2D> _entities;

//height and width of the viewport area in pixels


[ContentSerializerIgnore]
private int _viewportWidth;
[ContentSerializerIgnore]
private int _viewportHeight;

public string Name


{
get { return _name; }
set { if (!string.IsNullOrEmpty(value)) _name =
value; }
}

public string Description


{
get { return _description; }
set { _description = value; }

public int Width


{
get { return _width; }
set { _width = value; }
}

public int Height


{
get { return _height; }
set { _height = value; }
}

public int MinimumEntityLevel


{
get { return _minEntityLevel; }
set { _minEntityLevel = value; }
}

[ContentSerializerIgnore]
public int ViewportWidth
{
get { return _viewportWidth; }
set { _viewportWidth = value; }
}

[ContentSerializerIgnore]
public int ViewportHeight

{
get { return _viewportHeight; }
set { _viewportHeight = value; }
}

public Dictionary<Point, LevelSquare> GroundSquares


{
get
{
Dictionary<Point, LevelSquare> squares =
new Dictionary<Point, LevelSquare>();

Point pt;

for (int x = 0; x <


_groundSquares.GetUpperBound(0); x++)
{
for (int y = 0; y <
_groundSquares.GetUpperBound(1); y++)
{
//only store if there's a tile here
if (!string.IsNullOrEmpty(_groundSquares[
x, y].TilesetName))
{
pt = new Point(x, y);
squares.Add(pt, _groundSquares[x, y]);
}
}
}

return squares;
}
set
{
_groundSquares = new LevelSquare[_width, _height];

for (int x = 0; x < _width; x++)


{
for (int y = 0; y < _height; y++)
{
_groundSquares[x, y] = new LevelSquare();
}
}

foreach (KeyValuePair<Point, LevelSquare> kvp in


value)
{
_groundSquares[kvp.Key.X,
kvp.Key.Y].TilesetName =
kvp.Value.TilesetName;
_groundSquares[kvp.Key.X, kvp.Key.Y].TileX =
kvp.Value.TileX;
_groundSquares[kvp.Key.X, kvp.Key.Y].TileY =
kvp.Value.TileY;
}
}
}

public Dictionary<Point, LevelSquare> StructureSquares


{
get
{
Dictionary<Point, LevelSquare> squares =
new Dictionary<Point, LevelSquare>();

Point pt;

for (int x = 0; x <


_structureSquares.GetUpperBound(0); x++)
{
for (int y = 0; y <
_structureSquares.GetUpperBound(1);
y++)
{
//only store if there's a tile here
if
(!string.IsNullOrEmpty(_structureSquares[
x, y].TilesetName))
{
pt = new Point(x, y);
squares.Add(pt, structureSquares[x,
y]);
}
}
}

return squares;

}
set
{
_structureSquares = new LevelSquare[_width,
_height];

for (int x = 0; x < _width; x++)


{
for (int y = 0; y < _height; y++)
{
_structureSquares[x, y] = new
LevelSquare();
}
}

foreach (KeyValuePair<Point, LevelSquare> kvp in


value)
{
_structureSquares[kvp.Key.X,
kvp.Key.Y].TilesetName =
kvp.Value.TilesetName;
_structureSquares[kvp.Key.X, kvp.Key.Y].TileX
=
kvp.Value.TileX;
_structureSquares[kvp.Key.X, kvp.Key.Y].TileY
=
kvp.Value.TileY;
}
}

}
}

The first couple of members should be obvious as to what they contain.


The _minEntityLevel member is used to restrict the level to characters of
a certain level. While this is usually done in MMORPGs, not singleplayer RPGs, I added it in case someone finds it useful. We wont be
using it in our demo game.
The _tiles member contains the tilesets that are used. Note that the
member is set so that the textures arent stored in the level data on the
hard drive. This would be kind of silly to do, especially since the tileset
files are compiled already by the ContentBuilder class. The tilesets are
compiled so that we can use the same code to draw the level as is used in
the game. You can find out more about the ContentSerializerIgnore
attribute used here in the excellent posts by Shawn Hargreaves in his
blog (start
at http://blogs.msdn.com/shawnhar/archive/2008/08/12/everything-youever-wanted-to-know-about-intermediateserializer.aspx).
The next two members are used to give us two layers in which to draw
things. This allows objects to be hidden behind other objects and lets the
character walk behind things like buildings or trees.
The _entities member is used so that we dont have to load every entity
that exists when the level is loaded. This conserves memory, which is a
wise thing to do if your levels get to be fairly large. This isnt so much
an issue on most PCs nowadays as it is on the Xbox 360, which can be
considered to have a limited amount of memory. It would take a lot to
use all its memory, but its a good practice not to use more than you
need to.

The _viewportWidth and _viewportHeight members are used only in the


level editor, which is why we see again that the data in the members isnt
written to the level file.
The Level class only contains a couple of methods besides the Draw
method one each to set and remove a tile, FillGroundLayer, which
allows the tiles to be easily set to one tile type, one to put an entity on a
tile, and a couple of functions to load tiles and entities. Well take a look
at a few of these. Feel free to look at the others when you can.
Listing 8-9

public void SetTile(int squareType, int x, int y, string


tileset,
int tileCoordX, int tileCoordY)
{
switch ((Layer)squareType)
{
case Layer.Ground:
{
_groundSquares[x, y].TilesetName = tileset;
_groundSquares[x, y].TileX = tileCoordX;
_groundSquares[x, y].TileY = tileCoordY;

break;
}
case Layer.Structure:
{
_structureSquares[x, y].TilesetName = tileset;
_structureSquares[x, y].TileX = tileCoordX;
_structureSquares[x, y].TileY = tileCoordY;

break;
}
}
}

public void RemoveTile(int squareType, int x, int y)


{
switch ((Layer)squareType)
{
case Layer.Ground:
{
_groundSquares[x, y].TilesetName = "";
_groundSquares[x, y].TileX = -1;
_groundSquares[x, y].TileY = -1;

break;
}
case Layer.Structure:
{
_structureSquares[x, y].TilesetName = "";
_structureSquares[x, y].TileX = -1;
_structureSquares[x, y].TileY = -1;

break;
}
}
}

public void FillGroundLayer(string tileset, int tileCoordX,


int tileCoordY)
{
for (int x = 0; x < _width; x++)
{
for (int y = 0; y < _height; y++)
{
_groundSquares[x, y].TilesetName = tileset;
_groundSquares[x, y].TileX = tileCoordX;
_groundSquares[x, y].TileY = tileCoordY;
}
}
}

public void InsertEntity(string entityID, int x, int y)


{
_structureSquares[x, y].EntityID = entityID;
}

Although we only have two layers in our level, I used a switch statement
in the methods to set and remove a tile in case you want to add more
layers. Some RPG levels have three or more layers. Just add another
value to the Layer enum and another member for the array of
LevelSquare objects, copy and paste one case, and youre done.
Listing 8-10

public enum Layer


{
Ground,

Structure
}

The only remaining method is the main one, the Draw method:
Listing 8-11

public void Draw(SpriteBatch sb, int topX, int topY)


{
int tileX, tileY;

for (int x = 0; x <=

(int)(_viewportWidth / 32); x++)

{
for (int y = 0; y <=

(int)(_viewportHeight / 32);

y++)
{
tileX = x + topX;
tileY = y + topY;

if (!string.IsNullOrEmpty(_groundSquares[tileX,
tileY].TilesetName))
sb.Draw(_tiles[_groundSquares[tileX,
tileY].TilesetName],
new Rectangle(x * 32, y * 32, 32, 32),
new Rectangle(_groundSquares[tileX,
tileY].TileX *
32, _groundSquares[tileX, tileY].TileY *
32,
32, 32), Color.White);

if

(!string.IsNullOrEmpty(_structureSquares[tileX,
tileY].TilesetName))
sb.Draw(_tiles[_structureSquares[tileX,
tileY].TilesetName], new Rectangle(x *
32, y * 32,
32, 32),
new Rectangle(_structureSquares[tileX,
tileY].TileX * 32,
_structureSquares[tileX, tileY].TileY *
32, 32, 32),
Color.White);

if
(!string.IsNullOrEmpty(_structureSquares[tileX,
tileY].EntityID))
{
if
(_entities.ContainsKey(_structureSquares[tileX,
tileY].EntityID))
{

sb.Draw(_entities[_structureSquares[tileX,
tileY].EntityID], new Rectangle(x *
32
_entities[_structureSquares[tileX,
tileY].EntityID].Width - 32, x * 32
_entities[_structureSquares[tileX,
tileY].EntityID].Width - 32,
_entities[_structureSquares[tileX,

tileY].EntityID].Width,_entities[
_structureSquares[tileX, tileY]
.EntityID].Height), Color.White);
}
}
}
}
}

As with many of our classes, a relatively small amount of code does a lot
of work, mainly due to the object-oriented nature of C#. A simple loop
through the LevelSquare arrays is all that is needed to get the level
drawn on the screen. Only whats visible in the viewport is drawn and
only if the ground tile and structure tile is set. The entity in the tile, if
one exists, is also drawn. Its important to draw the tiles in the correct
order from the top left to the bottom right and to draw the ground layer
before the structure layer. Youll quickly know if things are not being
drawn correctly.

The Level Editor


The code for this chapter contains the level editor that will be used to
construct the levels for our sample game. The editor looks like Figure 85 when you first launch it.
The left side contains a tabbed dialog with the three tilesets well be
using. The right side is the rendering area for the level. The two combo
boxes in the toolbar are used to set the layer being drawn to and select an
entity to be placed in a tile. Most of the code in the editor is support for
the work done in the Level class. Feel free to fire up the editor and create
some test levels to get used to the functionality. You can also look at the
source code to see how using the SpriteBatch object in a non-XNA game
project is done.

Figure 8-5

Summary
We can now create just about whatever worlds we can imagine. Of
course we would have to add some new graphics to really get something
that seems like a living, breathing world, but the ability to create that
world is there. If you have a really good artist working for you, youll be
amazed at what you can create.
We now have a world, but no way for the player to really interact with it.
He cant even see what his character is wearing! In the next chapter,
well discuss what interface elements are needed to get the player to
where he needs to be as far as interacting with the world and everything
and everyone in it. Well implement a very rudimentary interface with
inventory and quest windows and a toolbar for allowing the player to
have quick access to items or skills.

Chapter 9
Interface
A games interface is the door between our world and the game world. A
good interface should be informative but unobtrusive. Too many game
interfaces are cumbersome and get in the way of playing the game. An
RPG is very complex, but some companies dont seem to try very hard
to make an interface that makes it any easier.
An interface covers such things as displaying a characters stats, skills,
inventory, and other vital information that must constantly be monitored.
It also usually offers a quick way to select and use spells and items such
as weapons and potions. Actions such as trading, buying, and selling are
also handled by the interface. Interactions with NPCs are sometimes
handled with dialogs, which are another part of the interface.
The interface can be designed in many different ways. Figures 9-1 to 93 are screenshots of parts of the interface of one RPG Neverwinter
Nights.
Neverwinter Nights also came up with a unique use for the right-click
function. Right-clicking on something brings up a set of general function
buttons around the object or entity. Clicking on one of these buttons
replaces the general buttons with more specific buttons if any are
available. The outward-pointing arrow next to a button indicates whether
or not it has more specific functionality. After spending a short time
using this, you learn how to quickly drill down to what you need. I like
this idea very much. It doesnt take up much space and, after you spend a
short amount of time learning it, you have quick access to almost
everything that pertains to what you click on.

Figure 9-1
Figure 9-2 is the character information window that is located in the top
right-hand corner of the game window. It gives you quick access to
basically everything to do with your character and any members of your
party. Immediately to the left of the characters picture is a bar that
shows the characters health. Having something like this on the screen at
all times is extremely convenient and almost necessary if your RPG is
quick moving, as the status of a character could change quickly. If you
have to stumble around the interface to find out if your character needs
healing because hes taking damage, its likely that your character could
be dead by the time you get to the information. Thats not a good way to
get people to like a game.

Figure 9-2
The piece of this interface that well be developing is a combination
inventory/character equipment window. It will show the armor and items
that the player has equipped the character with and the contents of the
characters inventory. The inventory piece will be very basic and wont
require the player to shuffle items around in the inventory. The player
will be able to drag an item thats in the inventory onto an area of the
characters equipped items, assuming its an item that can be equipped at
that location. Any item thats currently equipped at that location will be
dropped back into the inventory.
Figure 9-3 shows a couple of interface elements a status window to
give feedback to the player with information thats happening in the
game, a compass to show the direction in which the character is heading,
a small window to allow the player to talk to other players, and a toolbar
to allow quick access to items, skills, or other functionality.

Figure 9-3

Well be constructing just the toolbar piece of this interface. It would be


great to have all the other pieces, but Ill leave that to you to decide if
they would be useful for your game.

The Toolbar
The ToolBar class well be using will provide the player with access to
10 items or skills. The graphic it draws will look like the following:

Figure 9-4
The toolbar in this figure has been equipped in the first two slots with a
sword and a potion from the characters inventory. The potion is a oneuse item that will be removed from the inventory and toolbar when its
used. The sword will remain as long as the character is holding it.
The code for the toolbar is fairly simple and straightforward:
Listing 9-1

public class ToolBar : DrawableGameComponent


{
private const int NumToolbarIcons = 10;

private Texture2D _graphic;


private Rectangle _rect;

private Texture2D[] _icons;

private MouseState _lastState;

public delegate void ToolbarButtonClickedDelegate(int


index);

public event ToolbarButtonClickedDelegate


ToolbarButtonClicked;

public ToolBar(Game game)


: base(game)
{
_icons = new Texture2D[NumToolbarIcons];
}

public void SetIcon(int index, Texture2D icon)


{
if (index < NumToolbarIcons)
_icons[index] = icon;
}

protected override void LoadContent()


{
_graphic =
this.Game.Content.Load<Texture2D>("toolbar");

int x;

x = (this.Game.GraphicsDevice.Viewport.Width / 2) (_graphic.Width / 2);

_rect = new Rectangle(x,


this.Game.GraphicsDevice.Viewport.Height - 66,
_graphic.Width, _graphic.Height);

base.LoadContent();
}

public override void Update(GameTime gameTime)


{
MouseState state = Mouse.GetState();

//check to see if button was clicked


if (state.LeftButton == ButtonState.Released &&
_lastState.LeftButton ==
ButtonState.Pressed)
{
if (!(Rectangle.Intersect(_rect, new
Rectangle(state.X,
state.Y, 1, 1)) == Rectangle.Empty))
{
//figure out which icon was clicked
int index = (int)((state.X - _rect.X) /
64);
ToolbarButtonClicked(index);
}
}

_lastState = state;

base.Update(gameTime);
}

public override void Draw(GameTime gameTime)


{
SpriteBatch sb = ((Game1)this.Game).spriteBatch;

sb.Begin();

sb.Draw(_graphic, _rect, Color.White);

//loop through icons and draw


for (int i = 0; i < NumToolbarIcons; i++)
{
if (_icons[i] != null)
sb.Draw(_icons[i], new Rectangle(
_rect.X + (i * 64) + 1, _rect.Y + 1, 64,
64), Color.White);
}

sb.End();

base.Draw(gameTime);
}
}

The class has been inherited from the DrawableGameComponent class,


giving us some instant functionality to hook into, such as the
LoadContent, Update, and Draw methods. The icons that are drawn can
be changed by calling the SetIcon method and passing the slot for the
icon to be placed into.
Since the class inherits from DrawableGameComponent, we can use the
Update method to be able to tell when a button is clicked and let the

game know which button is clicked. The code outside of the class would
be responsible for figuring out what skill, spell, or item is in that spot on
the toolbar and taking the appropriate action.
Its not very exciting, but it doesnt have to be. The code has two jobs
to show the player what items have been set to each slot and to let the
game know when a toolbar button has been clicked. The next piece of
interface the inventory window is a bit more complicated.

The Inventory Window


Heres a screenshot of the inventory window as it appears at the start of a
game with nothing in the inventory and no items equipped:

Figure 9-5
The InventoryWindow class that is used to display this works almost
exactly like the ToolBar class. As items are picked up, theyll fill the
slots on the right side of the screen, showing the icon for the item and
the item name next to it. The player can drag the icon from the right side
to its corresponding location on the body on the left side, and the class
will handle setting that item to be equipped on the character.
As with the ToolBar class, the InventoryWindow class inherits from
DrawableGameComponent:
Listing 9-2

public class InventoryWindow :


Microsoft.Xna.Framework.DrawableGameComponent
{
//the height of the area that an item displays in
//on the right side of the screen
private const int ItemInfoBarHeight = 48;

private Inventory _inventory;


private Texture2D _graphic;

//the image of the inventory item being dragged to the


equipped area
private Texture2D _dragGraphic;

private Rectangle _rect;

private Rectangle _inventoryRect;


private Dictionary<ArmorArea, Rectangle> _armorRects;
private Rectangle _leftHandItem;
private Rectangle _rightHandItem;

private List<Rectangle> _inventoryItemRects;

//the up and down arrows on the right side of the window


private Rectangle _topButton;
private Rectangle _bottomButton;

private MouseState _lastState;

private int _inventoryIDSelected;

private int _topInventoryItemIndex;

private SpriteFont _font;

public Inventory Inventory


{
set { _inventory = value; }
}

public InventoryWindow(Game game)


: base(game)
{
_inventoryIDSelected = -1;
}

public override void Initialize()


{
_armorRects = new Dictionary<ArmorArea, Rectangle>();

_topButton = new Rectangle(611, 3, 26, 25);


_bottomButton = new Rectangle(611, 452, 26, 25);

_leftHandItem = new Rectangle(202, 20, 30, 30);


_rightHandItem = new Rectangle(266, 20, 30, 30);

_inventoryItemRects = new List<Rectangle>();

_inventoryItemRects.Add(new Rectangle(322, 2, 288,


44));
_inventoryItemRects.Add(new Rectangle(322, 50, 288,
44));
_inventoryItemRects.Add(new Rectangle(322, 98, 288,
44));
_inventoryItemRects.Add(new Rectangle(322, 146, 288,
44));
_inventoryItemRects.Add(new Rectangle(322, 194, 288,
44));
_inventoryItemRects.Add(new Rectangle(322, 242, 288,
44));
_inventoryItemRects.Add(new Rectangle(322, 260, 288,
44));
_inventoryItemRects.Add(new Rectangle(322, 308, 288,
44));
_inventoryItemRects.Add(new Rectangle(322, 352, 288,
44));
_inventoryItemRects.Add(new Rectangle(322, 400, 288,
44));

base.Initialize();
}

protected override void LoadContent()


{
_graphic =
this.Game.Content.Load<Texture2D>("inventory");

int x = (this.Game.GraphicsDevice.Viewport.Width / 2)
(_graphic.Width / 2);
int y = (this.Game.GraphicsDevice.Viewport.Height /
2) (_graphic.Height / 2);

_rect = new Rectangle(x, y, _graphic.Width,


_graphic.Height);

_inventoryRect = new Rectangle(x + 322, y + 2,

315,

476);

_armorRects.Add(ArmorArea.Head, new Rectangle(141 +


_rect.X, 33 +
_rect.Y, 30, 30));
_armorRects.Add(ArmorArea.Neck, new Rectangle(63 +
_rect.X, 47 +
_rect.Y, 30, 30));
_armorRects.Add(ArmorArea.Chest, new Rectangle(63 +
_rect.X, 97 +
_rect.Y, 30, 30));
_armorRects.Add(ArmorArea.LeftUpperArm, new
Rectangle(25 + _rect.X,
137 + _rect.Y, 30, 30));
_armorRects.Add(ArmorArea.UpperArms, new Rectangle(33
+ _rect.X, 315
+ _rect.Y, 30, 30));

_armorRects.Add(ArmorArea.LeftLowerArm, new
Rectangle(25 + _rect.X,
175 + _rect.Y, 30, 30));
_armorRects.Add(ArmorArea.LowerArms, new Rectangle(33
+ _rect.X, 369
+ _rect.Y, 30, 30));
_armorRects.Add(ArmorArea.LeftWrist, new Rectangle(25
+ _rect.X, 212
+ _rect.Y, 30, 30));
_armorRects.Add(ArmorArea.Wrists, new Rectangle(33 +
_rect.X, 421 +
_rect.Y, 30, 30));
_armorRects.Add(ArmorArea.LeftHand, new Rectangle(25
+ _rect.X, 249 +
_rect.Y, 30, 30));
_armorRects.Add(ArmorArea.Hands, new Rectangle(110 +
_rect.X, 414 +
_rect.Y, 30, 30));
_armorRects.Add(ArmorArea.RightUpperArm, new
Rectangle(62 + _rect.X,
137 + _rect.Y, 30, 30));
_armorRects.Add(ArmorArea.RightLowerArm, new
Rectangle(62 + _rect.X,
175 + _rect.Y, 30, 30));
_armorRects.Add(ArmorArea.RightWrist, new
Rectangle(62 + _rect.X, 212
+ _rect.Y, 30, 30));
_armorRects.Add(ArmorArea.RightHand, new Rectangle(62
+ _rect.X, 249

+ _rect.Y, 30, 30));


_armorRects.Add(ArmorArea.Waist, new Rectangle(242 +
_rect.X, 108 +
_rect.Y, 30, 30));
_armorRects.Add(ArmorArea.Groin, new Rectangle(242 +
_rect.X, 146 +
_rect.Y, 30, 30));
_armorRects.Add(ArmorArea.LeftUpperLeg, new
Rectangle(224 + _rect.X,
200 + _rect.Y, 30, 30));
_armorRects.Add(ArmorArea.LeftKnee, new Rectangle(224
+ _rect.X,
275 + _rect.Y, 30, 30));
_armorRects.Add(ArmorArea.UpperLegs, new
Rectangle(248 + _rect.X, 327
+ _rect.Y, 30, 30));
_armorRects.Add(ArmorArea.Knees, new Rectangle(248 +
_rect.X, 381 +
_rect.Y, 30, 30));
_armorRects.Add(ArmorArea.LeftLowerLeg, new
Rectangle(224 + _rect.X,
275 + _rect.Y, 30, 30));
_armorRects.Add(ArmorArea.LowerLegs, new
Rectangle(248 + _rect.X, 433
+ _rect.Y, 30, 30));
_armorRects.Add(ArmorArea.LeftFoot, new Rectangle(122
+ _rect.X, 365
+ _rect.Y, 30, 30));
_armorRects.Add(ArmorArea.Feet, new Rectangle(185 +

_rect.X, 415 +
_rect.Y, 30, 30));
_armorRects.Add(ArmorArea.RightUpperLeg, new
Rectangle(264 + _rect.X,
200 + _rect.Y, 30, 30));
_armorRects.Add(ArmorArea.RightKnee, new
Rectangle(264 + _rect.X, 238
+ _rect.Y, 30, 30));
_armorRects.Add(ArmorArea.RightLowerLeg, new
Rectangle(264 + _rect.X,
275 + _rect.Y, 30, 30));
_armorRects.Add(ArmorArea.RightFoot, new
Rectangle(165 + _rect.X, 365
+ _rect.Y, 30, 30));

_font = this.Game.Content.Load<SpriteFont>("font");

base.LoadContent();
}

public override void Update(GameTime gameTime)


{
//check to see if player is moving an item
//if so, update the inventory
MouseState state = Mouse.GetState();
Rectangle rectClicked = new Rectangle(state.X,
state.Y, 1, 1);

if (state.LeftButton == ButtonState.Pressed &&

_lastState.LeftButton
== ButtonState.Released)
{
//figure out if an inventory item has been
clicked and set index
if (Rectangle.Intersect(_inventoryRect,
rectClicked) !=
Rectangle.Empty)
{
_inventoryIDSelected =
_inventory.Items[_topInventoryItemIndex +
(int)((state.Y _inventoryRect.Y) /
ItemInfoBarHeight)].ID;
_dragGraphic =

GlobalData.Items[_inventoryIDSelected].Picture;
}
else if (Rectangle.Intersect(_topButton,
rectClicked) !=
Rectangle.Empty)
{
if (_topInventoryItemIndex > 0)
_topInventoryItemIndex--;

}
else if (Rectangle.Intersect(_bottomButton,
rectClicked) !=
Rectangle.Empty)

{
if (_topInventoryItemIndex +
((int)(_rect.Height /
ItemInfoBarHeight)) <
_inventory.Items.Count - 1)
_topInventoryItemIndex++;
}
}
else if (state.LeftButton == ButtonState.Released &&
_lastState.LeftButton == ButtonState.Pressed)
{
//figure out if an inventory item has been
dragged
//onto an equip area
if
(GlobalData.Items[_inventoryIDSelected].GetType() ==
typeof(Armor))
{
foreach (KeyValuePair<ArmorArea, Rectangle>
kvp in
_armorRects)
{
if (Rectangle.Intersect(kvp.Value,
rectClicked) !=
Rectangle.Empty)
{
//see if item can be equipped in
this spot
if

(((Armor)GlobalData.Items[_inventoryIDSelected]).
Location == kvp.Key)
{

_inventory.EquipItem(_inventoryIDSelected,
kvp.Key);
}
}
}
}
else if
(GlobalData.Items[_inventoryIDSelected].GetType() ==
typeof(Weapon) &&
Rectangle.Intersect(rectClicked, new
Rectangle(_rightHandItem.X + _rect.X,
_rightHandItem.Y +
_rect.Y, _rightHandItem.Width,
_rightHandItem.Height)) !=
Rectangle.Empty)
{
_inventory.WeaponEquippedID =
_inventoryIDSelected;
}
else if
(GlobalData.Items[_inventoryIDSelected].GetType() ==
typeof(Shield) &&
Rectangle.Intersect(rectClicked,
_leftHandItem) != Rectangle.Empty)

{
_inventory.ShieldEquippedID =
_inventoryIDSelected;
}

_inventoryIDSelected = -1;
}

_lastState = state;

base.Update(gameTime);
}

public override void Draw(GameTime gameTime)


{
SpriteBatch sb = ((Game1)this.Game).spriteBatch;

sb.Begin();

sb.Draw(_graphic, _rect, Color.White);

int count = 0;

//draw items
foreach (EntityItem item in _inventory.Items)
{
sb.Draw(GlobalData.Items[item.ID].Picture, new
Vector2(_inventoryItemRects[count].X +
_rect.X + 4,

_inventoryItemRects[count].Y + _rect.Y + 4),


Color.White);

sb.DrawString(_font,
GlobalData.Items[item.ID].Name, new
Vector2(_inventoryItemRects[count].X +
_rect.X + 48,
_inventoryItemRects[count].Y + _rect.Y + 8),
Color.White);

count++;

if (count == 10)
break;
}

//draw equipped armor and weapon/shield


foreach (int area in
Enum.GetValues(typeof(ArmorArea)))
{

if (_inventory.EquippedItemID((ArmorArea)area) >
0)
{

sb.Draw(_inventory.EquippedItem((ArmorArea)area).Picture,
_armorRects[(ArmorArea)area],
Color.White);
}

if (_inventory.ShieldEquippedID > 0)
{

sb.Draw(GlobalData.Items[_inventory.ShieldEquippedID].Picture
,
new Rectangle(_leftHandItem.X + _rect.X,
_leftHandItem.Y +
_rect.Y, _leftHandItem.Width,
_leftHandItem.Height),
Color.White);
}

if (_inventory.WeaponEquippedID > 0)
{

sb.Draw(GlobalData.Items[_inventory.WeaponEquippedID].Picture
,
new Rectangle(_rightHandItem.X + _rect.X,
_rightHandItem.Y
+ _rect.Y, _rightHandItem.Width,
_rightHandItem.Height),
Color.White);
}

sb.End();

base.Draw(gameTime);

}
}

One thing youll probably notice right off is all the hard-coded Rectangle
objects. While Im not a big fan of hard-coding numbers, theres not
much way around it here. You have to know where the player can click
to drag and drop items.
The _inventoryRect member allows us to check whether the player
clicks in the area that displays the inventory items to see if hes
attempting to drag an item to equip it. We do this by creating a
Rectangle object for the pixel that the player has clicked on and seeing if
it intersects with the _inventoryRect member:
if (Rectangle.Intersect(_inventoryRect, rectClicked) !=
Rectangle.Empty)

If the player has clicked on an item, we find the ID associated with that
item and keep track of it in the _inventoryIDSelected member. Once the
player releases the left mouse button, we figure out where the player has
dropped the item and whether that spot is valid based on the type of item
he dragged:
Listing 9-3

else if (state.LeftButton == ButtonState.Released &&


_lastState.LeftButton == ButtonState.Pressed)
{
//figure out if an inventory item has been dragged
//onto an equip area
if (GlobalData.Items[_inventoryIDSelected].GetType() ==
typeof(Armor))

{
foreach (KeyValuePair<ArmorArea, Rectangle> kvp in
_armorRects)
{
if (Rectangle.Intersect(kvp.Value, rectClicked)
!= Rectangle.Empty)
{
//see if item can be equipped in this spot
if

(((Armor)GlobalData.Items[_inventoryIDSelected]).
Location == kvp.Key)
{

_inventory.EquipItem(_inventoryIDSelected, kvp.Key);
}
}
}
}
else if (GlobalData.Items[_inventoryIDSelected].GetType()
==
typeof(Weapon) && Rectangle.Intersect(rectClicked,
new
Rectangle(_rightHandItem.X + _rect.X,
_rightHandItem.Y +
_rect.Y, _rightHandItem.Width,
_rightHandItem.Height)) !=
Rectangle.Empty)
{

_inventory.WeaponEquippedID = _inventoryIDSelected;
}
else if (GlobalData.Items[_inventoryIDSelected].GetType()
==
typeof(Shield) && Rectangle.Intersect(rectClicked,
_leftHandItem) != Rectangle.Empty)
{
_inventory.ShieldEquippedID = _inventoryIDSelected;
}

If the player is dragging a piece of armor and drops it on one of the


armor rectangles, we have to do an additional check to see if that area is
a valid location for that piece of armor. If it is, the EquipItem member of
the Inventory class is called, passing the ID and location.
If the player is dragging a shield or weapon, the check is simpler since
we only have one area for each of those types of items. The Inventory
class has two members, one for the shield thats equipped and one for
the weapon. If you want to enable dual-wielding so players can have a
character such as a thief using two daggers, the Inventory and
InventoryWindow classes will have to be modified. Its a fairly simple
modification, though. The graphic is already generic in that it says
Item and not Weapon or Shield, so that wouldnt need to be
changed. The code for this chapter includes a new Inventory class that
has _weaponEquipped and _shieldEquipped members added.
These members could be changed to match the _leftHandItem and
_rightHandItem members in the InventoryWindow class. You would
have to implement additional checks so that a player cant do something
like equip two shields.
Drawing the items is fairly easy because of the hard-coded rectangles we
have. The _armorRects and the _equippedItems members are

Dictionaries where ArmorArea values are the keys for the Rectangle
objects and item IDs so all that has to be done is a simple lookup to see
if an item is in that area. We do this, returning a value from the
EquippedItemID thats either an item ID or 1 if theres nothing
equipped in that area:
Listing 9-4

foreach (int area in Enum.GetValues(typeof(ArmorArea)))


{

if (_inventory.EquippedItemID((ArmorArea)area) > 0)
{

sb.Draw(_inventory.EquippedItem((ArmorArea)area).Picture,
_armorRects[(ArmorArea)area], Color.White);
}
}

//in the Inventory class


public int EquippedItemID(ArmorArea area)
{
if (_equippedItems != null)
{
if (_equippedItems.ContainsKey((int)area))
return _equippedItems[(int)area];
else
return -1;
}

else
return -1;
}

Drawing the inventory items is even easier. We simply get each item in
the inventory. The icon and name of the item are drawn for up to 10 of
them, and the name of the item is offset to the right of the icon:
Listing 9-5

foreach (EntityItem item in _inventory.Items)


{
sb.Draw(GlobalData.Items[item.ID].Picture, new
Vector2(_inventoryItemRects[count].X + _rect.X + 4,
_inventoryItemRects[count].Y + _rect.Y + 4),
Color.White);

sb.DrawString(_font, GlobalData.Items[item.ID].Name, new


Vector2(_inventoryItemRects[count].X + _rect.X + 48,
_inventoryItemRects[count].Y + _rect.Y + 8),
Color.White);

count++;

if (count == 10)
break;
}

The sample project for this chapter puts both of these interface elements
together in one game window, as seen inFigure 9-6.

Figure 9-6

GUI Libraries
Rather than creating your own GUI windows, you could take a look at
the various GUI libraries that exist for use with XNA Game Studio
games. Although they are all still in the early stages of their life (and
some have already died through starvation and neglect) and thus tend to
be buggy and incomplete in terms of features, using one of these
libraries may save you time on the front end of development in getting a
GUI up and running quickly. You may have to spend time later on in
development if you come upon a bug or need a feature that isnt
implemented. If the creator of the library has released the source code,
you can fix the bug or implement the feature yourself. If not, youll have
to report the bug or feature request and wait for the release of a new
version.
One GUI library that Ive found to be fairly full featured is the Neoforce
Controls library, which can be found
athttp://tomshane.cz/dnn/Default.aspx. It currently has 20 controls in it
and supports a lot of nice features:

Resizable windows
Movable windows
Auto-scrolling windows
Windows shadows
Transparent controls
Skinnable hardware cursor
Probably the nicest feature of this library is that its skinnable, meaning
you can change the way the controls look simply by creating a text file
that describes the appearance of the controls. You then tell the controls
to use this skin when you create them.
One problem you may run into when searching for a good GUI library
for XNA Game Studio games is that some of the ones that were built for
previous versions of XNA Game Studio have been abandoned and dont
necessarily indicate which version they were built for. If the latest
version of a library is over a year old, it will have been for an older
version and youll probably run into some issues with trying to get it
working for XNA Game Studio 3.0, especially if you want to get your
game running on the Xbox 360. Feel free to take a look at the code
though, as youll almost always learn something useful that can be
applied to what youre doing.

Areas for Improvement


One downside to what weve done here is that its not as generic as it
could be. Each class has the functionality hard-coded in it. A more
generic interface system might use basic controls to construct each
window, having events tied to each control, kind of like the way the
.NET Framework handles things. Doing this would be very difficult and
take a lot of time to develop and test. While some AAA-level games
have done something like this, even allowing players to modify the
interface through scripting (World of Warcraft is a good example, even

having an add-on for Visual Studio), I think its overkill for the average
indie developer.
As you gain more experience, you could begin constructing a GUI
library and replace pieces of the interface with a custom version built
using individual controls. Since this is a big area that XNA Game Studio
and the XNA Framework are lacking in, the community would definitely
welcome such a library, myself included.
Some specific things that could be improved:
The InventoryWindow class doesnt allow for unequipping items. You
can only replace an equipped item with another item. There are several
ways to fix this:
Implement code to check for a right-click on an area and unequip the
item
Implement code to handle dragging an item off an area and unequip
the item
Although the Item class has an _autoReady member, the functionality
to equip an item when the player picks it up is not implemented.
The _dragGraphic texture is being set for the item in the inventory
thats being dragged, but its not being drawn as the drag progresses.
This would be a simple matter of grabbing the X and Y coordinates from
the _lastState member and drawing the _dragGraphic texture as long as
the left mouse button is down. Checking the _inventoryIDSelected
member should suffice here as its set to 1 when the mouse button is
released.
The InventoryWindow class cannot be moved. The graphic could be
modified to have a title bar on which you can check for a click. You
could then allow the player to drag the window. Whether or not you
allow the player to drag the window partially off the screen is up to you.

If you choose not to, you have to implement boundary checks on the
edges of the screen.
Repairing (and damaging for that matter) items is not implemented,
although the members are there to handle it. This would probably require
more than just an interface to allow the player to select an item to repair,
since in RPGs you normally have to take the item to a black smith or
armorer, but the interface is important. You may want to charge the
player to repair items. In this case, you would have to let the player
know how much its going to cost and allow him to confirm that he
wants to have the item repaired.
Since a player can have more than one of the same item and these
items can have different properties, displaying only the name of the item
is not enough to allow the player to figure out which one he wants to
use. You could shrink the font used to display the item and include
enough of the properties of an item to allow the player to figure out
exactly what its capable of.
The toolbar doesnt currently support shortcut keys. Ideally this would
be configurable and saved in a configuration file of some kind.

Summary
This has been a very brief look at several basic pieces of an interface that
every RPG needs.
A good interface is a must. It will aid players without drawing them out
of the game world. Ideally, the interface should allow the player to
customize it to suit the way he plays the game and remember that
customization the next time he starts up the game. Theres plenty of
room for improvement in the small pieces of interface weve developed
in this chapter. It was never meant to be the ultimate interface
experience, just provide some basics in how to build one. You should
now have enough understanding to modify what was developed here so

that it works the way you determine it should work for your game. Try to
get some feedback from other gamers to see how well your interface
works before you get too far into development and are stuck with hardto-modify code. Keeping your interface code design open and modular
will benefit you when you get feedback that requires changes to the
interface.
In the next chapter well be developing code to create quests and
handling having a player work through them. You can use the
knowledge youve gained in this chapter to begin the creation of a
window in which to display these quests.

Chapter 10
Quests
The backbone of any good fantasy or sci-fi story is the quest the main
character undertakes. It may be the lone knight journeying through the
countryside and defeating all enemies who stand in his way until he gets
to the castle where the evil king/knight/wizard is holding the princess.
Or it could be a cave where the dragon that has been ravaging the land is
hiding. Whatever it is, you know that a huge battle is going to happen
near the end of the story.
Along the way, the character could have interesting little side
adventures, or subquests. They might not have any effect on the main
quest or they could be vital to its success. Saving a small village from a
pack of orcs is an example of a subquest that might not affect the main
quest. The character may think that undertaking the subquest could delay
him from completing the main one or he may consider the fact that he
might not survive a battle with the orcs so he decides not to accept it.
Accepting or declining this subquest may have no effect on his

completing the main quest, unless he dies, or there could be some side
effects of his decision not to accept it.
Perhaps hes a member of an organization that has made ridding the land
of orcs its goal. If word gets back that he didnt accept the subquest, he
could face being kicked out of the organization. Or say the character is a
paladin and one of his oaths is to protect the helpless. His church or god
may not like the fact that he abandoned the village. Even if the character
rescues the princess or kills the dragon, this fact may be overshadowed
by the penalty of not accepting the side-quest.
What if the character has set out to slay a dragon and hears a rumor that
its invulnerable to all weapons but a particular magic sword that has
been lost for centuries? The character would have to first find that sword
before he could face the dragon. This is an example of a subquest that
must be completed before the main one can be finished. Or the subquest
could be finding a key that unlocks the room holding the princess since
the room has been magically sealed against all entry without the key.
Subquests may just make the story more interesting or may be one or
more necessary steps in the completion of the main quest. Quests are a
staple of most stories either way. The same is true for most good RPGs,
whether theyre single player or multiplayer. Some of the MMORPGs
that Ive played EverQuest, World of Warcraft, and Dark Age of
Camelot among them had hundreds of different types of quests that
characters could undertake. The quests covered everything from running
notes between different NPCs to slaying a monster for an item. Most of
them had several steps that had to be completed before the quest was
finished. Completing quests was one of the things that made playing the
game so much fun. When you see a character run by with a flaming
sword you would most likely say, Wow, I have to get one of these!
and then spend the next couple of days or weeks figuring out the steps

necessary to complete that quest. Oftentimes this consisted of sitting


around waiting for a certain creature to appear. That was a big problem
with the quests in those games. Some creatures only appeared once a day
or week and then only at a certain time. If you couldnt be online at that
time, you missed your chance. In my opinion, thats unacceptable and is
one of the biggest problems with MMORPGs at this point.
The quest system well implement here will be very basic, as it has to be.
It will, however, cover quests in enough detail to allow you to
understand how they work so that you can implement quests of your
own with any number of steps and/or subquests. Well attempt to make it
easy to change and expand on. I know youre all impatient, so lets dig
in.

The Quest Class


Listing 10-1

public class Quest


{

private int _id;


private string _name;
private string _description;
private QuestType _type;
private QuestRewardType _rewardType;
private long _rewardItemID;
private string _requiredClasses;
private int _requiredLevel;
private bool _isMultipleAllowed;

// 0 means no limit

private long _timeBetweenQuests;

// total time in which quest must be completed, 0 for


none
private long _timeLimit;

// is the reward known by the player when accepting the


quest
private bool _isRewardShown;

// array of FactionAdjust
private List<KeyValuePair<int,int> _factions;

// array of QuestStep
private List<QuestStep> _steps = new List<QuestStep>();
}

As with other classes, the _id member will be used in Entity objects to
find a quest. Why do I say used in Entity objects? Quests are usually
given to and undertaken by entities. Sure, you could have a quest just
lying around waiting for the player to come by and accept it (say, finding
a piece of paper with a map to a treasure on it or a Help Wanted job
board in the center of a town), but its easier to just have them come
from an entity. You could certainly expand quests to come from places
like the aforementioned map or job board, and I would encourage you to
do so if you plan on creating a real world in your RPG.
A FedEx quest, named after the delivery company, is a quest in which
the player has to deliver an item to an entity. The item could be given to
the player by the entity giving the quest or it might have to be found by

the player. In the latter case, the entity giving the quest could be who the
item is delivered to or it could be another entity.
The _type member can be used to allow filtering of quests by the
programmer, designer, or player. This can be useful in determining how
many of what types of quests are available to players. If youve designed
100 FedEx quests and only 25 Kill quests, you may want to come up
with more of the latter type quests. Currently this member may be one of
the following:
Listing 10-2

public enum QuestType


{
FedEx,
Item,
KillMonster,
Rescue
}

There are probably more types of quests that could be implemented, but
these will do for now and well only actually implement one of them in
our sample game.
Although a quest may be of a certain type, it can actually contain steps
or even subquests of totally different types. How complex you make
your quests is totally up to you. Thats not to say that the more complex
a quest is, the better it is. Sometimes more is less. You could construct a
quest that takes the player a month of playing time to complete, but
making it interesting enough to make the player want to complete it
could be difficult. If the player has to go all over the game world and
listen to NPCs ramble on and on about things before getting the next step

of the quest, which turns out to be nearly impossible to complete, players


may just end up uninstalling your game and moving on to something
better. I put the word in quotes because its a subjective word. What
you think is good and works for a quest or your game might not be
something that a majority of gamers like. If you are making your game
with plans to sell it, youll need to be aware of your target audience. A
game where your side-quests (or even the main quest) make Frodos
journey in the Lord of the Rings trilogy seem like a trip to the corner
store probably wont be something most RPG enthusiasts will take the
time to play through. If youre making your game just for the experience
and its something only you or other people like you will be playing, go
for it.
Usually your game will contain one main quest that is the overall goal of
the game, but along the way the player could undertake many other
different quests. This is a good thing. If your game consists of only
quests where the player acts as a courier or goes on a killing spree, again
you run the risk of not attracting or holding the attention of players for
very long. Mix it up; keep it interesting. If a player gets the opportunity
to accept a quest in the middle of another one, youre making him have
to think and choose, especially if the quest hes on has a time limit or has
an unknown reward. Most RPG players enjoy this; if we wanted
mindless activity wed just play FPS games! A quest has to have a
reward and the _rewardType member indicates what that reward is. It
can be one of five different types:
Listing 10-3

public enum QuestRewardType


{
Armor,

Item,
Money,
Spell,
Weapon
}

The _rewardItemID member is used to indicate the specific item to be


given to the player. This could be a generic item of that type or a unique
item. In the case of money, this member is the amount given to the
player. This member is used in conjunction with the _isRewardShown
member and could be another useful filter for the player if you show the
reward of the quest before the player has to accept it. If its an optional
side-quest and the player cant use the item that hell be given, he could
just ignore the quest and move on to something else. You can also use it
during development of your game to see how many of what types of
items youre offering to the player. If all your quests give out money,
this could be another reason the player gets bored with your game. RPG
players like money, but they also like unique, interesting items as well,
especially if theyre things that cant be bought with the money they
acquire.
The _requiredClasses and _requiredLevel members allow the quest to be
given only to certain characters. If the character doesnt meet these
criteria, the player may not even know certain quests exist, although you
could set it up so that the entity that has the quest says something like
Oh dear, I really need a <some other class than the character>. Would
you happen to know where I can find one? or I dont think youre
ready to undertake such a difficult task. Come back to me when youve
gotten some experience. In the latter case, if you implement a log or
note system, you could allow the player to create a reminder to
himself that the entity has a quest and to come back when hes increased

in level. Note that the _requiredClasses member allows for more than
one type of class to be given the quest. Its simply the names of the
classes separated by a comma. The logic for interacting with entities will
figure out if the character can be presented with the quest.
You could change the way these two members will be used in order to
allow different pairings of class and level. For instance, you could
specify that a low-level fighter can complete the quest, but the same
quest will require a higher level mage. This is a useful thing to
implement and isnt difficult to do, although it will take some effort to
ensure it works nicely.
If the quest is a generic one, you can allow the player to undertake it
more than once by setting the _isMultipleAllowed member to true. This
is usually done for the Item or KillMonster quests since the other two
types rely on something that is probably unique. You could create a
FedEx quest to, say, deliver items from a warehouse to a storekeeper,
however. It all depends on what you want to do. Thats the nice thing
about a flexible system.
If a quest is allowed to be undertaken more than once, the
_timeBetweenQuests member will need to be consulted to determine if
the player can be presented with the task when he interacts with the
entity after completing the quest the first time.
Although time isnt usually a factor in most non-MMORPGs, the
capability to require a quest be completed in a certain amount of time is
there. The _timeLimit member will be used along with two members of
another class to determine if the player has completed the quest in time.
This is actual playing time, not real time.
The _factions member is something I kind of borrowed from the
MMO genre. There are probably single-player RPGs that use this type of
idea, but its widely used in MMOs. A faction can be a race, a group of

entities that belong to a guild or perform a type of job (such as


blacksmiths), citizens of a city or country, or just about anything else
you want to designate as a faction. It could even be every entity in your
game that likes dogs its whatever you decide.
An entity can belong to many factions, just like people in the real world
can belong to many clubs or organizations. Youll have to be careful
with assigning factions to an entity, however. You could end up with a
situation where entities will not associate with the player because the
characters status with one or more factions is not high or low enough to
allow the entities to interact with him. This could lead to the player
being unable to complete the game if interacting with certain entities is
part of the gameplay. This is one area where having a complete design
before you start development would be beneficial. It might not alleviate
all problems, but it could allow you to catch them before you get too far
into development.
The FactionAdjust structure that makes up the items that fill this list is a
simple KeyValuePair where the key is the ID of the faction and the value
is the positive or negative number to add to that entitys score with
that faction upon completion of the quest.
Every interaction with an entity will be preceded by a faction check,
comparing all factions the entity belongs to with the value for the
players character faction. Depending on the value, the entity might not
interact with him or might be very helpful. How the entity reacts is up to
you. The character will start out with this member having no items in it,
which mean entities will interact with the character in whatever way you
set by default. Most entities that are not creatures or monsters will
interact positively, and most creatures and monsters will attack the
character. You can also set up your game with this being switched
around if you want. You would just have to create enough quests to set

the scores for the different factions so that this occurs. This assumes that
the player accepts and completes these quests, of course.
As was noted before, a quest is made up of one or more steps. The _steps
member controls how the quest proceeds, helping to inform the player
what he needs to do to move along in a quest. The QuestStep class that
makes up the items that fill this member looks like this:
Listing 10-4

public class QuestStep


{
private string _stepName;
private int _giveItemIndex;
private int _getItemIndex;
private string _stepEntity;
private InteractionType _stepInteractionType;

// array of IDs of subquests


private List<int> _subQuests;

private List<Item> _requiredItems;

// required level to start the step,


//each step may have a different level
private byte _minimumLevel;

// number of minutes the step can take


private long _timeLimit;

private string _journalEntry;


}

The first five members should be used to create the _journalEntry


member that will be shown in the players quest journal, which you will
have to create as part of your GUI, so that the player knows what to do.
When the step is created in the Quest Editor, the _journalEntry member
will be able to be tweaked so its grammatically correct. This could be
something like Get the key. Talk to Bill. He will give you the key to
return to Bob. The _stepName would be Get the key. The _getItemID
and _giveItemID members would point to an item named key. The
_stepEntity would be Bill and the _stepInteractionType would be
Talk. The only other type of interaction currently is Kill, as can be
seen by looking at the enum:
Listing 10-5

public enum InteractionType


{
Talk,
Kill
}

If the entity for the step is friendly a shopkeeper, town guard,


barmaid, whatever a check is done to see if the entity has a
conversation to start with the character. Well discuss creating these
conversations in the next chapter. The conversation manager will detect
that the character has been assigned a quest and start the conversation to
finish the step.
Like a quest itself, a quest step can contain subquests that have to be
completed before the step can be completed. You may want to do it this

way instead of just having the subquest as additional steps in the quest if
the subquest is one that can be obtained outside of the current quest. An
example is a quest where an entity wants an article of clothing made
from the skin of some type of animal. The character goes to the store to
buy the article, only to find out that the storekeeper doesnt have the
pelts to make the article. The character is then given the subquest to kill
<x> number of that animal and retrieve the pelts. This Kill quest might
also have been something the character could have obtained if hed gone
to the shopkeeper to buy or sell something before hed accepted the
current quest. Completing this subquest would then fulfill the
requirement of the _requiredItems member, the pelts.
While its unlikely that most RPGs would do this, you can include the
ability for a step to require a certain level, just like a quest itself could
require a certain level. The _minimumLevel member allows you to do
this. This level could be any number greater than either the previous step
or the _requiredLevel member of the quest itself.
The _timeLimit member works just like the one for the Quest class. Note
that this value isnt added to the _timeLimit member of the Quest class.
That member should be the time to complete the entire quest. The
elapsed time will be tracked for both the quest and the current step.
When a player accepts a quest, an AssignedQuest object is added to the
_quests list in the Entity object for the character. The AssignedQuest
class looks like this:
Listing 10-6

public class AssignedQuest


{
private int _questID;
private int _curStep;

private long _timeStepStarted;


private long _timeStepFinished;
private long _timeQuestStarted;
private long _timeQuestFinished;
private string _questGiverName;
private bool _questFinished;
}

This class keeps track of the ID of the quest, the current step the player is
on, the time the quest and current step started and finished, the ID of the
entity that gave the player the quest, and whether or not the quest has
been completed. The last member is used instead of just checking the
_timeQuestFinished member because of the possibility of the quest not
being finished. When the _timeStepFinished member is filled in, the
value is compared with the time the step started and then the quest is
checked to see if there was a time limit on the step. If so and the player
exceeded that time, the quest is aborted, setting _questFinished to true
but not filling in the _timeQuestFinished member.

Entity Class Changes


The entity class gets some new members for both the player character
and NPCs:
Listing 10-7

private List<int> _npcQuestIDs;


private List<AssignedQuest> _assignedQuests;

The first member holds the quest IDs for any quests an NPC may have to
give to the player and the second is the list of quests the player has
accepted, which is only used in the player character Entity object. This

list will be iterated through as part of the games update code to check
timing of steps and the overall quest.

Creating Quests
Designing quests is something youll want to give some thought to so
that theyre interesting and challenging, but actually creating them isnt
hard. Its a simple matter of firing up the Quest Editor, filling in some
controls, and saving. The following figure shows the application in the
middle of entering some data for a quest:

Figure 10-1
When you start the application, it will load any existing quests that it
finds in the application folders Quest folder and put the quest names in
the Quests combo box. This means we need another function in the
GlobalFunctions class to handle the loading of the quest data:
Listing 10-8

public static Quest LoadQuest(string filename)


{
XmlSerializer serializer = new
XmlSerializer(typeof(Quest));

try
{
XmlReader reader = XmlReader.Create(new FileStream(
filename, FileMode.Open));

Quest quest =
IntermediateSerializer.Deserialize<Quest>(
reader, null);

reader.Close();

return quest;
}
catch (Exception ex)
{
return null;
}
}

The controls will be empty (the combo boxes will have items in them,
but nothing will be selected). You can start filling them out or select an
existing quest from the combo box and the data for the quest will be
filled in.
Clicking on the button to the right of the Factions Affected list box will
display a small form where you can edit the factions affected by the
quest:

Figure 10-2
If factions already exist, theyll be passed to the form when its created.
Clicking on a faction will display the Adjustment value in the Amount
text box. If you want to change it, simply change the value or clear it out
and go on to the next faction or click the OK button.
In looking at the quest shown in Figure 10-1, we would guess that it
wouldnt make dwarves very happy if they were to find out a character
was killing their kinfolk. In this case the Dwarves faction would get a
negative value for the amount. But if the dwarves were at war with the
goblins (and when arent they in almost every fantasy novel out there?),
the goblins would be happy with the character so that faction would get a
positive value.
The form keeps track of everything thats entered and, when you click
the OK button, the Quest Editor form will get those values and update
the Factions Affected list box.
The data on the Quest Editor form is just that data for the quest itself,
not for the steps that make up the quest. To edit the steps for the quest,
click the Edit Steps button, which displays the following form:

Figure 10-3
Note that any subquests have to be created prior to creating the quest that
uses them in order to populate the Subquests combo box. This should be
obvious, but its worth pointing out. You can always go back and edit a
step that requires subquests, but creating the subquests in advance will
save time, which is always a good thing when developing an RPG if you
havent figured that out by now.
Any items, either for a step or as a reward for the quest, will also have to
be created to populate the Give Item and Get Item combo boxes as well
as those in the Required Items area.
Make sure the Journal Entry data is clear and concise. The player will
probably be depending on it to remind him what he has to do, especially
if he has several quests going on at once.

Summary
Im sure you have a lot of ideas for exciting, challenging, and fun quests
and are anxious to get started creating them. Remember to take time
when designing them as theyre arguably the most important part of an
RPG. Before you go rushing out to create the next Fellowship of the
Ring quest, you might want to check out the next couple of chapters,
especially since the next one will help you give voice to your quests by

explaining the building of conversations. Players will have to interact


with NPCs in order to get to all the quests you have in your head, and
conversations are the best way to interact with them.

Chapter 11
Conversations/Scripting
When a player starts up an RPG, he expects a vibrant, living, breathing
world populated by people and creatures that he can interact with. These
interactions could include holding a conversation with an NPC or
fighting a monster. If a character were to walk up to a bartender, he
would expect to be able to order a drink and get the latest information
about what has been happening in the area. The same holds true for
being able to interact with a blacksmith to repair equipment, a
shopkeeper to buy supplies, or any other NPC. If the person just stands
there when the character tries to talk to him, it becomes obvious that the
NPC isnt a person at all, but just a graphic being drawn on the screen.
This breaks the immersion a player expects from an RPG. Fortunately,
with scripting its possible to simulate living beings to some degree. You
wont be able to discuss philosophy or politics with people or have a
creature that is very smart in its combat tactics, but youll be able to have
a degree of interaction, which goes a long way in making a game
interesting.
In this chapter, well construct and discuss a conversation editor and the
associated classes. Conversation scripts will allow the character to talk to
NPCs. This is normally done so that quests can be assigned, but they can
also be used just to make an NPC react to the character. Figure 111 shows the completed editor:

Figure 11-1

The Conversation Class


As with most things, we start with a class to encapsulate the data well
be using for our conversations:
Listing 11-1

public class Conversation


{
private int _id;

[NonSerialized]
private int _idCounter = 0;

private List<ConversationNode> _nodes;

[NonSerialized]
private ConversationNode _curNode;

public Conversation()
{
}

public int ID
{
get { return _id; }
set { _id = value; }
}

public ConversationNode CurNode()


{
return _curNode;
}

public List<ConversationNode> Nodes


{
get { return _nodes; }
set { _nodes = value; }
}

public void Initialize()


{
//assume the first node is the start of the
conversation
_curNode = _nodes[0];
}

public string GetNodeText()


{
return _curNode.Text;
}

public List<ConversationNode> GetResponses(int id)


{
ConversationNode node = null;

foreach (ConversationNode child in _nodes)


{
if (child.ID == id)
{
node = child;
break;
}
if (child.Responses.Count > 0)
{
node = FindNodeByID(child, id);
if (node != null)
break;
}
}

return node.Responses;
}

public void SelectNode(int id)


{

foreach (ConversationNode child in _nodes)


{
if (child.ID == id)
{
_curNode = child;
break;
}
if (child.Responses.Count > 0)
{
_curNode = FindNodeByID(child, id);
if (_curNode != null)
break;
}
}
}

public void SelectResponse(int id)


{
//figure out which node should be the current one
foreach (ConversationNode child in
_curNode.Responses)
{
if (child.ID == id)
{
_curNode = child;
break;
}
}
}

public void AddNode(ConversationNode node, int


parentNodeID)
{
//find the node
foreach(ConversationNode child in _nodes)
{
if (child.ID == parentNodeID)
{
child.Responses.Add(node);
break;
}

ConversationNode parent = FindNodeByID(child,


parentNodeID);
if (parent != null)
{
parent.Responses.Add(node);
break;
}
}
}

public int AddNode(string text, FunctionType


functionType,
string functionText, CaseType caseType, string[]
paramText)
{
_idCounter++;

ConversationNode node = new


ConversationNode(_idCounter);

node.Text = text;
node.NodeFunction = functionType;
node.NodeCaseType = caseType;
node.FunctionName = functionText;
node.FunctionParams = paramText;

_nodes.Add(node);

return _idCounter;
}

public int AddNode(int parentNodeID, string text,


FunctionType functionType, string functionText,
CaseType caseType, string[] paramText)
{
_idCounter++;

ConversationNode node = new


ConversationNode(_idCounter);

node.Text = text;
node.NodeFunction = functionType;
node.NodeCaseType = caseType;
node.FunctionName = functionText;
node.FunctionParams = paramText;

AddNode(node, parentNodeID);

return _idCounter;
}

ConversationNode FindNodeByID(ConversationNode node, int


id)
{
ConversationNode parent = null;

foreach (ConversationNode child in node.Responses)


{
if (child.ID == id)
{
parent = child;
break;
}

if (child.Responses.Count > 0)
{
parent = FindNodeByID(child, id);
if (parent != null)
break;
}
}

return parent;
}

public bool CurNodeHasPreFunction()


{
return _curNode.NodeFunction ==
FunctionType.PreFunction;
}

public string GetPreFunction()


{
if (CurNodeHasPreFunction())
return _curNode.FunctionName;
else
return "";
}

public bool CurNodeHasPostFunction()


{
return _curNode.NodeFunction ==
FunctionType.PostFunction;
}

public string GetPostFunction()


{
if (CurNodeHasPostFunction())
return _curNode.FunctionName;
else
return "";
}
}

Each conversation will have a unique ID that can be attached to an entity


to allow that entity to start the conversation when the player interacts
with him. An entity could have more than one conversation attached to
him for different things, such as multiple quests. Youd have to write
logic to determine which quest to offer, but thats easy enough,
depending on the quests. If all the conversations are for quests and the
character is qualified to undertake all of them, simply generate a random
number. If you want to get more complicated, such as offering different
quests based on the character (a different quest depending on
the characters class, for example), youd probably want to write a
manager of some sort that knows what kinds of quests the NPC has to
offer and what their requirements are. For our purposes though, such
logic isnt really related to a conversation itself, so were not going to
get into that.
A conversation is basically just a hierarchy of responses based on certain
conditions. Those conditions are wrapped up in the ConversationNode
class:
Listing 11-2

public class ConversationNode


{
private int _id;
private string _text;
private FunctionType _functionType;
private string _functionName;
private string[] _functionParams;
private CaseType _case;

private List<ConversationNode> _responses;

public ConversationNode()
{

public ConversationNode(int id)


{
_id = id;
_responses = new List<ConversationNode>();
}

public int ID
{
get { return _id; }
set { }
}

public string Text


{
get { return _text; }
set { if (!string.IsNullOrEmpty(value)) _text =
value; }
}

public FunctionType NodeFunction


{
get { return _functionType; }
set { _functionType = value; }

public string FunctionName


{
get {return _functionName;}
set
{
if (_functionType != FunctionType.FunctionNone)
if (!string.IsNullOrEmpty(value))
_functionName = value;
}
}

public string[] FunctionParams


{
get { return _functionParams; }
set
{
if (_functionType != FunctionType.FunctionNone)
if (value != null)
_functionParams = value;
}
}

public CaseType NodeCaseType


{
get { return _case; }
set { _case = value; }
}

public List<ConversationNode> Responses


{
get { return _responses; }
set { _responses = value; }
}

public void AddResponse(ConversationNode node)


{
_responses.Add(node);
}

public void RemoveResponse(int index)


{
_responses.RemoveAt(index);
}

public void UpdateResponse(int index, ConversationNode


node)
{
_responses[index] = node;
}
}

Each node in the conversation has its own ID, mainly for determining
where in the conversation the two entities are currently or previously (in
the case of a conversation spanning completing a quest, which well get
to in Chapter 13). The text is whats displayed to the player. The three
function x properties are used to determine what course the conversation
takes. The same conversation could happen more than once and the

conditions are used to keep the conversation from being repeated exactly
the same each time or to keep the NPC from giving incorrect responses.
The _functionType property can have one of three values:
Listing 11-3

public enum FunctionType


{
FunctionNone,
PreFunction,
PostFunction
}

A node in the conversation can be set to have a check done before being
displayed, allowing you to filter responses based on selected criteria (a
PreFunction) or to have a check done if the player selects the response (a
PostFunction).
The _functionName property determines what function is called.
Currently, this is somewhat hard-coded to be one of the following:
Listing 11-4

public enum ConversationFunctions


{
FirstTime,
HasQuest,
AssignQuest,
QuestAssigned,
CheckForQuestCompletion,
CompleteQuest
}

Heres a summary of what each of these functions does:


FirstTime This function is called to determine if the current
interaction between the NPC and the character is their first ever
interaction. This function will always be used as a PreFunction. Most
conversations, at least the ones that involve quests, will have the
function called in the first node of the conversation. In the editor
screenshot shown in Figure 11-1, the node with the text Hello uses this
function. If the interaction is the first between the two, this is the node
thats displayed. The check is a simple one:
Listing 11-5

public bool FirstTime(int id)


{
return HasPlayerTalkedToNPC(id);
}

public bool HasPlayerTalkedToNPC(int id)


{
return _NPCsTalkedTo.IndexOf(id) != -1;
}

_NPCsTalkedTo is a List<int> in the entity class. After every


conversation, the NPCs ID member is added to the list if its not already
there.
HasQuest Continuing along the Hello node, if the player selects
the response Do you have a quest for me? this function is called since
that response has a PostFunction that calls this function. The NPC
checks to see if it has any quests that the character is qualified to
undertake, and depending on the return value of the function, displays

one of the two responses. Since were not doing any checking of this
type, the function simply checks to see if the NPC has at least one quest:
Listing 11-6

public bool HasQuest()


{
return _questIDs.Count > 0;
}

_questIDs is another List<int> that provides indexes into the global list
of quests that would be created using the Quest Editor from the previous
chapter.
AssignQuest Almost self-explanatory. If the NPC has a quest and
the player agrees to undertake it, this function is called. Its passed a
couple of parameters to make sure the quest can be kept track of:
Listing 11-7

public void AssignQuest(int questID, int npcID, long


startTime)
{
AssignedQuest quest = new AssignedQuest();

quest.QuestID = questID;
quest.CurStep = 1;
quest.TimeStepStarted = startTime;
quest.TimeQuestStarted = startTime;
quest.QuestGiverID= npcID.ToString();
quest.QuestFinished = false;

_quests.Add(quest);
}

QuestAssigned This function checks to see if the quest associated


with the conversation has already been assigned to the character:
Listing 11-8

public bool QuestAssigned(int id)


{
bool ret = false;

foreach (AssignedQuest quest in _quests)


{
if (quest.QuestID == id)
{
ret = true;
break;
}
}

return ret;
}

CheckForQuestCompletion This function checks to see if the quest


associated with the conversation has been completed by the character so
that the NPC can give the character the reward for the quest. It looks
almost exactly like the QuestAssigned function, except it has two
additional checks:

Listing 11-9

public bool CheckForQuestCompletion(int id)


{
bool ret = false;

foreach (AssignedQuest quest in _quests)


{
if (quest.QuestID == id &&
quest.CurStep ==
GlobalData.Quests[id].Steps.Count-1 &&
quest.TimeStepFinished > 0)
{
ret = true;
break;
}
}

return ret;
}

CompleteQuest This function is called if the


CheckForQuestCompletion function returns true. It marks the quest as
completed and puts the quest reward in the characters inventory:
Listing 11-10

public void CompleteQuest(int id, long timeFinished)


{

foreach (AssignedQuest quest in _quests)


{
if (quest.QuestID == id)
{
quest.TimeQuestFinished = timeFinished;
_inventory.Items.Add(GlobalData.Items[
GlobalData.Quests[id].RewardItemID]);
}
}
}

The value of the _functionParams member is dependent on the type of


function the node calls. For the quest-related functions, this is the ID for
the quest and possibly other quest data the NPC or character ID, the
ID of the quest reward, etc. For the FirstTime function, its the ID of the
NPC. Its up to the developer to know the order and types of data that
each function uses. The data is separated by the pipe character (|) as its
a fairly safe bet that its never going to be used in data, unlike the
comma, semicolon, or other characters that you normally find in
delimited data.
When an NPC asks a question such as Did you finish the quest? we
cant just take the players word for it that hes done; we need to check.
Thats the purpose of the _case member. It allows us to call a function to
check whether or not the player is telling the truth when he responds to a
question like this in the positive. In the case of completing a quest, the
CheckForQuest-Completion function is called. This can be used for
anything, however; you just need to add to the ConversationFunctions
enum the appropriate function to be called and add the logic to call it.
The CaseType enum has only three values:
Listing 11-11

public enum CaseType


{
CaseNone,
CaseTrue,
CaseFalse
}

It would be easy enough to expand this to allow the selection of one of


three or more responses, in which case you could eliminate the enum and
simply use an integer if you want to keep the number of responses openended. If you decided to limit the number of responses to a set number,
you could keep the enum and simply change it to something like:
Listing 11-12

public enum CaseType


{
None,
Response1,
Response2,
Response3,
Response4,
...,
}

You would only do this if you needed to call a function with some of the
responses, however. Thats the only reason for needing the CaseType.
Otherwise, you would just construct your conversation nodes as normal.
Thats really all there is to the conversation code. Well need some code
to manage conversations, though, so that we can test them and have

them work the same during the test as they will in a game. Lets take a
look at the ConversationManager class that will do that.

Testing the Conversation


Since you dont want to have to fire up your game every time you create
a conversation (at least I dont), it makes sense to have the ability to
abstract the conversation playing code so you can use it anywhere. The
code to manage the conversation would just have methods to call to
select a response, show the responses for a node, etc. The
ConversationManager class does this, and the code for this chapter
includes a Windows Form application that uses the class to test out
conversations. You just give the form the NPC and player character
Entity objects and the Conversation object, and it loads the manager and
starts up the conversation. Select the response for each node and it does
the necessary checking to show the proper node for each response. For
things like checking to see if the player has a quest item, you would have
to modify the player data, but since the form uses the LoadEntity
function, you simply modify the XML file for the player. In the game,
the compiled version of the player file is used with the ContentManager,
so you wont be able to modify the file by hand as you can with the
XML version.
Heres the conversation test form at the start of the conversation weve
been working on:

Figure 11-2
Heres the code behind the form. Some of the functionality will be
reused in the games GUI once its created:
Listing 11-13

public partial class ConversationTestForm : Form


{
Conversation _conversation;
Entity _player, _npc;

ConversationManager _manager;

List<ConversationNode> _responses;

public ConversationTestForm(Conversation conversation,


Entity npc,
Entity playerCharacter)
{

InitializeComponent();

_conversation = conversation;

_player = playerCharacter;
_npc = npc;

_manager = new ConversationManager(_conversation,


_player, _npc);

private void btnStart_Click(object sender, EventArgs e)


{
lblTest.Text = _manager.Start();

_responses = _manager.GetResponses();

SetResponses();
}

private void SetResponses()


{
//wipe out controls in group box and recreate
grpResponses.Controls.Clear();

Button btn;

foreach (ConversationNode node in _responses)

{
btn = new Button();
btn.Text = node.Text;
btn.Width = TextRenderer.MeasureText(btn.Text,
btn.Font).Width +
20;
btn.Click += new EventHandler(btnResponse_Click);
btn.Tag = node.ID.ToString();
btn.Location = new Point(10,
(grpResponses.Controls.Count *
btn.Height) + (15 *
grpResponses.Controls.Count) + 15);

grpResponses.Controls.Add(btn);
}

private void btnClose_Click(object sender, EventArgs e)


{
this.Close();
}

private void btnResponse_Click(object sender, EventArgs


e)
{

_manager.SelectResponse(Convert.ToInt32(((Button)sender).Tag)
);

List<ConversationNode> responses =
_manager.GetResponses();

lblTest.Text = "";

if (_manager.GetCurNode().NodeFunction ==
FunctionType.PostFunction)
{
switch (_manager.GetCurNode().FunctionName)
{
case "HasQuest":
{
if (_npc.HasQuest())
{
//filter responses
foreach (ConversationNode response in
responses)
{
if (response.NodeCaseType ==
CaseType.CaseTrue)
{

_manager.SelectResponse(response.ID);
lblTest.Text = response.Text;
}
}
}
else

{
foreach (ConversationNode response in
responses)
{
if (response.NodeCaseType ==
CaseType.CaseFalse)
{

_manager.SelectResponse(response.ID);
lblTest.Text = response.Text;
}
}
}

_responses = _manager.GetResponses();

SetResponses();

break;
}
case "AssignQuest":
{
_player.AssignQuest(Convert.ToInt32(

_manager.GetCurNode().FunctionParams[0]),
_npc.Name, 0);

break;
}

case "CheckForQuestCompletion":
{
//filter responses
foreach (ConversationNode response in
_responses)
{
if (response.NodeCaseType ==
CaseType.CaseFalse &&
!_player.CheckForQuestCompletion(

Convert.ToInt32(response.FunctionParams[0])))
{

_manager.SelectResponse(response.ID);
lblTest.Text = response.Text;
}
else if (response.NodeCaseType ==
CaseType.CaseTrue
&&
_player.CheckForQuestCompletion(

Convert.ToInt32(response.FunctionParams[0])))
{

_manager.SelectResponse(response.ID);
lblTest.Text = response.Text;
}
}

responses = _manager.GetResponses();

SetResponses();

break;
}
}
}
else
{
_responses = new List<ConversationNode>();

SetResponses();
}
}
}

The first time you test the conversation, the FirstTime function that is the
PreFunction for the first node in the conversation will return true, setting
the current node to the first node and displaying the text for the node.
The responses for the first node are returned by the call to GetResponses,
and buttons are dynamically created and the response text is used to set
the buttons Text property. A Click event handler is added to each button
in the list of responses to handle the selected response. All the buttons
use the same handler. The code in the event uses the sender object to get
the selected response.
When you click the Start button, the ConversationManagers Start
method is called to get the starting node. In most conversations this is
going to be the first node, but it doesnt have to be. The responses for

that node are then retrieved and used to create the buttons that you use to
select a response.
When you click a response, the Tag property of the button is issued to
get the selected response and continue the conversation. The selected
response is checked to see if theres a PostFunction attached to it and, if
so, calls it to resolve what node to show next, if any.
The ConversationManager is fairly small:
Listing 11-14

public class ConversationManager


{
Conversation _conversation;
Entity _player, _npc;

ConversationNode _curNode;

public ConversationManager(Conversation conversation,


Entity player,
Entity npc)
{
_conversation = conversation;
_player = player;
_npc = npc;
}

public string Start()


{
string text = "";

_conversation.Initialize();

_curNode = _conversation.GetCurNode();

while (text == "")


{
text = CheckForStartNode();

if (text == "")
_curNode = _conversation.GetNextSibling();
}

return text;
}

private string CheckForStartNode()


{
string text = "";

//Make sure initial node is the correct one


//check for PreFunction and verify conditions
if (_curNode.NodeFunction ==
FunctionType.PreFunction)
{
switch (_curNode.FunctionName)
{
case "FirstTime":
{
if

(!_player.HasPlayerTalkedToNPC(_npc.Name))
text = _curNode.Text;

break;
}
case "QuestAssigned":
{
if
(_player.QuestAssigned(Convert.ToInt32(
_curNode.FunctionParams[0])))
text = _curNode.Text;

break;
}
case "CheckForQuestCompletion":
{
if
(_player.CheckForQuestCompletion(Convert.ToInt32(
_curNode.FunctionParams[0])))
text = _curNode.Text;

break;
}
}

}
else
text = _curNode.Text;

return text;
}

public List<ConversationNode> GetResponses()


{
List<ConversationNode> responses = new
List<ConversationNode>();

responses = _conversation.GetResponses(_curNode.ID);

//filter responses
foreach (ConversationNode response in responses)
{
if (response.NodeFunction ==
FunctionType.PreFunction)
{
switch (response.FunctionName)
{
case "FirstTime":
{
if
(_player.HasPlayerTalkedToNPC(_npc.Name))
responses.Remove(response);

break;
}
case "QuestAssigned":
{
if

(!_player.QuestAssigned(Convert.ToInt32(
response.FunctionParams[0])))
responses.Remove(response);

break;
}
}
}
}

return responses;
}

public void SelectResponse(int id)


{
_conversation.SelectNode(id);
_curNode = _conversation.GetCurNode();
}

public ConversationNode GetCurNode()


{
return _curNode;
}
}

The biggest chunk of code is that which gets the responses for the
current node (the current node is what the NPC is saying). It has to
resolve any PreFunction criteria to determine what responses are valid to
return. The PreFunction criteria is also used to determine the initial
response for the NPC at the beginning of the conversation.

Summary
Were now into the home stretch. With everything thats been discussed
to this point, you have all the knowledge you need to put together a basic
single-player RPG. Whats that you say? What if you want to create an
RPG you can play with a friend? Hmmm, good question. Tell you what
turn to the next chapter and well see what kind of information we
can dig up on the issues involved with creating multiplayer RPGs and
what the XNA Framework and XNA Game Studio can do to help you
create one.

Chapter 12
Multiplayer Considerations
So there you are, alone in a dungeon and you realize that youre in an
area thats just a bit out of your league. Its time to call in the
reinforcements. You head back to town and stop by the local tavern
where you post a notice for other adventurers, letting them know what
youre planning and that you need some help. You stop by the next day
and there are a couple of people who saw your notice and would like to
join you, for a cut of the treasure that you recover, of course.
Adding multiplayer capability to a game is almost a requirement these
days. It used to be that adding multiplayer functionality was extremely
difficulty to do well. Part of that was an Internet that was young and not
quite up to the task of handling all the data that was passed through it,
resulting in gameplay that was less than ideal. With broadband
connections accessible to almost everyone at relatively cheap prices, its
become more expected to have some sort of multiplayer capability in
most games.

In this chapter, well discuss various ways to offer a multiplayer


experience in your game and briefly look at the functionality thats
offered by the XNA Framework for implementing such an experience.

Whos the Boss?


There are two components to a multiplayer game from an application
standpoint the server and the client. These two components can be in
the same executable or in separate executables, running on the same
machine or different machines. A server isnt always necessary before or
during the game, but you need something to find other players over the
Internet. On a local network or the Xbox LIVE network, a server isnt
necessary as clients can find one another easily. In addition, one of the
clients may act as the host before and during the game.
The host is one of the players who basically says to the world, Im
having a party, come on in and join the fun. That player hosts the party,
in other words. The host can have limited or total control over the way
the multiplayer aspect of the game functions. He can allow certain
people to join the game, refuse entry to others, or kick current players
out of the game. The exact functionality the host is given depends on the
developer. A typical setup for a game that uses this type of architecture
would be something like the following:

Figure 12-1
This is known as a peer-to-peer type of setup. Once the game is started,
every player will send all the necessary messages to every other player.
Any validation of data is done on every client. Its not the most secure
method, but its less work than writing a separate server application.
The server is the component that controls the gameplay to a certain
extent and allows clients to join. Its usually a separate piece of software
from the game application in order to keep it free from the prying eyes of
players seeking an exploit. The person controlling the server usually can
set certain options of the game time limits, the number of people that
can join, victory conditions, etc. The server is the boss. It enforces the
rules of the game and can set up certain rules the way it wants. The setup
for this type of architecture would look like this:

Figure 12-2
In some cases the server could be running on the same machine as a
player that is connecting to it. Such a setup would look like this:

Figure 12-3
The server controls communication between the players, passing
messages to the proper parties and sending out its own messages as
needed, such as notifying players when someone joins or leaves the
game. It validates player movements and changes what a player has tried
to do if it violates the games rules. You can think of part of the servers
responsibility as a referee at a sporting event.
If the server is the referee, the clients are the players, doing what the
server tells them when necessary, but otherwise playing the game the
way they want. The client doesnt know anything about the way the

multiplayer aspect of the game works; it just knows how to join and quit
a game and how to send and receive messages, either to other players or
through the server. It usually doesnt verify any messages it receives; it
just accepts them and continues doing what it was doing. It relies on the
server to make sure the other players are doing what they say theyre
doing.
So now we know what our options are from an architectural standpoint.
The various types of multiplayer games that can be created will use one
of these types of architectures. Which one is up to you. Some pairings
will make more sense than others once you look at them both.

Multiple-Player Party
The multiplayer party is the example that was used at the beginning of
the chapter, but it could also be random people that get together in a
game lobby or even in the game in the case of an MMORPG. This type
of game can use any of the network architectures, which in most cases
will determine how the players can find one another and join together.
Lionhead Studios added a multiplayer component to the sequel to its
mega-hit Fable. Fable 2 allows a player to jump right into a friends
game over Xbox LIVE, through System Link, or on the same console.
There are restrictions to this (for example, the joining player has to use a
premade character, not one he uses when he plays his single-player
game), but it at least allows players to have fun together. The player
hosting the game can set various rules how to split loot that is gained
between the players, whether friendly fire is active, etc.
Here are some other things youll need to consider when setting up a
multiplayer party type experience:
How is experience split between players? Do you split it equally? If
so, is a player that does 95% of the damage to an enemy or takes 95% of

the damage an enemy inflicts on the party (think MMORPG tank type
character, whose job is to take the punishment his character is built for
so others who cant take it dont have to) going to complain about how
unfair the experience is split? If you try to make it fair, youre adding
more code to do the calculations and thus more testing.
Its almost inevitable that a player will find loot that he cant use but
another player can. How do you handle getting the item from one player
to another? Do you force the player with the item to drop it and the other
player to pick it up? This is probably not the best solution. Do you allow
the player with the item to drag it from his inventory onto the other
players character? That would be nice, but now you need to implement
functionality to recognize when this occurs, which potentially opens up a
whole new can of worms. You would probably want to implement a
trade dialog of some kind, which means you need to plan for the
additional coding and testing that will be required. If you have a dialog
thats used for buying items from and selling items to an NPC
shopkeeper, you might be able to reuse it and cut down on the coding,
but it will have to be tested in both cases.
How do you handle level disparities between characters? If you allow
characters with a sizable level gap between them in the same party, you
could end up with the experience being too easy or too hard for players.
You could dynamically generate enemies that are of a level thats the
average of the entire party, but again youre adding more code to do so,
which takes more development time and means more testing. Are you
noticing a pattern here? The more functionality you add to your game,
the more time youll need to allocate for development and testing. This
might seem obvious, but its something you always need to keep in
mind.

How do you handle loot? If you are dynamically generating items,


youll need to verify that there are roughly the same number of items
that can be used by all the characters. You could add a check to the
levels that are used in your multiplayer game so that theyre designed
around a minimum and maximum level. This is a nice solution in that it
removes some of the headaches associated with level disparity. It doesnt
take much more code to do this than to just build levels generically,
either.
How do you handle alignment differences between party members?
Do you allow evil characters to join with good characters? If so, how
does this change the game experience? If you have an evil character as
part of the party, hes probably going to want to be able to do things that
the rest of the party disagrees with, so hell want to be able to do them
without the party noticing. A thief will probably want to be able to steal
without the rest of the party being informed. He may even want to be
able to steal from party members! Obviously you would want to give the
party members a chance to notice this theft, with perhaps a greater
chance of noticing it if its from another player rather than an NPC.
What happens if a player notices this? Do you allow the other players to
kick the thief out of the party? If so, what happens to him? Can he still
play the game in the same session, perhaps trailing the party and
harassing them?
What if the evil character is an assassin type character and wants to be
able to kill the other party members and steal their loot? If you dont
allow this, youre potentially alienating a percentage of players. If you
do allow it, you could end up having to deal with griefing.
Griefing: Playing a game in a way thats meant to simply aggravate and
harass other players. This type of play is normally associated with
MMORPGs.

Normally RPGs that use an alignment system have penalties or bonuses


for players that actually play the game as their character would act. If
you allow conflicting alignments within a party, what is this going to do
to your system?
RPGs are considered one of the hardest types of games to create, mainly
because the action is supposed to take place in a living, breathing world.
Its difficult enough to try to anticipate what one player will do, let alone
an entire party. Not only could the party members be affecting the world
in ways the designer didnt think about, the party members could be
affecting one another.

GM-Controlled Game
There have been several computer games where one person takes the
role of the GM (Game Master), making the game more dynamic and
adaptive to the players and their actions. Vampire: The Masquerade
Redemption, published in 2000 by Activision and developed by
Nihilistic Software, featured a multiplayer mode that allowed one person
to become the Storyteller, changing the game as necessary to adapt to the
players and keep it interesting and challenging.
Neverwinter Nights had a dungeon master client feature that gave a
person complete control over the server portion of the game that allowed
people to join a semi-persistent world. A key piece of the DM client was
the ability for the DM to take control of an NPC, helping to make the
game seem more realistic by responding to players as they would expect
them to and engaging them directly in order to further the adventure in
case the players had strayed too far afield.
A GM-controllable game is much more difficult to create and test than a
multiplayer party game. Each piece of functionality that you allow the
GM to have adds another layer of complexity to the game. What if the
GM spawns dozens of high-level monsters? Can your game handle the

additional rendering and AI requirements? What if the GM takes control


of a monster; does your AI for that entity stop running and start back up
when he relinquishes control?

Players as Both Good and Bad Entities


The recently released Left 4 Dead takes the multiplayer experience one
step further by allowing a player to become one of the many zombies
that the group of human players have to take on during the game. Not
only can players become normal zombies, but they can also control one
of the several types of boss-type creatures that the game features.
Although its not an RPG, it offers a type of gameplay that can be used
in a multiplayer RPG.
In RPGs you normally dont see players taking the role of one of the bad
guys (unless its part of the storyline), but it could be very interesting to
change things up and give them this ability. There are a lot of ways this
could be done. Here are a few:
Two groups of players, one good and one bad, race for a weapon of
ultimate power. Obstacles that stand in the way would be tailored to each
group and force the group to make decisions based on their alignment
that would shorten the journey to the goal but negatively affect their
characters. (The evil group has to help out someone to get a piece of the
puzzle that shows where the weapon is, and the good group has to kill
someone in cold blood.)
Plain deathmatch type gameplay where experience and/or money is
made (think Gladiator Arena).
An assault type game where one group defends a base or some area
and another group has to assault and take it over.
The last two are first-person shooter types of multiplayer gaming, but I
think they can be adapted to RPG play with little problem.

This is one area that RPGs typically havent gotten into, but coming up
with a solid game that has a unique feature like this would increase the
chance of your game doing well.

Setting Up for Multiplayer


There are a couple of decisions you have to make in deciding which API
to use to implement your networking functionality. The .NET
Framework comes with all the functionality you would need to create a
multiplayer game, but if you want to submit your game to the Xbox
LIVE Community Games system you have to use the network
functionality specifically provided in the XNA Framework. While this
means you have an instant audience of millions of gamers, it does limit
you somewhat for a PC version of the game. The Games for Windows Live functionality is not included in the redistributable of the XNA
Framework, which means that any PC that attempts to play a game that
uses the functionality must have XNA Game Studio installed or have
another game installed that uses Games for Windows - Live (not many at
this time). Furthermore, the profile that is signed in must be tied to a
Creators Club membership.
If you want to release a strictly local network game that uses system link
networking for the PC, theres nothing required in terms of extra
software installed on the players PC or memberships. This limits your
audience on the PC side, however.
Another alternative is to use the Live network for your Xbox 360 version
of the game and give the player the option of Games for Windows - Live
or another networking library for the PC. If you have the knowledge and
time to implement something like this, its a great alternative.

For our purposes well assume that the Live networking is enough and
well discuss various issues related to it. That said, theres a lot to
consider so lets jump right in.

Getting Started
Before any kind of networking can be done, the gamer services system
must be initialized. The gamer services system provides access to the
messages that the Guide raises, such as sign-in status changes and game
invitations. Since a player has to be signed in to play an XNA
Framework game, hell have to have access to the Guide, and in order to
have access to the Guide, the system that provides access to it has to be
active. Fortunately, its extremely simple to get the service up and
running:
Components.Add(new GamerServicesComponent(this));

Thats it were done. By adding an instance of the


GamerServicesComponent to the games Components list, we get the
benefit of having the services Update method called automatically.
If youre not using the XNA Framework application model or
component infrastructure, you can use the GamerServicesDispatcher
class. In this case, youll have to do a little extra work. First, some
initialization, best done in your startup code:
Listing 12-1

protected override void Initialize()


{
GamerServicesDispatcher.WindowHandle = Window.Handle;

GamerServicesDispatcher.Initialize(Services);

base.Initialize();
}

Youll then need to call the Update method of the class once per frame:
Listing 12-2

protected override void Update(GameTime gameTime)


{
GamerServicesDispatcher.Update();
base.Update(gameTime);
}

A game can now call any networking API function without an exception
being thrown.

In-Game Chat
Being able to communicate with the other players in a group is important
to ensuring the group survives in places like dungeons or any combat
situation. If the group has no way of communicating and all but one of
the group decides to run from an encounter, the remaining player is
probably going to be pretty upset to find himself facing a horde of
monsters by himself.
Having to type to communicate is one option, but can be problematic in
combat when a player has to concentrate on the enemy hes facing. A
multiplayer game cant be paused like a single-player game to type a
message to the other players. Providing this functionality is fine, but
having another solution would be ideal.
Luckily, voice support in XNA Framework games comes free of charge.
The voice data is automatically transmitted and replayed without having
to write one line of code. There are a couple of pieces of data that have
to be checked, however:

Are the players allowed to send and receive communications using


voice, text, messaging, or game invites?
If GamerPrivileges.AllowCommunication is set to false the XNA
Framework will automatically take care of disabling voice chat in game.
Do they have voice access?
NetworkGamer.HasVoice will be set to false if the player doesnt have a
headset. You might want to note this in-game somehow. There are icons
available on the Creators Club web site that can be used. A couple of
examples are shown in the following figure:

Figure 12-4
Are they currently talking?
If the player is currently talking (NetworkGamer.IsTalking) you could
use something like one of the icons shown above or highlight the player
in the games GUI.
Are they muted?
If you dont let the other players know a person is muted
(NetworkGamer.IsMutedByLocalUser) they could talk to the muted
player and if dont get a reply they may think something is wrong with
the game.
If you want to enable things like team chat or in-game location-based
chat theres the LocalNetworkGamer.EnableSendVoice method.

I sense a presence
So gamers are playing your game and their friends want to know exactly
what theyre doing in the game. If youve ever played on Xbox LIVE,
you know that your Friends List will have text next to a friend like

Playing Rock Band 2 - Band Quickplay - Smile Like You Mean It.
This is called Presence information.
Each game sets and displays pieces of the information during the game
to reflect whats going on. The first piece of information is set
automatically. The second and third pieces are general and specific,
respectively, and are set by the developer. Games created using the XNA
Framework also have the ability to specify information like this, but in a
limited fashion. Because XNA Game Studio games are not certified, any
information thats displayed has to be limited to something that would
fall under what would be a rating of E - Everyone. In order to be certain
that this is the case, Microsoft has provided a list of strings that can be
displayed, some with values that can be provided by the developer.
The Figure 12-5 shows the current list from which the developer can
select.
The first two lines of displayed information will be set to Xbox LIVE
Community Game and the games title, and the item will be displayed
on the third line. The following items can specify a value along with the
text by setting the PresenceValue property of the GamerPresence class:
GamerPresenceMode.Stage
GamerPresenceMode.Level
GamerPresenceMode.Score
GamerPresenceMode.CoopStage
GamerPresenceMode.CoopLevel
GamerPresenceMode.VersusScore

Figure 12-5
To set the gamers presence, you would do something like the following:
Listing 12-3

foreach (SignedInGamer signedInGamer in


SignedInGamer.SignedInGamers)
{
signedInGamer.Presence.PresenceMode =
GamerPresenceMode.InCombat;
}

Session Management

Before any multiplayer game can begin, there has to be a session for the
players to join. As there are several reasons that creating a session could
fail, it would be a good idea to trap for them, as the following code
shows:
Listing 12-4

void CreateSession(NetworkSessionType sessionType)


{
try
{
IAsyncResult asyncResult =
NetworkSession.BeginCreate(sessionType, 1,
World.MaximumPlayers, null, null);

}
catch (NetworkException ne)
{
System.Console.WriteLine("Failed to create session: "
+
ne.Message);
}
catch (GamerPrivilegeException gpe)
{
System.Console.WriteLine(
"Insufficient privilege to create session: " +
gpe.Message);
}
}

The NetworkSessionType variable can be one of four values:

Local
SystemLink
PlayerMatch
Ranked
Note that the Ranked value is only used for commercial games that have
earned Xbox LIVE certification.
If you want to be notified when the session is created, you can pass in a
callback as the fourth argument of the BeginCreate function. The object
returned from the call to BeginCreate can be used to monitor the
progress of the session creation, however.
You can simply check it each call to the Update method to see if its
finished:
if ((asyncResult != null) && asyncResult.IsCompleted)

Once the session is created, youll want to save the session object for
future use and set some properties for it:
Listing 12-5

void SessionCreated(object sender,


OperationCompletedEventArgs e)
{
NetworkSession networkSession = null;
try
{
networkSession =
NetworkSession.EndCreate(e.AsyncResult);
}
catch (NetworkException ne)

{
System.Console.WriteLine("Failed to create session: "
+
ne.Message);
}
catch (GamerPrivilegeException gpe)
{
System.Console.WriteLine(
"Insufficient privilege to create session: " +
gpe.Message);
}
if (networkSession != null)
{
networkSession.AllowHostMigration = true;
networkSession.AllowJoinInProgress = false;
}
}

At this point you can display a screen to let the player who has created
the session wait to see if any players join the session. You would also
allow them to indicate that theyre ready for the game to start. See the
following figure for an example of a screen like this from the Net
Rumble Starter Kit:

Listing 12-6
In order for other players to find this session, they have to be given an
interface to see the available sessions. The code to do this looks
suspiciously familiar:
void FindSession(NetworkSessionType sessionType)
{
try
{
IAsyncResult asyncResult =
NetworkSession.BeginFind(sessionType, 1, null,
null, null);
}
catch (NetworkException ne)
{
System.Console.WriteLine("Failed to search for
session: " +
ne.Message);
}
catch (GamerPrivilegeException gpe)
{

System.Console.WriteLine(
"Insufficient privilege to search for session: " +
gpe.Message);
}
}

When the available sessions are found, you would display them to the
player in a GUI of some type:
Listing 12-7

private AvailableNetworkSessionCollection availableSessions =


null;

try
{
availableSessions =
NetworkSession.EndFind(e.AsyncResult);
}
catch (NetworkException ne)
{
System.Console.WriteLine("Failed to search for session: "
+
ne.Message);
}
catch (GamerPrivilegeException gpe)
{
System.Console.WriteLine(
"Insufficient privilege to search for session: " +
gpe.Message);
}

if (availableSessions != null)
{
foreach (AvailableNetworkSession availableSession in
availableSessions)
{
if (availableSession.CurrentGamerCount <
World.MaximumPlayers)
{
Console.WriteLine(availableSession.HostGamertag +
" (" +
availableSession.CurrentGamerCount.ToString()
+ "/" +
World.MaximumPlayers.ToString() + ")"));
}
}
}

World.MaximumPlayers is a game-implemented class member that can


be anywhere from 2 to 31 (there is an XNA Framework imposed limit of
31 players in a multiplayer game). The other two pieces of data come
from the session data that is transmitted by the host.
Once the player has picked the session he wants to join, you would begin
an attempt to join the session:
Listing 12-8

try
{
IAsyncResult asyncResult = NetworkSession.BeginJoin(
availableSessions[entryIndex], null, null);

}
catch (NetworkException ne)
{
System.Console.WriteLine("Failed to join session: " +
ne.Message);
}
catch (GamerPrivilegeException gpe)
{
System.Console.WriteLine(
"Insufficient privilege to join session: " +
gpe.Message);
}

If joining the session succeeds, youll get the network session that the
player is joined to:
Listing 12-9

NetworkSession networkSession = null;


try
{
networkSession = NetworkSession.EndJoin(e.AsyncResult);
}
catch (NetworkException ne)
{
System.Console.WriteLine("Failed joining session: " +
ne.Message);
}
catch (GamerPrivilegeException gpe)
{
System.Console.WriteLine(

"Insufficient privilege to join session: " +


gpe.Message);
}
if (networkSession != null)
{
LobbyScreen lobbyScreen = new
LobbyScreen(networkSession);
lobbyScreen.ScreenManager = this.ScreenManager;
ScreenManager.AddScreen(lobbyScreen);
}

The last couple of lines of code come from the Net Rumble Starter Kit,
which uses classes to represent the various screens needed to display the
network data to the player to allow him to get to this point. The
LobbyScreen class is what you saw back in Figure 12-6.
From here, you have a couple of events that need to be handled and the
information for those events displayed to the player:
GamerJoined You need to update the screen to display the data for
the player that has joined.
GamerLeft You need to remove the player from the list of players
that are in the session so his or her data is no longer displayed.
GameStarted Whatever needs to be done to start the gameplay
would happen. This code should only happen on the host and then be
transmitted to the other players.
SessionEnded You would need to let the player know the session is
ended and then take the player back to the appropriate screen.
Once the game has started, there are two class youll be constantly using
the PacketWriter and PacketReader. You would use the PacketWriter
class anytime something happens in the world that the other players need
to know about. This includes player movement or actions and events that

are caused by NPCs or the world itself. In order to transmit this data to
players, you first need to figure out what type of information it is that
you need to send. A common way to do this is to create an enum that
contains a value for every type of packet that you need to send. Heres a
sample enum:
Listing 12-10

public enum PacketTypes


{
PlayerData,
EntityData,
WorldSetup,
WorldData,
PlayerInput,
GamestateChange,
GameWon,
};

You could get a lot more, depending on how much depth you want, but
making the values somewhat generic gives a little more flexibility. The
combination of GamestateChange and PlayerInput could be used for
anything from combat to conversation handling, for example. If you had
a game state of InitiateConversation, you could send this to display
the conversation dialog. The PlayerInput packets would then be used to
show the other players the selections made as the conversation goes on.
To send data, the easiest thing to do is to serialize a class that holds the
data for that packet type. For example, to send a change to an entitys
stat, you would do something like:
Listing 12-11

packetWriter.Write(_entities[0].Name);
_entities[0].Stats["Strength"].Serialize(packetWriter);
localGamer.SendData(packetWriter,
SendDataOptions.ReliableInOrder);

// Serialize method for EntityStat class


public void Serialize(PacketWriter packetWriter)
{
// safety-check the parameter, as it must be valid.
if (packetWriter == null)
{
throw new ArgumentNullException("packetWriter");
}

packetWriter.Write(_stat);
packetWriter.Write(_value);
}

The other players would get this data as part of the games update:
Listing 12-12

private void ProcessPackets()


{
if ((networkSession != null) &&
(networkSession.LocalGamers.Count > 0))
{
// process all packets found, every frame
while (networkSession.LocalGamers[0].IsDataAvailable)
{

NetworkGamer sender;

networkSession.LocalGamers[0].ReceiveData(packetReader,
out sender);
// read the type of packet...
PacketTypes packetType =
(PacketTypes)packetReader.ReadInt32();
// ... and dispatch appropriately
switch (packetType)
{
case PacketTypes.PlayerData:
UpdatePlayerData(sender);
break;

case PacketTypes.WorldSetup:
// apply the world setup data, but only once
if (!Initialized)
{
Initialize();
}
break;

case PacketTypes.EntityData:
if ((sender != null) && !sender.IsLocal)
{
UpdateEntityData(sender);
}
break;

case PacketTypes.WorldData:
if (!networkSession.IsHost && Initialized)
{
UpdateWorldData();
}
break;

case PacketTypes.PlayerInput:
if (sender != null)
{
PlayerData playerData = sender.Tag as
PlayerData;
if ((playerData != null)
{

playerData.ProcessInputPacket(packetReader);
}
}
break;

case PacketTypes.GameWon:
gameWon = true;
if (networkSession.IsHost &&
(networkSession.SessionState ==
NetworkSessionState.Playing))
{
networkSession.EndGame();
}
break;

}
}
}
}

Summary
What weve gone over in this chapter is a far from exhaustive look at the
networking functionality thats offered by the XNA Framework. A
complete discussion of the subject would likely take up several chapters.
Whats been covered here should be enough, however, to give you some
information that you can use to start planning for offering multiplayer
functionality in your game. Offering multiplayer gameplay is a great
way to increase both your potential audience and the longevity of your
game. As with most games that offer a multiplayer component, once the
player completes the single-player portion of your game, he can then get
a potentially completely different experience by jumping into the
multiplayer portion of the game. Some games live on for years after their
release, based solely on the strength of the multiplayer experience. The
longer you can keep your game in the awareness of gamers, the more
your name will be known, and the easier it will be for you to get gamers
to pick up games you release from then on.

Chapter 13
Putting It All Together
At last were finally going to bring all the pieces that weve been talking
about together into a sample game. Because of all the work that weve
done in creating the pieces, its fairly simple to create a basic game.
After doing so, well discuss some areas where you would probably

want to flesh things out a bit to make it a game that you would be proud
to call your own.
Youll want to make sure you have the code for this chapter and youll
want to look through it for a while to make sure you understand how it
all works together and how you can use whats there to create your own
game. I purposely made it so that you couldnt just compile it, slap your
name on the front, and call it yours (well, you probably could, but it
wouldnt be something to be proud of).
If you compile and run the project, youll find that it starts up with a
character already created and standing in a small town. It shouldnt be
too hard to figure out what to do as theres only one other character in
the town. When you interact with him, youll start up the conversation
that leads to the main quest for the demo the NPC was attacked on his
way from another town to his home in this town by some creatures and,
although he managed to get away without being killed, he lost a family
heirloom, an ordinary ring. Its not worth anything except for the
sentimental value and hes willing to pay you to find it and return it to
him. He believes the creatures that attacked him picked it up and their
leader has it.
Hes found out that the creatures live in a cave not far from the path that
leads out of the town. Youll have to travel through a bit of wilderness to
get there, but you cant miss it. Lucky for you, since you dont have any
skill at tracking or any other skill except swinging the sword thats at
your waist. Thats to be expected, since you just decided to take up
adventuring and this sounds like a perfect way to start your career as a
famous adventurer. Once you accept the quest, youll head out of town,
find the cave (maybe fighting some creatures along the way), find and
kill the leader of the small clan of monsters, get the ring, and return it to
its owner. No problem!

Go ahead and play through the game. It shouldnt take more than a
couple of minutes. Ill wait here.
Okay, so it wasnt The Lord of the Rings. I never claimed it would be,
but you could turn it into something almost as exciting with a little work.
Lets talk about some of the code youll need to modify to get there.
Everything in the game is driven from the Game class. This isnt how
youll want to leave it, but it works. Ideally, you would have a menu
system to allow the player to do all the things you normally expect to be
able to do start a new game, load a previous game, save the current
game, adjust options such as resolution, sound, and controls, etc. Theres
not much going on in the class. Youve got an instance of the Level class
and an instance of the Entity class that represents the character. The
Game object creates and initializes these objects in the LoadContent
function:
Listing 13-1
public class Game1 : Microsoft.Xna.Framework.Game
{
GraphicsDeviceManager graphics;
SpriteBatch spriteBatch;

public Game1()
{
graphics = new GraphicsDeviceManager(this);
Content.RootDirectory = "Content";
}

protected override void LoadContent()


{

spriteBatch = new SpriteBatch(GraphicsDevice);

Entity character;
Level level;

level = Content.Load<Level>("town");
character = Content.Load<Entity>("player");

character.Location = level.PlayerStartLocation;

level.Entities.Add(character);

this.Components.Add(level);
}
}

Since the level is a DrawableGameComponent, its Update and Draw


methods will be called automatically. We dont have to do any other
work. All the logic is handled inside the Update method getting the
gamepad state and moving the character around accordingly since weve
added the character object to the levels list of Entity objects, handling
the interaction with the NPC and other entities, displaying the
conversation dialog, etc.
I did this partially to show how quick and easy it is to get something up
and running when you have all the pieces designed so that they work
well with the XNA Frameworks plumbing code. The Framework takes
care of all the boring, mundane code that you shouldnt have to worry
about and lets you deal just with gameplay code. I also did it partially so
that youd have to do a little code design work. Ive never met anyone
who could learn programming just by copying and pasting code that they

probably dont understand. I see enough posts in the Creators Club


forums where people have simply copied and pasted code incorrectly
and cant figure out why it doesnt work. I figured Im not doing you any
favors by doing all of the work for you! That said, while its enough to
show you how things can work, its not quite ready for prime time.

Making It Better
Obviously we cant create something during the course of this book that
most people expect of an RPG. Now that youve got the concepts down,
though, it should be a lot easier to create a full-fledged RPG that you
could submit to Xbox LIVE Community Games and actually expect
people to pay for. Notice that I said easier, not easy. Game development
isnt easy, and RPGs in particular are one of the more difficult genres to
work in. It is fun, however, at least in my opinion, and I hope to see a lot
of RPGs submitted to Xbox LIVE Community Games over the next year
or so.
Heres a list of things to consider when expanding what weve done here
into a full game:
Story While not strictly necessary, most RPGs have at least a basic
story behind the gameplay. MMORPGs are usually the type of games
that dump you into a world without any main guiding force, but you
could do the same thing in a regular RPG (although I wouldnt
recommend it). My personal feeling is that a good story is more
important than flashy graphics in an RPG. The story shouldnt interfere
with the gameplay, however. Try to use conversations and interactions
with NPCs to partially drive the storyline along if possible, without
having the NPCs seem like theyre reading the story from a book.
Speaking of books, they and other objects in the world can also be used
to provide background and other information that fleshes out the game
world and gives the players some idea of what theyre doing and why. If

the player is given a quest to help defeat some evil king, he may wonder
why he should bother. If he picks up a book and it turns out to be a
history of that king that describes how the king killed all but a few of the
characters race, he now has some incentive to see the king taken down.
Good storytelling is an art and even more so in games where you have to
do it in a medium different from those most people are used to. Dont
expect to win awards for the story in your game the first, second, or even
tenth time. Even award-winning authors have penned stories and scripts
for games that havent gotten great reviews. Do the best job you can
though, and players should notice the effort.
Levels Ideally you would have all your levels laid out before you
begin designing them. This could be done by designing your world first,
then creating levels that you can drop into areas of the world. Thats
assuming, of course, that you dont just make your world one big level
and dynamically load portions of it as the user explores it. That would be
an ideal situation and it can be done. The Dungeon Siege games were a
great example of doing this, but of course those had a huge team of
professionals. Most indie developers dont have those kinds of resources,
but theyre also not usually developing games on the level of a Dungeon
Siege.
Dont just create empty levels merely so you can say your game has 100
levels. If only a dozen of them are populated or interesting in some way,
you can expect the community feedback to be appropriately negative.
Compress the wilderness type levels to break things up a bit and give the
players a decent chance at nice random encounters. Make sure the
encounters are appropriate for the area as well. Players shouldnt be
fighting giant rats in the middle of a forest or bats in a desert.
As a player I could spend hours wandering around a town level as long
as there are interesting things to do there, especially if Im playing a thief

type character and thief skills are actually usable. If theres a thief guild
in the town, even better. You could have quests just based around it
pickpocket x amount of money, put a shop out of business by stealing
inventory because the owner wont pay for protection, etc. The
possibilities are almost endless. As long as theres enough content to
keep things fresh and interesting, one town can go a long way. This
could naturally lead to
More quests This goes with the story item but there are also sidequests to consider. The main story itself can have anywhere from one to
dozens of quests that have to be completed, but to keep the player on his
toes, you should have side-quests pop up from time to time. If the sidequests cause the player to think about accepting them and possibly
disrupting the main quest, making it more difficult to complete, or not
accepting them and losing out on whatever rewards can be obtained from
completing them well, thats part of what makes RPGs so interesting
and different from other genres.
If your game has dozens or even hundreds of quests, youre going to
have to ensure that the player has some way of managing them all. This
means not only a way to see all the quests hes currently working on but
also those hes completed, as well as possibly a way to reorganize them
in the GUI you use to display them. By default youll probably be
displaying them in reverse order of when they were accepted, moving
those hes completed to the bottom. If quests are tied together, youll
probably also want to give the player a way of easily seeing the thread
that leads from one to another.
More loot This goes without saying I think. Every RPG has tons of
items for the player to find, steal, whatever. Making the character more
powerful by getting new gear is part of the fun. Dont just throw loot at
the player for the sake of having loot in the game, though. There needs

to be a balance to when and where the player gets it and how much of it
they get. Avoid the Monty Haul campaign at all costs
(seehttp://tvtropes.org/pmwiki/pmwiki.php/Main/MontyHaul for an
explanation of this term if you havent heard it).
New classes, races, skills, spells, etc. One new skill that can
provide hours of gameplay is crafting. By allowing the player to create
his own items, you give him the ability to play the game he wants to
play, assuming that your implementation of crafting is fun, interesting,
and useful. Forcing the player to make his own arrows and having that
process be dull, boring, and take hours is not the kind of memorable
experience you want your game to be known for. You can look at most
MMORPGs for a way to not do crafting in my opinion. Ive yet to play
an MMORPG where crafting was interesting, fun, or immediately
useful. This is probably due to the way MMORPGs work. Developers
have to keep you busy doing something so you continue paying the
monthly fee. Making crafting easy would be counterproductive. Im sure
theres a way to make it fun, but I havent seen one yet. Fable 2s
smithing mini-game is about the closest to what I think crafting should
be.
Ive said it many times so far, but its so important Ill say it again.
Youll need to be careful with adding things like races, classes, or skills
to the game. Its very easy to create an unbalanced, and therefore unfun
(in my opinion anyway) game. If one race or class has superior power,
making it easier to complete the game when playing as that race or class
than as another race or class, most players probably will ignore the other
races or classes and possibly miss out on content youve spent time
creating for them, which means youve wasted time and possibly money
on all that content.

Try to plan all your content before you even begin developing,
prototyping on paper if possible. Create characters of all the race/class
combinations and playtest combat with some of the creatures you plan
on having in the game. If its obvious that one combination is better than
another, tweak values for stats, skills, or whatever until it takes about the
same effort with every combination. Yes, its going to take a lot of time,
but its better to do this on paper, where its easy to change things, than
in the game where you have to worry about breaking the game.
Saving and loading progress It wouldnt be very fun it you had to
start from the beginning every time you loaded the game, would it? I
havent bothered going over loading and saving an entire game because
its not much different than loading and saving a class from a code
perspective. You do have to think a little about what exactly needs to be
saved, however. Rather than saving the entire level, you really only need
to save any changes to the level. This includes things that have been
removed from the level (dead entities, loot thats been picked up, etc.).
In allowing the player to save his progress, youll have to answer the
question How many saves should the player have? Unfortunately,
theres no one right answer to this except It depends. You can give the
player the ability to save as many times as he wants, but if he can save
every time the character takes a step, theres no sense of danger in doing
anything. Fear of having the character die and losing something (be it
experience, items, temporary reduction of stats, etc.) is a good thing in
my opinion and something that should exist in the game experience.
Theres the checkpoint method of saving, but this usually turns out to be
more negative than positive from what Ive seen. Picking the right place
to save and ensuring that the state of the game at that point is always
such that the player can complete the game can be problematic. More
than a couple of games that have used the checkpoint system have been

patched to allow the player to save at any point. It takes a little more
work to allow the save anywhere feature, but its usually better than
the alternative. That being the case, restricting the number of saves while
allowing the player to save anywhere is usually a good compromise.
Theres still the possibility of the reduction of the danger of the character
dying, but theres not much that can be done about that from what Ive
seen. Keeping the player on his toes by not making encounters glaringly
obvious helps to heighten that sense of danger.
Options Give the players the option to change things that can be
changed. Some of these things include resolution, default controls, and
sound and music volume levels (with the option to turn them off
completely if they want). Make sure that changing or turning things off
doesnt affect the gameplay. (That quest where the character has to listen
outside a door? Yeah, that one. Thats not going to work if the players
turned off the sound!) One thing that Ive not seen much of is allowing
the player to adjust the brightness. Usually this isnt a problem, but in
dungeon-type levels there is the possibility of things being so dark that
on certain monitor and video card combinations the players ability to
make things out isnt as great as it could be. Making sure you test your
game on more than just your development machine can help spot this
problem, especially if you can do it on a low-end machine without
blazing graphical power.
Gamestate The demo doesnt have any real understanding of
gamestate things like pausing the game, pulling up a main menu to
change options or save the game, or even handling ending the game
gracefully. At a minimum, for the last item youd want to prompt the
user to save the game, not just shut down. Simply adding a menu system
means youre probably going to want to add some kind of gamestate
management. Luckily, a sample exists on the Creators Club web site that

shows how to do this. Modifying the demo to use it would be fairly


simple, consisting mainly of moving the level from the Game class to the
GameplayScreen class that the sample uses.
Whew! Thats a lot to think about. And here Ill bet you thought you
were done having to think about things and were ready to put out the
next Fable or Dungeon Siege. In ever promised an easy journey, nor that
Id get you all the way to your destination. If youve gotten this far
though, the remainder of your journey will be fairly short compared to
how far youve come already.
Remember, game development is a lot of hard, long work, but it should
be fun too. Create the game you want to play and youll be sure to have
something others will want to play as well. I know Ill probably want to
play it and Ill be looking on Xbox LIVE Community Games for a lot of
great RPGs to show up. There are a lot of RPG fans out there that are
waiting for you as well.

Appendix Additional Resources


The following web sites provide more information about XNA, RPG
game programming, and other game development topics.

RPG Development Links


RPG Toolkit Development System 3.1
http://sourceforge.net/projects/rpgtoolkit/
RPG Maker List http://rmlist.rpgsource.net/
Wikipedia entry on RPG Makers
http://en.wikipedia.org/wiki/RPG_Makers
RPG Maker XP http://tkool.jp/products/rpgxp/eng/
RPG engine http://www.explore-rpg.com/
RPG blog http://xnafantasy.wordpress.com/

RPG-related tutorials http://www.rpgrevolution.com/tutorials/gamedevelopment.html

Community Sites
Official XNA site http://creators.xna.com
Ziggyware http://www.ziggyware.com
XNA development http://www.xnadevelopment.com
The ZBuffer http://www.thezbuffer.com/
Reimer Grootjans site http://www.riemers.net/index.php

Blogs
Shawn Hargreaves blog
http://blogs.msdn.com/shawnhar/default.aspx
XNA Team blog http://blogs.msdn.com/xna/default.aspx
Michael Kluchers blog http://klucher.com
Virtual Realm http://www.virtualrealm.com.au/blogs/
Do as I say, not as I do http://amapplease.blogspot.com/
Nick Gravelyns blog http://nickgravelyn.com/
Random Chaos http://xna-uk.net/blogs/randomchaos/default.aspx
Catalin Zima http://www.catalinzima.com/

Game Development Resources


GameDev.net http://www.gamedev.net
Reiners Tilesets (many RPG-related assets here)
http://reinerstileset.4players.de/index.html
International Game Developers Association (IGDA)
http://www.igda.org
Game Programming Wiki http://www.gpwiki.org

AI Resources
AI forums on GameDev.net
http://www.gamedev.net/community/forums/forum.asp?forum_id=9
Game AI for developers http://aigamedev.com/

Links and resources for AI http://norvig.com/


Generation5 (an old site but you might still find some good information
there) http://www.generation5.org/
The Game AI Pagehttp://www.gameai.com/
Wikipedia, game AI
http://en.wikipedia.org/wiki/Game_artificial_intelligence
AI Wisdom http://www.aiwisdom.com/
AI-Depot, Artificial Intelligence in Game Design http://aidepot.com/GameAI/Design.html
Simple A* tutorial
http://www.policyalmanac.org/games/aStarTutorial.htm
Simple A* tutorial using Pac-Man as a base
http://www.geocities.com/jheyesjones/astar.html

AI Middleware Links
http://www.kynogon.com/products/technology/index.html
http://www.trusoft.com/ac_for_games_developers.html
http://www.simbionic.com/indexjs.htm
http://www.simbionic.com/games.htm

Source Code Control


SourceGear Vault http://www.sourcegear.com/vault/
SourceForge.net http://sourceforge.net/
Tigris.org http://www.tigris.org/
Comparison of revision control software Wikipedia page
http://en.wikipedia.org/wiki/Comparison_of_revision_control_software

Index
A
2D sound, playing, 186-189

AddCost function, 83-84


AddSpell function, 126-127
adventure type, 25-26
Agility stat, 35-36
Akalabeth: World of Doom, 3-4
alignment of entity, specifying, 60-61, 113, 140
AlignmentBitwise enum, 140
AlignmentFlags enum, 113
ambient lighting, 30
Arena, 9
armor, specifying location of, 146-147
Armor class, 145-147
Armor skill, 90
ArmorArea enum, 146-147
AssignedQuest class, 241
AssignQuest function, 257
attacks,
selecting, 163-165
types of, 161-162
AttackTypes enum, 161
audio, see sound
AudioEngine object, 181
Autoduel, 4-5

B
Baldurs Gate, 13-14
BaseItem class, 134-135
BaseTrapDamage enum, 197
Betrayal at Krondor, 8
BioShock, 19

Body Development skill, 91


Bonus structure, 42
bonuses, 82
for stats, 95-96

C
CalledShot attack type, 161-162
camera, 24, 29-30
CaseType enum, 259-260
Cast method, 122-124
CastSpell method, 121-122
casual games, 24
character, 1
designing, 33-34
multi-class, 51-52
character classes, 25
and skills, 94
Charisma stat, 36
chat, in-game, 280-281
CheckForQuestCompletion function, 258
Chest class, 147-151
class alignment combinations, 64
class-based system vs. skill-based system, 25
client-server network, 271-272
combat, 158-161
real-time, 23, 159-160
turn-based, 23, 160-161
combat engine, 165-168
combat simulator, 169-171
combat system, features to add, 171-172

CombatEngine class, 165-167


CompleteQuest function, 258
Constitution stat, 36
context menus, using to cast spells, 119-120
Conversation class, 248-253
ConversationFunctions enum, 255
ConversationManager class, 265-267
ConversationNode class, 253-255
conversations, 21, 247
testing, 260-265
CreateSession function, 283
Cross-Platform Audio Creation Tool, see XACT
Cue object, 181

D
damage,
resistance, 59
specifying, 197
types of, 58-59, 144
weakness, 59
Damager structure, 58-59, 143, 197
DamageType enum, 58-59, 144
design document, 22
for sample game, 28-32
Detect Trap skill, 92
Dexterity stat, 35
Diablo, 11
DieType enum, 39
difficulty, specifying, 87
Difficulty enum, 87

Disarm Trap skill, 92


Disengage attack type, 162
dnd, 3
Dodge skill, 91
Doom, 9
Draw method, 206-207
Dungeon, 3
Dungeon Keeper, 16
Dungeon Keeper 2, 16
Dungeon Siege, 11-12
Dungeons and Dragons, 3
Dunjonquest: Temple of Apshai, 4
Dwarf,
race type, 47
stats and skills, 48

E
Elf
race type, 47
stats and skills, 46-47
entities, 33-34
alignment of, 60-61
specifying type of, 54
Entity class, 53-62
EntityAlignment enum, 60
EntityClass class, 50-52
EntityItem class, 152-153
EntitySpell class, 117-119
EntityStat class, 40-42
EntityType enum, 54

event, audio, 181


experience, level of, 55-56

F
Fable, 17-18
factions, 237-238
Fallout, 12-13
FedEx quest, 234
FillGroundLayer method, 206
FillSkillObject function, 98-99
FindSession function, 285
First Aid skill, 93
FirstTime function, 256
Freedom Force, 11
FunctionType enum, 255

G
Game class, 295
Game Master, 276
GamerJoined event, 287
GamerLeft event, 288
GamerPresence class, 282
GamerPresenceMode enum, 282
GameStarted event, 288
gamestate, 301-302
GetCost function, 83-84
GetRandomNumber function, 39
GetTotalDefBonus function, 88
graphics, 191-192
graphics engine, 23-24

griefing, 275
GUI, see interface
GUI libraries, 227-228

H
Half-Elf
race type, 48
stats and skills, 48
Halfling
race type, 49
stats and skills, 49
HasQuest function, 256-257
Hellgate: London, 20
Hide skill, 92
hit points, 56-57
calculating, 57
host, 270
hotkeys, using to cast spells, 119
Human race type, 47

I
Icewind Dale, 15
Icewind Dale II, 15
in-game chat, adding, 280-281
Initialize function, 279
Intelligence stat, 36
interactions, 247
checking, 255
specifying type of, 240
InteractionType enum, 240

interface, 211-213
creating inventory window, 217-226
creating toolbar, 214-216
features to add, 228-230
IntermediateSerializer class, 43-45, 99-100, 243
Inventory class, 154-156
inventory items, drawing, 225-226
inventory management, 153-154
inventory window, 217
creating, 217-226
InventoryWindow class, 217-226
Item class, 138-141
items, 133-134
adding, 298-299
distributing, 133
implementing damage to, 140
limiting use of, 139-140
managing, 153-154
specifying types of, 139, 150
ItemType enum, 139, 150

K
Knights of the Old Republic II: The Sith Lords, 17

L
Layer enum, 206
layers, specifying type of, 206
LearnSpell method, 116
Level class, 200-207
level editor, 208

levels, 200, 297-298


LevelSquare class, 193
lighting, 30
LoadContent method, 186
LoadQuest function, 243-245
LoadSkill function, 100
LoadStat function, 45
LockUnlock trigger type, 199
LongRangeShot attack type, 162

M
magic, 109-110
using, 119-124
mana, 2, 109
Mass Effect, 19-20
MaxWeight function, 64
MediaLibrary class, 178
MediaPlayer class, 178
MediaQueue class, 179
Melee Weapons skill, 90
Message trigger type, 199
metadata, 135
Might and Magic series, 7
Might and Magic VI: The Mandate of Heaven, 10
MMORPG, xv
Money class, 136-138
Morrowind, 9
mouse gestures, using to cast spells, 120
Move Silently skill, 93
MoveSpell function, 128-129

multi-class characters, 51-52


multiplayer capability, 269
setting up for, 278-290
multiplayer experience, features to add, 277
multiple-player party, 273-275

N
NetworkSessionType enum, 283
Neverwinter Nights, 16-17
Neverwinter Nights 2, 17
Normal attack type, 161
Nox, 16

O
objects, specifying type of, 199
ObjectType enum, 199

P
PacketTypes enum, 288
PacketWriter class, 288
Parry attack type, 161
pedit5, 3
peer-to-peer network, 270-271
Perception skill, 93
Pick Lock skill, 93
PickLock function, 151
Planescape: Torment, 14-15
Playlist class, 179
point-based skill system, 78-79
Pool of Radiance, 5

presence information, 281-282


primary stat, 35
ProcessPackets function, 289-290
progress, saving and loading, 300-301

Q
Quest class, 233-240
QuestAssigned function, 257
QuestRewardType enum, 235
quests, 22, 231-233
adding, 298
checking, 256-259
designing, 242-245
specifying type of, 234
QuestStep class, 239
QuestType enum, 234

R
race alignment combinations, 63
race bonuses for skills, 94-95
race types, 47-50
race/class combinations, 63
races, 46
Ranged Weapons skill, 90
ranks, 78
real-time combat, 23, 159-160
RemoveCost function, 83-84
RemoveTile method, 205
resistance to damage, 57-59
ResolveAttack method, 167-168

resources, 303-306
rewards, 140
specifying type of, 235
Riposte attack type, 161
Rogue, 3
RPG, 1
designing, 22-32
history of, 3-20
objects in, 21-22
system, 24-25
RPGGame class, 66

S
Sacred, 11
sample game,
camera, 29-30
characters, 30-31
combat simulator, 169-171
creating entity classes in, 70-73
creating races in, 69
creating skills in, 97
creating stats in, 67-68
design document, 28-32
designing quests, 242-245
features to add, 296-302
game world overview, 28-29
items, 31
learning skills in, 101-103
music, 31
putting it all together, 293-294

single-player, 32
testing conversation, 260-265
user interface, 31
save system, 26
SaveSkills function, 99-100
SaveStats function, 43-44
scripting system, 27-28
scripts, 22
server, 271-272
SessionCreated function, 284
SessionEnded event, 288
sessions,
creating, 283-284
displaying, 286
joining, 286-287
SetTile method, 205
SetTrap trigger type, 199
Shield Use skill, 91
skill-based system vs. class-based system, 25
Skill class, 80-84
skill data, storing, 96-101
skill points, 78-79
calculating, 89-90
skills, 2, 21, 77-80
cost of, 82, 94
learning, 94, 101-104
loading, 100
race bonuses for, 94-95
saving, 99-100

specifying types of, 81


tracking, 89
types of, 90-93
using, 104-107
SkillType enum, 81
Song class, 178
songs, playing, 178-180
sound, 175
adding to sound bank, 183-184
creating with XACT, 182-185
playing, 177-178
playing 2D, 186-189
sound bank, adding sounds to, 183-184
SoundBank object, 181
SoundEffect class, 177-178
SoundEffectInstance class, 177-178
Spawn trigger type, 199
spells, 21
adding to spell book, 126-127
difficulty in casting, 111
learning, 115-116, 118
moving in spell book, 128-129
specifying duration of, 112
specifying effects of, 111-112
specifying range of, 112
specifying rate of, 114
specifying type of, 111
spell book, 124-126
adding spell to, 126-127

moving spell in, 128-129


using to cast spells, 120-121
spell casting, implementing, 119-121
Spell class, 110-115
Spellbook class, 126
SpellBookPage class, 130-131
SpellCastRate enum, 114
Spellcraft skill, 91
SpellType enum, 111
Stalk skill, 92
Star Wars: Knights of the Old Republic, 17
stat bonuses, 95-96
Stat class, 36-37
stats, 1-2, 35-36
loading, 45
saving, 43-44
specifying types of, 37-38
StatType enum, 37
story, 296-297
Strength stat, 35
subquest, 231-232

T
target, selecting, 163
The Bards Tale, 4-5
The Witcher, 18-19
tiles, 21, 192
creating, 193-200
removing, 205
setting, 205

tileset, 194
ToolBar class, 214-216
toolbar, creating, 214-216
tools, 27
toolset, see XNA RPG Toolset
track, audio, 181
trap, specifying type of, 150, 196
Trap structure, 196
TrapType enum, 150, 196
Trigger structure, 198
triggers,
specifying, 198
types of, 199
TriggerType enum, 198
turn-based combat, 23, 160-161

U
Ultima 1: The First Age of Darkness, 4
Ultima series, 6-8
Ultima Underworld: The Stygian Abyss, 7
Unarmed Combat skill, 91
Unlimited Adventures, 5
Update method, 187-188, 279
Use function, 84-87
user interface, 31
see also interface
UseSkill method, 104-105
UseUnarmedCombat function, 106-107

Warcraft, 10-11
Wasteland, 5
WaveBank object, 181
Weapon class, 141-144
weapons, specifying types of, 143
WeaponType enum, 143
weather, 29
Wisdom stat, 36
Wizardry series, 7

X
XACT, 176, 180-181
creating sounds with, 182-185
XNA RPG Toolset, 65-75
combat simulator, 169-171
creating skills in, 97
designing quests, 242-245
learning skills in, 101-103
testing conversation, 260-265

You might also like