The Daily Click ::. Forums ::. Klik Coding Help ::. Enemy Ai
 

Post Reply  Post Oekaki 
 

Posted By Message

\/\/olf

Creative Genius

Registered
  06/08/2005
Points
  76

VIP Member
26th November, 2007 at 02:34:51 -

This has probably been done before. Anyway, im workin on an 8 directional movement system. Can be toned down to a 4-dir one if 8-dir one is difficult to do. I just need the enemies to follow the hero and be smart enough to go around walls.

I tried using the easy grid and pathfinding object but couldnt figure them out. im using mmf 1.5 btw. Any help, like always, is most appreciated. Examples, even more so.

 
Image

www.OldMansTale.net
Sign the Petition! Go go Go!!

~Zigzag~



Registered
  13/03/2007
Points
  292

Game of the Week WinnerSilverNova Member
26th November, 2007 at 03:24:22 -

You could use bouncy ball movement coupled with Always look in the direction of Hero. Then just have him slow down the nearer he gets to the hero, so he doesn't fly past him etc.

 
http://www.SilverNova.co.uk

\/\/olf

Creative Genius

Registered
  06/08/2005
Points
  76

VIP Member
26th November, 2007 at 04:59:33 -

but that doesnt get the enemy go around walls.

 
Image

www.OldMansTale.net
Sign the Petition! Go go Go!!

DeadmanDines

Best Article Writer

Registered
  27/04/2006
Points
  4758
26th November, 2007 at 07:33:26 -

Yeah, that bit's a little trickier.

Problem with Pathfinding is it's quite a heavy process. You don't want it running too much of the time. You'd also have the problem of defining the map for the pathfinding object. This would probably involve a time-consuming loading sequence at the start.

Is your player movement custom-made? or is it a built-in movement?

I have an idea for a solution which I'm probably gonna call Threading, but I use MMF2, so doing an example could be tough. I'll see if I can copy/paste the event list.

 
191 / 9999 * 7 + 191 * 7

AndyUK

Mascot Maniac

Registered
  01/08/2002
Points
  14586

Game of the Week WinnerSecond GOTW AwardHas Donated, Thank You!VIP Member
26th November, 2007 at 10:33:13 -

Well i can think of a few ways.

The player object never actually touches a wall. So if the player object leaves behind something every now and then that the ai players can move towards?

or you could pre-determine places the ai player can move to? Like nodes that they can walk from and when they get to one there is always another one at 90 degrees or 45 degrees to where they currently are so they can easily reach each node.

but if they still get stuck on walls you can create your own 8 directional movement. That was moving up and down is seperate from moving left and right. When the ai player is overlapping a wall they get pushed away from it in the opposite direction. But the other axis will still work fine. So they'll eventually get where they want.

 
.

DeadmanDines

Best Article Writer

Registered
  27/04/2006
Points
  4758
26th November, 2007 at 12:07:13 -

Okies, it's done.
Only works for one follower at the moment, I can imagine it being a bit tricky for many followers. But it works perfectly so far as I can tell.

You'll need the following extensions:

Move Safely 2
Advanced Direction Object

And the following objects:

A small 2x2 active object
^ We call this 'LOS Detector', just a small yellow box. We'll use this to test for obstacles.
A Player Object
A Follower Object
A small circular 16x16 active object
^ We'll call this one 'MARKER'.
It'll serve as a node in the path for the follower, or like a breadcrumb if you wanna use the Hansel and Grettle analogy.

It works like this:


Imagine walking through a maze holding a piece of thread. Where it pulls tight, it gets caught against the edges, like this:

Image

See where it pulls tight?

Well this does something similar. Using Move Safely 2, it tests for obstacles between the player and the follower. We call this a Line Of Sight (LOS) Routine. It basically moves a detector object between two points to find out if there are obstacles between them. If not, then those two points have a 'clear line of sight'.

So if we test between our follower and player, then we now have this:

Image

Move Safely basically moves our 'LOS detector' object along that line, constantly asking it "are you over an obstacle?... how about now?... now? ... now?"

What we do next is a couple of events like this:

ALWAYS
--- Set 'State' of 'Follower' to 'CAN SEE'

On Safety
+ Detector is over Obstacle
+ Only One Action When Event Loops
--- Set 'State' of 'Follower' to 'CANT SEE'
--- Create 'MARKER' at 'LOS Detector'
--- Stop Safety Loop and Push Out

The 'State' bit is just an ALterable string. We'll use this later when we're coding the behaviour of the follower AI - how he'll react when he CAN see the player, and when he CANT. He starts off assuming that he can see you (the always event), and then tests for an obstacle in case he can't.

The rest of the event would do this:

Image

It has added a marker where the colision happens.

However, we're not quite finished with that above event yet. We want to find the angle of the line that was drawn, so we use the Advanced Direction object to do that. We want the angle between the follower and the player. So we change our event to:

On Safety
+ Detector is over Obstacle
+ Only One Action When Event Loops
--- Set 'State' of 'Follower' to 'CANT SEE'
--- Set 'Angle' of 'LOS Detector' to Angle between Follower and Player
--- Create 'MARKER' at 'LOS Detector'
--- Stop Safety Loop and Push Out

Our basic objective is to move the Marker away from the colision point at an angle of 90 degrees. We do this twice, once doing it 90 degrees clockwise, and the other time 90 degrees anticlockwise.

This is important. It basically enables us to lift the line away from the wall, making it easier to follow. A diagram:

Image

See how we've split the marker into two? One on the left of the dotted line, one on the right? This represents the way we've moved it right, tested if it was overlapping an obstacle, and then moved it left and done the same.

In this case, the side without an obstacle is the left hand side, so we've moved it in that direction.

This basically lifts the marker away from the wall. The marker is what the Follower will navigate to when he can't see the player. Moving it away from the wall gives him a bit more room to move. I would move it about 16 pixels.

As a quick note, in case you don't know, you can use pythagoras to help with this. For instance:

X = Xpos("MARKER") + sin(LineAngle("LOS DETECTOR"))*16

Will move the marker 16 pixels away from its previous position, along the Line Angle. For the Y coordinate, you do:

Y = Ypos("MARKER") + cos(LineAngle("LOS DETECTOR"))*16



Anyway, what we're left with now is this:

Image

It's starting to take shape isn't it? But this isn't the end.

While the Follower is walking towards the Marker, the Player will still be wandering around, perhaps turning more corners, etc.

So we carry on doing LOS tests, but instead of looking from the Follower to the Player, we look from the NEWEST MARKER to the Player, like this:

Image

If you're careful, you can code it in such a way that it will simply re-use the Line of Sight code above, but using the new marker. If a wall gets in the way again, you end up with another Marker, followed by another, followed by another, like this:

Image

And that's how it works.

To make your Follower follow the path, you can Spread a value inside the Markers, giving them an ID number. Then do the following events:

STATE of Follower = "CANT SEE"
+ ID of Marker = 'NObjects("MARKER")-1'
--- Look in direction of MARKER

Follower colides with Marker
--- Destroy Marker

STATE of Follower = "CAN SEE"
--- Look in direction of PLAYER
--- Destroy MARKER

This will make him always follow the OLDEST Marker that exists. When he touches it, it gets destroyed, so the he has to follow the next one.

When he can see the player, all MARKER objects get instantly destroyed, to clean the memory up a bit.


Some Useful Expressions

An expression or two you may find useful:

Oldest Marker ID = NObjects("MARKER")-1
Second Oldest Marker ID = NObjects("MARKER")-2
Newest Marker ID = 0

When I built my own example of this, I made it so the OLDEST Marker always follows the Follower. And the dotted line is always drawn from the NEWEST Marker to the Player.

If there is only one Marker, then that one is both newest AND oldest, so it acts like the line was being drawn from the Follower to the Player.

The Follower then always looks to the second oldest Marker to provide it with its directions.

Simple

(Note: I haven't listed off all the events, because they're not optimised, and because you wouldn't understand what it was doing just by the events)

 
191 / 9999 * 7 + 191 * 7

Hernan



Registered
  04/03/2003
Points
  707

VIP Member
26th November, 2007 at 17:23:26 -

That giant post is article worthy
I think it's a good solution. It might get into trouble with some more complex mazes though.

 
This space is for rent

DeadmanDines

Best Article Writer

Registered
  27/04/2006
Points
  4758
26th November, 2007 at 17:48:24 -

Lol!

Have a go, it works better than I expected:

http://www.create-games.com/download.asp?id=6921

 
191 / 9999 * 7 + 191 * 7

Eternal Man [EE]

Pitied the FOO

Registered
  18/01/2007
Points
  2955

Game of the Week WinnerHero of TimeLOL SignI am an April Fool
26th November, 2007 at 18:27:57 -

Dang! That was very clever Dines!

 
Eternal Entertainment's Code'n'Art Man

E_E = All Indie


...actually Ell Endie, but whatever.
Image
Image

\/\/olf

Creative Genius

Registered
  06/08/2005
Points
  76

VIP Member
26th November, 2007 at 18:33:37 -

woah, thats pretty cool. altho, i havent totally understood it but the example works really well. ill analyze it and these article-like posts to fully understand the concept. i think i got the basic gist tho.
great stuff. haha, yes, it is pretty smart dines.

Image Edited by the Author.

 
Image

www.OldMansTale.net
Sign the Petition! Go go Go!!
   

Post Reply



 



Advertisement

Worth A Click