Hi to all. This is my first attempt at AS Artificial Intelligence Programming thatâs better than just adjusting the enemieâs _y coordinate relative to the playerâs position.
Short intro, skip this paragraph to get on with the brass tacks. Now, what I want to do, is a top-down game where the player has free 360Âș movement and aiming capabilities. The player character(letâs call him James)'s direction, and _rotation, is always pointing towards the mouse pointer. Pressing forward and backwards means the player walks or backpedals towards the mouse and left and right is sidestepping, relative to the pointer (so if you want to sidestep in a straight line you have to move the mouse so that James keeps facing the same direction). You have to imagine a FPS without the Z coordinate and you can get the feel of it.
Now, my AI is patrolling around a âtile-generatedâ universe, using the main four possible directions, 0(360), 90, 180 and 270. So the little guards about to be shot by James (Iâll leave it to you to guess our Double Oh agentâs family name) would patrol around vertically and horizontally UNTIL THEY SEE THE PLAYER. Then, once they see they player, the guards would be in their âagressive modeâ: theyâd stop moving and concentrate on shooting in the direction of James. Agressive mode is a boolean checked at every frame. If James moves out of the line of sight, the guard resumes patrolling. This whole line of sight thing is the hard part. Iâm able to calculate the hypothenuse of the two coordinates (the guardâs and Jameâs) in real time and to show/trace a boolean which dictates if James is in range of the guard. But I donât know how to trace a line and see if thereâs any obstacles between the guard and James, such as walls or crates.
Finally, my question: Suppose these obstacles are all instances of duplicated movie clips, how do I determine if an object is in the way (thus blocks line of sight) of the guard?
[font=Arial]Supplementary: I tried to have a small mc thatâs like a pixel large and wide and that travels along the hypothenuse of the aforementionned points (guardâs and Jameâs coordinates) and thus that could see if it hits an obstacle along the way, turning a boolean false and thus proving the guard cannot see James. But I cannot make that because the checks have to be made every frame, and the movement of that little reticule has to be done onEnterFrame. So we have to be more creativeâŠand I still havenât found how![/font]
Line of sight should be pretty simple. Range of sight is a whole different story.
First of all, to make your life easier, put all your duplicated clips within a parent so that you only have to check hitTest against one clip. Then put something along the lines of the following in the onEnterFrame event of the guard:
var distance = 200; // how far you want to guard to see
for (var i = 0; i < distance; i++)
{
var radians = _rotation * Math.PI / 180;
var sightX = _x + Math.cos(radians) * i;
var sightY = _y + Math.sin(radians) * i;
if (james.hitTest(sightX, sightY, true))
{ iSeeJames();
break;
}
else if (mystuff.hitTest(sightX, sightY, true))
{
break;
}
}
I was going to suggest using a tile system, but I see that you already have
Anyway, that eases my response a bit. Since you are working in the four cardinal directions this should be simple:
Given the range of sight for the guard, have him look that number of blocks, or tiles ahead of him. You can handle this with a simple for-loop and break. Keep looking down until it comes across an object. If the object so happens to be James, go into aggressive mode, if not, be on your merry way.
Now this implementation requires a little setup:
Youâre going to have to have some sort of matrix representing the actual tiles, and thus, position of every object, which gets updated whenever anything moves. With it, checking for objects in line of sight should be facilitated. The matrix can simply hold the names of each object which you can use for querying position later on.
EDIT: you mentioned that the checks are made every frame? You might want to consider using a setInterval for the checks so you can override the movieâs FPS.
That guardâs MOVEMENT is based on tiles, as is the whole level generation, but I want him to be able to see in front of him and to the side, thus a total of 180Âș (0 being to his left, then going by the front, then finishing at 180 to his right).
Opiate, I donât understand what you said about putting âstuffâ in a âdifferent levelâ. I understand the for()⊠loop, it tests if the _x and _y coordinates of this line of sight intersects with James. I donât think Iâm gonna do a for loop on an enterframe event for every guard (even though thats basically what I did, which lagged like hell).
Thoriphes, I agree with doing a setInterval on the checks, thus reducing the âweightâ of sight checks and, benefically, representing a âreaction timeâ to the guards.
Still, I need just a few specifications, perhaps it is I who does not understand/graps the concept fully enough�
Instead of putting your objects on the stage, put them inside of another clip. That way you donât need to keep track of all the duplicated clips, since you only have to call hitTest with the movie clip that contains them. Thats basically what I said the first time though, isnât it? Oh well⊠(EDIT: To explain the code a bit, mystuff represents the name of a movie clip that contains anything that can block the guardâs view of James.)
What I think made what you did not work, is that a movieclip can only physically move once per frame. Thats probably why it appeared to lag.
I see what youâre saying with setInterval though, using that seems like a good idea.
I also thought of a more âphysicalâ approach (donât read âphysicsâ, read "tangible): to have independant line of sight MovieClips follow and rotate, each one according to a guard. Independant, because else the bouding box of the guard would include his line of sight and, well, that would be bad.
So the guards would roam around and have their lines of sight follow them and rotate along as they scour the land. Difficulty setting could actually make these line of sights visible on easy mode, just like Metal Gear. However I wanted to find a more mathematical approach, hence the thread.
Calculating if James is in the tiles which are within a guardâs line of sight (what I think Thoriphes suggested) is touchy because James can move around with much more agility than the npcâs, so he can be within 1 to 4 tiles at a time. Updating an array with such information (when one of these many tiles could well be a wall) is REALLY touchy.
Iâd rather have ONE formula which decides if agressive mode is on or off, and if itâs on, shoot in the direction of James(or the last ânotedâ direction, if we use setInterval, so that the guard doesnât shoot exactly AT James), and if *agressive mode * is off, then the guard patrols.
Just to add something, Iâve been reading a couple of topics in here, and my game is similar to the one in this thread: http://www.kirupaforum.com/forums/showthread.php?t=60439, only it has a MAP and not just a blank white landscape, thus itâs the reason I need some line of sight!