It occurs to me that some of my posts have been way too long.
Thursday, September 27, 2007
The pursuit of brevity
Wednesday, September 26, 2007
Real-time battles, part 2: enemy AI
My first post about real-time battles dealt with timing -- how to pace a battle so it's fast-paced but leaves just enough time to make decisions. Part 2 deals with a considerably more complicated topic: enemy artificial intelligence (AI).
Before I begin, a disclaimer. I don't know anything about AI -- at least not about programming it (yet). These thoughts are just that: reflections on what's required to simulate an intelligent adversary. The way I see it, the problem of enemy AI can be divided into two parts (at least in terms of RPG games like the one I'm making):
Basic movement
In a real-time battle system, enemies exist in a world filled with obstacles -- rocks, trees, buildings, other creepy monsters -- so enemies need the ability to move around the world without doing silly things like trying to walk through a wall or wandering into the ocean.
Basic movement, then, requires that enemies have the ability to move around in a normal fashion (when nothing is in the way), and to avoid obstacles when they arise. Normal movement, of course, can take several forms. One enemy might patrol between a series of fixed points while another might wander aimlessly in a particular area.
Neither of these possibilities is very convincing, however. It would make much more sense for enemies to move about the world with a purpose. Not only would they lead happier and more fulfilling lives, they would seem more realistic. An evil imperial soldier might indeed patrol between fixed points, but a giant cave bat wouldn't spend all its time wandering within five meters of the place it was born.
Higher brain function (deciding what to do)
Wandering is fine, but what if a player (or group of players) invades the cave bat's cave? It would protect its turf by attacking the intruders. The first order of business is to decide who to attack. This decision is easy enough when there is one player-controlled character, but in a party-based or multiplayer game it obviously becomes more difficult.
Many games solve this issue with the concept of aggro. An enemy might attack the first player it sees, but if another player comes in and deals twice as much damage, he will draw the enemy's attention. Aggro, then, can be thought of as a function of damage or healing. Whichever player in range has offended the enemy the most becomes the object of its raging cave bat wrath.
Once the enemy has decided who to attack, it must then choose the manner of attacking. The conventional way to approach this problem is to build a decision tree. Given its set of possible moves, the enemy will survey its situation and choose a move, often with a healthy dose of randomness built in. For example, a monster with access to a healing spell and a basic attack might go through this sort of thought process:
- If my health is less than 60%, heal myself.
- Otherwise, attack the player with the most aggro.
A similar approach is also useful for party AI, which I'll discuss in part 3. I know you can't wait.
Monday, September 24, 2007
My camera, vanquished
After three days of wrangling with my code and muttering to myself, I have managed to get my camera system to a place where it mostly behaves. Having accomplished this, I feel a new sense of admiration for games with cameras that gracefully avoid passing through floors and walls. It's still possible to make it pop through a wall occasionally or to find just the right spot where it will completely freak out, but it'll do for now.Here's the gist of how it works:
- Just before every frame is drawn on screen, the camera casts a series of rays to detect objects around it. The primary ray starts at the camera's target (the player) and casts back toward the camera, ending a short distance behind the camera. A group of secondary rays are also cast pointing outward from the camera itself, like spines sticking out in several directions.
- In normal circumstances (when no offending objects are near the camera), the camera can be moved around by clicking and dragging the left mouse button.
- If an object interrupts the primary ray (i.e., passes between the camera and its target), the camera jumps to a point in front of the object. Once the object is clear, the camera slides back to its preferred distance from the player.
- If the camera detects an object below it (like the ground), it will begin sliding toward its target. In this mode, the camera's distance to the target is proportional to its own distance from the ground.
- If an object gets too close on the left or right side of the camera, the camera will slide along this object toward the target until it slides clear and can move along unobstructed.
Then the muttering diminished, and I cracked open a beer.
Thursday, September 20, 2007
The virtual web, and how to avoid hitting the ground
The other day I stumbled on an intriguing new project called Metaplace that's aiming to provide an easy-to-use, web-standards-based way to create virtual worlds. The possibilities for creating games are obvious, but this seems an interesting step for the Internet in general.
If Metaplace works like they say it will, it would be possible to turn your web site into a virtual world--meaning that your site wouldn't just deliver content, it would provide a place where people could gather and discuss that content. Imagine being able to chat in real time with anyone else who's currently visiting a site. It could be an incredibly powerful way to make connections. This is a big step beyond our current social networking setup, where people just leave messages amounting to little more than, "I wuz here."
--------------------
On a game-related note, I spent most of my time today working on camera collisions. There's nothing worse than a game with bad camera controls. I'm trying to build a camera that's smart enough to keep the player always in sight. This means recognizing when it can't see the player and moving to a place where it can.
I've gotten to the point where my camera can handle direct obstacles well enough. Things get tricky when it needs to avoid objects like the ground. It doesn't make much sense to look at the player-character through the ground, so the camera needs to recognize when its getting too close to the ground (or something like a wall) and move to a safe spot along the vector between the camera and the player. This involves a lot of math for an English major, so I'll just have to take it slow.
Wednesday, September 19, 2007
Real-time battles, part 1: timing
Ok, so my last post wasn't exactly about real-time battle systems like I said it would be. This one is.
As I mentioned previously, there are advantages to a real-time battle system (like World of Warcraft or most other MMOs). For one, you don't need to whisk the player off to a "battle mode" that exists in some parallel universe. Another big advantage is that battles can be more realistic. Enemies and party members can attack and be attacked at any time, and there doesn't need to be any god-of-the-battle AI that dictates when each character or enemy is allowed to execute a move.
As you might expect, these advantages come with their share of tricky design decisions. This is the first in a series of posts that will discuss some of the common ones. Where to start?
Timing
Attack speed -- At first glance, timing seems easy. Each character or enemy has an attack speed, probably determined by some stat or the awesomeness of your weapon.
Cooldown -- Ok, that might be enough if all you do is flail about, but what if you want to give your player a special "extended flail" skill? You wouldn't want him to be able to string these together endlessly (it just wouldn't be fair), so you need a cooldown time for each ability or skill.
Charge time -- So now you can't eliminate your target with an endless string of "extened flail," but couldn't you just string together every skill in your arsenal and gank your unsuspecting target that way? (Indeed, this is the method used by every god-forsaken rogue in World of Warcraft.) This wouldn't be too challenging, either (yes, I played a mage), so you also need to implement some system where abilities require time to execute. Then you need to decide whether the charging process can be slowed or interrupted.
Down time -- This is similar to cooldown, but instead of affecting a single ability, down time affects your ability to do anything at all. After executing your supremely powerful "nuclear meltdown" ability, there might be a period of time when you can't execute any new moves, which leaves you vulnerable to the giant cockroach monster that survived the meltdown. Final Fantasy XII used down time instead of cooldown; WoW imposes a uniform down time of about a second after each move, in addition to skill-specific cooldown.
Easy enough, right? Part 2 will cover the intricacies of enemy AI.