Platformer Enemy AI

Questions about the LÖVE API, installing LÖVE and other support related questions go here.
Forum rules
Before you make a thread asking for help, read this.
User avatar
tentus
Inner party member
Posts: 1060
Joined: Sun Oct 31, 2010 7:56 pm
Location: Appalachia
Contact:

Platformer Enemy AI

Post by tentus »

Let's talk a bit about enemy AI for platformer games. I'm not only looking for ideas for my own game, but trying to generate discussion that will help future Lovers out, so please post your ideas, no matter how crazy.

To start out, I'm going to define how I want my AI to act, specifically. I want enemies to move left and right on surfaces, meaning that they fall when in midair. I want enemies to die when hit from above (Mario-esque stomping), but otherwise dish out damage to the player. Both of these two goals have been accomplished using Box2D and a relatively light smattering of code. Next, I want my enemies to change direction when faced with an obstacle. This is where the discussion gets interesting.

There are basically two main kinds of obstacles: solids and vacuums. A solid is a wall or other obstruction that cannot be passed through. A vacuum is a cliff or pit. Changing direction when faced with a solid is easy: one collision callback that compares Xes and you're done. The vacuum, on the other hand, is hard, because there's nothing to compare against.

You can circumvent this by making the level designer set numeric boundaries inside each enemy object. This is a bad solutions though, because the player may find some way of knocking the AI out of its initial area. What if the AI gets bounced into a shallow pit that is beyond the preset AI boundaries?

Another solution would be to force the level designer to set clipping blocks, giving the AI something to collide with, invisible to the player. This is stronger than storing numeric boundaries, because the AI doesn't glitch outside it's home area, but it can lead to other exploits (ever seen the Mario Level 1 flagpole vault?). It also puts a greater onus of work on the level designer.

What are your guys' thoughts? Any clever ways to check against a vacuum? Other little behaviors that might be useful for making games more interesting, like making enemies lunge at players within a certain distance?
Kurosuke needs beta testers
User avatar
BlackBulletIV
Inner party member
Posts: 1261
Joined: Wed Dec 29, 2010 8:19 pm
Location: Queensland, Australia
Contact:

Re: Platformer Enemy AI

Post by BlackBulletIV »

My first thought is that you could do some sort of ray cast downward from the enemy, say, 15 pixels ahead of the current x position. If nothing collides for a certain distance, you can tell that you're standing at a vacuum.
User avatar
kikito
Inner party member
Posts: 3153
Joined: Sat Oct 03, 2009 5:22 pm
Location: Madrid, Spain
Contact:

Re: Platformer Enemy AI

Post by kikito »

If you are using box2d, the "am I facing a vacuum" problem could be resolved with a sensor shape. It should be intangible in front of your monster "face" and under his "feet". That way they can really "sense" the vaccum in front of them (or the absence of ground, in any case). And it's also a callback check, which I assume is performant enough for your taste.

On tile-based games it's quite easy; you just check the tile in front of the enemy. I know it sounds obvious; my point is that in general, you can use the map itself to do calculations like this with ease, if you have tiles.
Last edited by kikito on Mon Jan 24, 2011 1:08 am, edited 1 time in total.
When I write def I mean function.
User avatar
tentus
Inner party member
Posts: 1060
Joined: Sun Oct 31, 2010 7:56 pm
Location: Appalachia
Contact:

Re: Platformer Enemy AI

Post by tentus »

kikito wrote:If you are using box2d, the "am I facing a vacuum" problem could be resolved with a sensor shape. It should be intangible in front of your monster "face" and under his "feet". That way they can really "sense" the vaccum in front of them (or the absence of ground, in any case). And it's also a callback check, which I assume is performant enough for your taste.
My younger brother and I refer to this as the white cane solution, I've used it in other frameworks. :) My biggest issue with the white cane is that it's really easy to mess up: forgetting that it's there, getting false positives from incidental objects, getting false negatives from gaps smaller than the enemy... It can be a real headache. Still, it's worked in the past, so it's a very viable solution.
BlackBulletIV wrote:My first thought is that you could do some sort of ray cast downward from the enemy, say, 15 pixels ahead of the current x position. If nothing collides for a certain distance, you can tell that you're standing at a vacuum.
This has a lot of the same issues as the white cane solution. Where do you start the ray? Eye level for the enemy, or maybe 1 pixel above their bottom edge? Do you run the ray every frame, or every pixel of movement? You get into some very interesting decision making problems.

Keep em coming folks, I know we have even more good ideas floating out there!
Kurosuke needs beta testers
User avatar
BlackBulletIV
Inner party member
Posts: 1261
Joined: Wed Dec 29, 2010 8:19 pm
Location: Queensland, Australia
Contact:

Re: Platformer Enemy AI

Post by BlackBulletIV »

tentus wrote:
BlackBulletIV wrote:My first thought is that you could do some sort of ray cast downward from the enemy, say, 15 pixels ahead of the current x position. If nothing collides for a certain distance, you can tell that you're standing at a vacuum.
This has a lot of the same issues as the white cane solution. Where do you start the ray? Eye level for the enemy, or maybe 1 pixel above their bottom edge? Do you run the ray every frame, or every pixel of movement? You get into some very interesting decision making problems.
Yeah, running a ray cast every frame or even pixel would have performance issues when you get a lot of enemies. You could probably do a check every 7.4 (less than 7.5, which is half of 15) pixels or less and get away with it; but that is starting to sound like it could cause bugs and exploits. Hmmmmm...
User avatar
tentus
Inner party member
Posts: 1060
Joined: Sun Oct 31, 2010 7:56 pm
Location: Appalachia
Contact:

Re: Platformer Enemy AI

Post by tentus »

BlackBulletIV wrote: Yeah, running a ray cast every frame or even pixel would have performance issues when you get a lot of enemies. You could probably do a check every 7.4 (less than 7.5, which is half of 15) pixels or less and get away with it; but that is starting to sound like it could cause bugs and exploits. Hmmmmm...
Out of curiousity, where does the 15 come from? Why not a more common int, like 32?
Kurosuke needs beta testers
User avatar
BlackBulletIV
Inner party member
Posts: 1261
Joined: Wed Dec 29, 2010 8:19 pm
Location: Queensland, Australia
Contact:

Re: Platformer Enemy AI

Post by BlackBulletIV »

I thought that a number around from around 10-20 would most likely be best. I usually use multiples of 5 for some reason. Of course it could be 16 if you really need a power of two.
User avatar
kikito
Inner party member
Posts: 3153
Joined: Sat Oct 03, 2009 5:22 pm
Location: Madrid, Spain
Contact:

Re: Platformer Enemy AI

Post by kikito »

tentus wrote:... the white cane solution...
Haha, nice name!

I just went through the sonic the hedgehog tutorial and saw that they do indeed use a couple "sensor lines" for both "ground" and "edge" detection (you are on an edge if only one of the two sensors is active). Again, they optimize for tile-based cases, but the idea remains.
When I write def I mean function.
User avatar
The Burrito
Party member
Posts: 153
Joined: Mon Sep 21, 2009 12:14 am
Contact:

Re: Platformer Enemy AI

Post by The Burrito »

I'm in the process of rewriting this kind of check for my game. Right now I do a collision check for a point just in front of and below the enemy, and if it returns false, it checks again a couple of pixels away.
This is pretty crappy, but I had issues using sensor shapes and made this point check system for the player (it's mostly just to tell the game which animation should be playing) and copied it over for the enemy ai.

I will likely replace it with either a sensor shape or test segment but I'm not sure which is the fastest option yet. Box 2D is smart when it comes to checks and don't forget that computers are really fast.
All these little rolly guys have animation, ai, and physics, not to mention the lighting system, backgrounds and player code(he's buried in there somewhere), not a noticeable performance impact, the ones stuck in the floor and stuff are my fault for clicking all over the screen spawning them randomly.
InTheDarkenemy.jpg
InTheDarkenemy.jpg (138.11 KiB) Viewed 2467 times
My computer isn't crappy, but it's not really high end anymore, and the only thing preventing this from running on my netbook is non Po2 framebuffers.
User avatar
tentus
Inner party member
Posts: 1060
Joined: Sun Oct 31, 2010 7:56 pm
Location: Appalachia
Contact:

Re: Platformer Enemy AI

Post by tentus »

I suppose I should bring up the Tilted Box approach, to keep people talking. The Tilted Box approach checks the angle of each enemy's physics box, and if it's beyond a certain point (say, 15 degrees), the enemy changes direction. This is a clean little approach, and works in theory, but in practice the little buggers seem to find ways to tip over anyhow, no matter how clever you get with your decision timers and angular dampening.

@Burrito: I'd be very interested in seeing your code, if you'd be willing to share. Even if it's code that didn't make the cut for your game, I'd bet that someone can find use for your code.
Kurosuke needs beta testers
Post Reply

Who is online

Users browsing this forum: Google [Bot], Majestic-12 [Bot] and 8 guests