View Full Version : I wanna learn really -basic- AI >_<
elion
January 1st, 2004, 09:35 PM
Since I have some pretty basic scripting skills, all the AI tutorials and I stuff I look at are too confusing, so I wanna start with some really basic stuff :pleased:. To start, how could I make an object move twords another directly, no matter where that object moves too? :puzzle:
Marz
January 1st, 2004, 09:41 PM
Hmm.. You want extremely basic AI then...
Here is a small code example for you then.
// Assuming you have two movieclips
// One : player
// Two : enemy
if(player._x > enemy._x)
{
enemy._x += 5;
}
else if(player._x < enemy._x)
{
enemy._x -= 5;
}
if(player._y > enemy._y)
{
enemy._y += 5;
}
else if(player._y < enemy._y)
{
enemy._y -= 5;
}
elion
January 1st, 2004, 09:59 PM
Yumm... Code that actually looks simple!! :P
elion
January 1st, 2004, 10:02 PM
Hmm... I put this on the frame right? Cause it 'aint working.
Marz
January 1st, 2004, 10:06 PM
Well.. You have to put it in an event handler of some sort.. Like..
_root.onEnterFrame = function()
{}
Then put it in the curlies.. :)
elion
January 1st, 2004, 10:08 PM
I have no idea what that means, but it worked so thanks! :D
elion
January 1st, 2004, 10:16 PM
Hmm, what would I do about having that MC shoot things at the player? (-:
Marz
January 1st, 2004, 10:17 PM
EVENT handlers my friend...
_root.onLoad = function()
_root.onEnterFrame = function()
_button.onPress = function()
Very, very powerful tools :)
Marz
January 1st, 2004, 10:19 PM
When do you want it to shoot? Randomly?
elion
January 1st, 2004, 10:23 PM
Yeah, I guess :beam:
Marz
January 1st, 2004, 10:36 PM
Okay... I'll work something up later tomorrow... :) I'm half sleeping now ;)
elion
January 1st, 2004, 10:36 PM
Mkay. :)
Hm, well I have absolutly nothing to do till then, cause I need it for my game :x
Johnny64
January 2nd, 2004, 08:46 AM
Hoi
beat you there Marz :P
// enemy shooting
if (!(random(20))) {// if the random number is 0 the and new projectile is made
this.depth++; // increase depth so that each projectile has its own depth
var proj = this.projectile.duplicateMovieClip("projectile"+depth, depth);// duplicates a new projectile
proj._x = enemy._x; //places the new projectile on the same place of the enemy
proj._y = enemy._y;
proj.Xmov = Math.random()*10-5; // sets a random X en Y speeds (-5 to 5)
proj.Ymov = Math.random()*10-5;
proj.onEnterFrame = function() {
this._x += this.Xmov;// moves the projectile
this._y += this.Ymov;
this.time++;// increase time
if (this.time>50) {// checks if time is up 50 frames
this.removeMovieClip(); // delete the projectile
}
};
}
i hope i commented it well :to: thats a mouth full
here is a fla if you want it :)
elion
January 2nd, 2004, 01:34 PM
Cool :D. Now, how can I make it shoot -directly- at the player? That would be nice to know too. (-:
Edit: Oh, and how do I make duplicates work with AS?
Johnny64
January 2nd, 2004, 06:13 PM
speed = 10
if (!(random(20))) {
// if the random number is 0 the and new projectile is made
this.depth++;
// increase depth so that each projectile has its own depth
var proj = this.projectile.duplicateMovieClip("projectile"+depth, depth);// duplicates a new projectile
proj._x = enemy._x;//places the new projectile on the same place of the enemy
proj._y = enemy._y;
var xdiff = player._x-enemy._x;//finds de x y distance between the player and the enemy
var ydiff = player._y-enemy._y;
var radians = Math.atan2(ydiff, xdiff);// find the ip-radians(angle) between the player and the enemy
proj.Xmov = speed*Math.cos(radians);// finds what the x y speed must be to make the projectile move to the player
proj.Ymov = speed*Math.sin(radians);
proj.onEnterFrame = function() {
this._x += this.Xmov;// moves the projectile
this._y += this.Ymov;
this.time++;// increase time
if (this.time>50) {// checks if time is up 50 frames
this.removeMovieClip();// delete the projectile
}
};
}
here :D
Oh, and how do I make duplicates work with AS?
don't understand :huh:
:)
elion
January 2nd, 2004, 08:17 PM
I want know how to make duplicate movie clips work with AS, because when you duplicate them, they all have the same instance names which doesn't work with AS >_<
Johnny64
January 3rd, 2004, 01:35 PM
OK
well no they can't have the same names. :P
var proj = this.projectile.duplicateMovieClip("projectile"+depth, depth);
In the example I used
var proj
But this is not the projectiles name, the name is just saved in there to make it easier.
The real names are projectile0, projectile1, projectile2…..
MovieClip.duplicateMovieClip(NewName, Depth);
I used "projectile"+depth
Depth increase very time a new projectile is made.
If depth = 5 at one point then if you do your maths "projectile"+depth = “projectile5”
So that’s its I think :D
M64 @_@
Marz
January 4th, 2004, 01:24 AM
Originally posted by Master64
Hoi
beat you there Marz :P
// enemy shooting
if (!(random(20))) {// if the random number is 0 the and new projectile is made
this.depth++; // increase depth so that each projectile has its own depth
var proj = this.projectile.duplicateMovieClip("projectile"+depth, depth);// duplicates a new projectile
proj._x = enemy._x; //places the new projectile on the same place of the enemy
proj._y = enemy._y;
proj.Xmov = Math.random()*10-5; // sets a random X en Y speeds (-5 to 5)
proj.Ymov = Math.random()*10-5;
proj.onEnterFrame = function() {
this._x += this.Xmov;// moves the projectile
this._y += this.Ymov;
this.time++;// increase time
if (this.time>50) {// checks if time is up 50 frames
this.removeMovieClip(); // delete the projectile
}
};
}
i hope i commented it well :to: thats a mouth full
here is a fla if you want it :)
I think the terms he stated were..
*simple*
*lol*
Johnny64
January 4th, 2004, 10:19 AM
"Enemy AI that can shoot AND aim at the player " *simple* :smirk:
Well its good to come with some thing hard so when FireDrake101 and onthers see it, it would be like :h: *look at it better * and then :!: *its simple* and then its FireDrakeGuru
:beam:
elion
January 4th, 2004, 06:30 PM
I couldn't even tell if you explained how to make duplicates work a few posts ago or not, go me! =)
Johnny64
January 5th, 2004, 04:12 AM
ok so i suck at expleining Marz! your turn again =)
junahu
January 5th, 2004, 09:59 AM
i ++
duplicateMovieClip(_root.mymovieclip0,"mymovieclip" + i, i )
whenever the movieclip is duplicated the new one is called
"mymovieclip" and the value of i is stuck on the end
e.g.
mymovieclip1
mymovieclip2
mymovieclip3
mymovieclip4
the depth level of the movie is the same as the number at the side in this case. Two movieclips can't have the same depth. An easy way to remove earlier movieclips would be to reset i once it reaches a certain number or the framerate drops.
I bet that didn't help in the slightest huh?
Johnny64
January 5th, 2004, 10:46 AM
Well you did better then me :P
I could fallow it ;) *lol*
Marz
January 5th, 2004, 03:34 PM
I'll start explaining it as soon as I get off work tonight... But I'll only have 2 hours for it because I'll be turning something tonight at midnight and will be doing something... :whistle:
*lol*... But anyways... It was extremely simple for me man.. But to someone else it probably wouldn't be ;)
I'll write up something buddy :D
elion
January 5th, 2004, 06:40 PM
I feel really retarded right now :crazy:
Marz
January 6th, 2004, 12:23 AM
Don't feel retarded my friend... It's all a learning experience and I can say Game Programming is about the hardest out of all programming to do.. You have to know how to design a reliable and working engine that can go a certain speed at all times on a slower than usual machine that's out of date anyways. :)
Optimization is fun.. *lmao*
Now.. On with the coding.. :)
_root.onEnterFrame = function()
{
// Assuming you have two movieclips
// One : player
// Two : enemy
if(player._x > enemy._x)
{
enemy._x += 5;
}
else if(player._x < enemy._x)
{
enemy._x -= 5;
}
if(player._y > enemy._y)
{
enemy._y += 5;
}
else if(player._y < enemy._y)
{
enemy._y -= 5;
}
}
This was the codeset I gave you before... Let's add some new stuff on to this and create a couple of functions.. Shall we? :)
Well.. Let's see what we need to create.. An enemy that randomly shoots at the player... Nothing too major.. Let's break this up into what we shall need to pull this off though..
• a function that handles the shots
• a timer that informs when to check for the next random shot
• a function that informs which direction to shoot
Allright... That should be everything. Out of this.. We know that we need two new functions... And a timer of some sorts. Let's handle the timer first.. It's the easiest by far to handle...
_root.onLoad = function()
{
actionTimer = 0;
actionDelay = 45;
}
This little bit of code states that.. When the movie is first loaded completely (when they click the link to see it or when it finally loads), it will set up two variables.. actionTimer and actionDelay...
actionTimer is an integer that will hold the amount of frames that is needed to get to the other variable before going back to 0 again...
Every frame actionTimer will ascend by 1 until it reaches actionDelay or in this case.. 45... Then, we will set that up to handle actions like possibly shooting at the player character. That is coming up... tomorrow... Because I'm going out and about now.. :) Sorry bro..
Allright.. Here is the rest of the tutorial. I figured I'd place it in the same post to keep things better intact.
Let's start creating some functions now.. The ones that will handle everything about the game :)
function findDirection()
{
tempx = Math.abs(_root.player._x - _root.enemy._x);
tempy = Math.abs(_root.player._y - _root.enemy._y);
if(tempy < tempx)
{
if(_root.player._y > _root.enemy._y)
{
_root.shotDirection = "DOWN";
}
else
{
_root.shotDirection = "UP";
}
}
else
{
if(_root.player._x > _root.enemy._x)
{
_root.shotDirection = "RIGHT";
}
else
{
_root.shotDirection = "LEFT";
}
}
}
That's a whole bunch of stuff for a simple function.. Isn't it?!
And that is suppose to be simple? Well of course.. And I'll walk you through it right now :D
The first two lines state some simple statements saying to take the absolute values of the x location and y location of player and subtracting off it the x and y locations of the enemy. Taking the absolute value of this means that if the value is negative, it will be positive, and if it is positive, it stays positive. :D
SO.. We do a simple test... If tempy is less than tempx.. That means that the enemy is closer to the player in the y axis than he is in the x axis.. So now we know that the enemy should shoot either up or down.
Now.. We do a simple real location test.. If the players y location is greater than the enemy's y location... Then the player is below the enemy.. Therefore.. he should shoot in the most logical of directions.. DOWN... If not.. Then shoot UP instead.
And everything else pretty much follows those simple rules in these equations.
But.. Now that we have determined which direction the enemy should shoot... How do we actually get the guy to shoot a real life bullet anyways?
Well, this is typically not an easy thing. You may say it could be... But really.. It isn't. Unless you only have the enemy shoot one shot until it reaches the end of a screen or it dissipates... In which case... I'm going to show you..
First though.. Let's do the actual shooting of the bullet...
function shootBullet(whatDirection, shotBy)
{
if(_root[shotBy+"shooting"] == 0)
{
if(whatDirection == "UP")
{
_root[shotBy+"Bulletx"] = 0;
_root[shotBy+"Bullety"] = -5;
}
else if(whatDirection == "DOWN")
{
_root[shotBy+"Bulletx"] = 0;
_root[shotBy+"Bullety"] = 5;
}
else if(whatDirection == "LEFT")
{
_root[shotBy+"Bulletx"] = -5;
_root[shotBy+"Bullety"] = 0;
}
else
{
_root[shotBy+"Bulletx"] = 5;
_root[shotBy+"Bullety"] = 0;
}
_root[shotBy+"bullets"].duplicateMovieClip(shotBy+"bullet", _root.numz);
_root.numz = _root.numz + 1;
_root[shotBy+"shooting"] = 1;
}
}
Wow.... That's alot of stuff.. And it looks hella confusing too doesn't it? There is a reason for this subtle confusion and that;'s because of these lines...
_root[shotBy+"Bulletx"]
Yeah.. Looks confusing doesn't it? shotBy will be one of two letters... "player" or "enemy" So.. player bullet or enemy bullet. This just allows us to save alot of code space and it optimizes our code alot.
Now... We need to change around our _root.onLoad function top include a couple more variables...
_root.onLoad = function()
{
actionTimer = 0;
actionDelay = 45;
_root.shotDirection = "UP";
_root.playerBulletx = 0;
_root.playerBullety = 0;
_root.enemyBulletx = 0;
_root.enemyBullety = 0;
_root.numz = 5;
_root.playershooting = 0;
_root.enemyshooting = 0;
}
Now.. We have our new variables set.. And I set up these six variables as global variables by using the _root command and placing them like that. :)
Now... The last little bit of code we need can be found in the two bullets themselves... Start by creating the two movieclips... platerbullets and enemybullets.
In playerbullets place this code...
on(enterFrame)
{
if(this._name != "playerbullets")
{
this._x += _root.playerBulletx;
this._y += _root.playerBullety;
}
if(this.hitTest(_root.enemy))
{
_root.enemy.gotoAndPlay("death");
this.removeMovieClip();
_root.playershooting = 0;
}
else if(this._x > 550 || this._x < 0)
{
_root.playershooting = 0;
this.removeMovieClip();
}
else if(this._y > 400 || this._y < 0)
{
_root.playershooting = 0;
this.removeMovieClip();
}
}
In enemybullets place this code...
on(enterFrame)
{
if(this._name != "enemybullets")
{
this._x += _root.enemyBulletx;
this._y += _root.enemyBullety;
}
if(this.hitTest(_root.player))
{
_root.player.gotoAndPlay("death");
this.removeMovieClip();
_root.enemyshooting = 0;
}
else if(this._x > 550 || this._x < 0)
{
_root.enemyshooting = 0;
this.removeMovieClip();
}
else if(this._y > 400 || this._y < 0)
{
_root.enemyshooting = 0;
this.removeMovieClip();
}
}
Wow... Alot of code... But hey.. You wnated it simple.. Dammit.... And we have to make a change yet in the onEnterFrame in our main document too now! *lol*... This is the last of em man.. :)
_root.onEnterFrame = function()
{
// Assuming you have two movieclips
// One : player
// Two : enemy
if(player._x > enemy._x)
{
enemy._x += 5;
}
else if(player._x < enemy._x)
{
enemy._x -= 5;
}
if(player._y > enemy._y)
{
enemy._y += 5;
}
else if(player._y < enemy._y)
{
enemy._y -= 5;
}
if(actionTimer == actionDelay)
{
if(Math.random()*100 < 10)
{
findDirection();
shootBullet("_root.shotDirection", "enemy");
actionTimer = 0;
}
else
{
actionTimer++;
}
}
}
And there we go... I think... I'm kind-a out of it.. So if this doesn't work.. Just tell me ! *lmao*
Johnny64
January 6th, 2004, 01:18 PM
Originally posted by FireDrake101
I feel really retarded right now :crazy:
Sorry m8, i didn't intend to make you feel retarded. I asked some really stupid Q's in my time :blush: but you will get the hang of it after some time and then it would look simlpe to you too ;)
elion
January 6th, 2004, 05:28 PM
:)
GreenLantern
January 7th, 2004, 03:38 AM
This is a great thread, very educational. I will be watching it.
Thanks!
SeiferTim
January 7th, 2004, 06:42 PM
Game Programming is about the hardest out of all programming to do..
True Dat.
Take it from me. I'm currently working on a game myself. The major problem that I see people make is not with the code itself, but it is with the planning process for the game itself... and FireDrake seems to be making a similar mistake...
I noticed, with one of his firsts posts, that FireDrake seems to be adding things as he goes... This is a BIG mistake. Step one is to plan ahead, and determine EXACTLY what it is you want to do, and then figure out how you're going to do it.
For instance:
say you want to make a "cool space shooter game". And start coding things, make a cool space ship, and some cool graphics, and figue out how to make things fly around and shoot, and it works great, then you decide you want to make the enemy ships do something special. Now you have to go back into the code, and append more lines, and tweak things to get it going. After hours of tweaking, you arrive with the desired effect. Then you decide to add another feature... here's several more hours of testing, tweaking, and editing, which probably will end up in messing up one of the original features. This is wasting time, and effort, not to mention adding to frustration.
Now, example 2:
Same game, but this time, you PLAN EVERYTHING before hand!
Decide from the begining: The player's Ship should do this, this, and this, and shouldn't be allowed to do that. And the enemies behave like this. WRITE IT DOWN! Make a Design Document if you have to! Sketch out ideas on how you want enemies to look, move, etc. This way, when you sit down to code, you can look, and say: "Hey! If this enemy moves left at this point, and then goes right over here, I can use an If/Then Statement right off the bat!". Believe me, this will help A LOT! And cut down on all the recoding time. Determine your goals before you begin coding!
It sounds like you're trying to do more Arcade-type games, which won't need much in the way of story, so you should probably just sit down and come up with some fun, and interesting characters, enemies, etc, and write down ideas on how they behave, and interact with each-other, and other characters.
I'm working on an RPG. Which requires an in-depth story, and lots of fun features. Short of a few little "Engine Test" applications, I haven't even begun to code ANYTHING! If'you're interested in taking a look at my design doc, goto: http://seifertim.no-ip.com
Marz
January 7th, 2004, 07:02 PM
HEy seifer.. Nicely stated.. I think you might find my game programming tutorials I'm making here to be quite along the same lines.. ;)
Look into the resources section found in this forum section... Should be stickied.. And go to the link Marz's game Programming Tutorials.. Tell me what you think so far.. :)
elion
January 7th, 2004, 07:15 PM
I didn't start a game from when I started this post, but have been using it as a way to learn scripting for my future games, and I would also like to include the thing we're talking about now in a game that's already got a lot in it :).
Edit: And as I wait for Marz' next lession, I go play FFX-2!!!11 :)
Johnny64
January 8th, 2004, 11:29 AM
Hoi
Well the first time I made a game, I didn't plan at all :be:. And yes, it was the worst game I had ever see and made . But I did learn allot :D by " tweaking" at the code debuging. I learned the syntax and other small things that way. But if you what to make a good game, Plan! :)
SeiferTim
January 8th, 2004, 12:24 PM
Hey Marz, I've noticed that you tend to have a very good foundation for all your examples. I've been reading as many of these posts as I could since finding this section yesterday. I think I'll be posting often :)
I'm planning on building my Game with a combination of Visual Basic and Flash, I have a tutorial that kind of demonstrates the underlying principles behind what will become my RPG - http://www.kirupa.com/developer/mx/flashvb.htm
I plan on learning a few things from you guys, and hope I can share what I know as well.
APDesign
January 8th, 2004, 12:32 PM
Hey, thanks for making that tutorial by the way, I used it about a year ago when making a CD extra thing for my bands CD (see link.) And while I'm getting off topic by thanking people for tutorials, thanks for the cool AI/game tuturials Marz :thumb:
I always start to make a game and then just give up, but hopefully I'll actually follow through one of these days, and I'm sure I'll have some questions if I do. :D
elion
January 8th, 2004, 05:48 PM
You die Marz? I'm still waitinnng!!!!
elion
January 9th, 2004, 05:58 PM
AHHHH!!!11
Marz
January 9th, 2004, 11:48 PM
Nope.. Just got done working a 14 hour shift man... *lol*... My brain has been fried out.. But no fault guys... I should be able to trace back to where I was tomorrow afternoon.. I think I actually have a night off :)
elion
January 10th, 2004, 07:34 PM
Yay :D
Marz
January 11th, 2004, 12:36 AM
Updates have been made... Check them out in the reply a couple messages above :)
elion
January 11th, 2004, 02:47 PM
"But.. Now that we have determined which direction the enemy should shoot... How do we actually get the guy to shoot a real life bullet anyways?"
Thats a **** good question :D Well, at least by my standards :P
Marz
January 11th, 2004, 06:53 PM
*lol*... Yeah man.. Like I said.. Buys.. So they com eout in parts ;)
elion
January 16th, 2004, 06:38 PM
Still waitin' for the next one >.<
Marz
January 17th, 2004, 02:31 AM
Understandable... Just relax though man.. I'm trying to work these **** things in on my busy schedule... If I had net connectivity at the mall.. I'd do it while I was working.. :D
Marz
January 17th, 2004, 08:40 PM
Found in playerbullets movieclip
on(enterFrame)
{
if(this._name != "playerbullets")
{
this._x += _root.playerBulletx;
this._y += _root.playerBullety;
}
if(this.hitTest(_root.enemy))
{
_root.enemy.gotoAndPlay("death");
this.removeMovieClip();
_root.playershooting = 0;
}
else if(this._x > 550 || this._x < 0)
{
_root.playershooting = 0;
this.removeMovieClip();
}
else if(this._y > 400 || this._y < 0)
{
_root.playershooting = 0;
this.removeMovieClip();
}
}
Found in enemybullets movieclip
on(enterFrame)
{
if(this._name != "enemybullets")
{
this._x += _root.enemyBulletx;
this._y += _root.enemyBullety;
}
if(this.hitTest(_root.player))
{
_root.player.gotoAndPlay("death");
this.removeMovieClip();
_root.enemyshooting = 0;
}
else if(this._x > 550 || this._x < 0)
{
_root.enemyshooting = 0;
this.removeMovieClip();
}
else if(this._y > 400 || this._y < 0)
{
_root.enemyshooting = 0;
this.removeMovieClip();
}
}
Found in Main Looping Frame
_root.onLoad = function()
{
actionTimer = 0;
actionDelay = 45;
_root.shotDirection = "UP";
_root.playerBulletx = 0;
_root.playerBullety = 0;
_root.enemyBulletx = 0;
_root.enemyBullety = 0;
_root.numz = 5;
_root.playershooting = 0;
_root.enemyshooting = 0;
}
function shootBullet(whatDirection, shotBy)
{
if(_root[shotBy+"shooting"] == 0)
{
if(whatDirection == "UP")
{
_root[shotBy+"Bulletx"] = 0;
_root[shotBy+"Bullety"] = -5;
}
else if(whatDirection == "DOWN")
{
_root[shotBy+"Bulletx"] = 0;
_root[shotBy+"Bullety"] = 5;
}
else if(whatDirection == "LEFT")
{
_root[shotBy+"Bulletx"] = -5;
_root[shotBy+"Bullety"] = 0;
}
else
{
_root[shotBy+"Bulletx"] = 5;
_root[shotBy+"Bullety"] = 0;
}
_root[shotBy+"bullets"].duplicateMovieClip(shotBy+"bullet", _root.numz);
_root.numz = _root.numz + 1;
_root[shotBy+"shooting"] = 1;
}
}
function findDirection()
{
tempx = Math.abs(_root.player._x - _root.enemy._x);
tempy = Math.abs(_root.player._y - _root.enemy._y);
if(tempy < tempx)
{
if(_root.player._y > _root.enemy._y)
{
_root.shotDirection = "DOWN";
}
else
{
_root.shotDirection = "UP";
}
}
else
{
if(_root.player._x > _root.enemy._x)
{
_root.shotDirection = "RIGHT";
}
else
{
_root.shotDirection = "LEFT";
}
}
}
_root.onEnterFrame = function()
{
// Assuming you have two movieclips
// One : player
// Two : enemy
if(player._x > enemy._x)
{
enemy._x += 5;
}
else if(player._x < enemy._x)
{
enemy._x -= 5;
}
if(player._y > enemy._y)
{
enemy._y += 5;
}
else if(player._y < enemy._y)
{
enemy._y -= 5;
}
if(actionTimer == actionDelay)
{
if(Math.random()*100 < 10)
{
findDirection();
shootBullet("_root.shotDirection", "enemy");
actionTimer = 0;
}
else
{
actionTimer++;
}
}
}
And everything is explained on the first page in the original post.
jaywar
January 23rd, 2004, 11:03 AM
I'm having trouble getting this to work in MX. Even if I cut and paste from the "final" example of the full game program. Any ideas? Does someone have a .fla they want to make available so I can see what I'm doing wrong? Thanks!
Here is a small code example for you then.
// Assuming you have two movieclips
// One : player
// Two : enemy
if(player._x > enemy._x)
{
enemy._x += 5;
}
else if(player._x < enemy._x)
{
enemy._x -= 5;
}
if(player._y > enemy._y)
{
enemy._y += 5;
}
else if(player._y < enemy._y)
{
enemy._y -= 5;
}
[/B]
InsaneMonk
January 23rd, 2004, 10:46 PM
grrrr... post the "problem" and we will gladly help you
Powered by vBulletin® Version 4.1.10 Copyright © 2012 vBulletin Solutions, Inc. All rights reserved.