|
-
Hi! Great AI code! But it's not Actionscript, although the langauge is VERY similar. It's also VERY long. Tell me if you have problems with anything, and tell me what you think abotu the code.
Let me explain a few things:
"%" stands for mod which works like this a%b and returns the remainder of a / b. eg. 10%3 = 1
Built for a level that is 64 by 64, but that can be changed
the random works like this random(a,b), it returns a floating point >= a and < b.
playerscount is the ammount of players in the room.
onwall is like a hit detection for walls.
the command is:
if (onwall(x,y)) {
blah();
}
"^" is equal to power
eg. 9^.5=3
setcharani is a command that set the characters animation. This can easily be changed to gotoAndStop("moving") or whatever.
The properties are set up like this:
players[index].property,the properties used in this code are id (which is either 0 or 1, if it's 0 it's a baddy, of it's 1 it's a human player), and hearts (how many hearts the player has). The properties of the NPC that has the code are simply x, y, dir (ranges from 0 to 3), ect.
Timeout is a countdown (makes a very good loop)
eg.
if (playerenters) {
timeout = 0.05;
}
if (timeout) {
stuff();
timeout = 0.05;
}
There are many flags there are set by the game, ie playerenters, playertouchsme, wasthrown, ect. They're pretty self explanatory.
the message command print something above the NPCs head.
Well.... here we go!
Code:
if (created) {
// Initialize the attributes
showcharacter;
setcharprop #3,head735.gif;
setcharprop #C0,orange;
setcharprop #C1,white;
setcharprop #C2,blue;
setcharprop #C3,red;
setcharprop #C4,black;
setcharprop #2,shield1.gif;
shieldpower = 1;
dir = 2;
swordpower = 1;
hurtdx = 0;
hurtdy = 0;
hearts = 3;
}
if (playerenters || wasthrown) {
// Initialize the this. variables
message;
this.huntspeed = 0.5;
dirgo = {0,-1,-1,0,0,1,1,0};
timeout = 0.05;
this.walkmode = 1;
if (wasthrown && this.walkmode>1) this.walkmode = 1;
this.x1 = 0;
this.x2 = 63;
this.y1 = 0;
this.y2 = 63;
this.speed = 0.4;
if (hearts<=0) {
this.mode = 5; // RESPAWN
this.runcounter = 0;
timeout = 5;
} else {
this.mode = 0;
setcharani idle,;
this.runcounter = int(random(10,40));
}
}
// Walking stuff
if (timeout && this.mode==0) { // WALKING
setcharani walk,;
newx = x + dirgo[dir*2] * this.speed;
newy = y + dirgo[dir*2+1] * this.speed;
this.runcounter--;
if (this.walkmode==1) { // RANDOM
if (this.runcounter>0) {
testx = newx + 1.5 + dirgo[dir*2];
testy = newy + 2+ dirgo[dir*2+1];
if (onwall(testx,testy)) {
dir = (dir+2)%4;
this.runcounter = int(random(0,60));
} else {
x = newx;
y = newy;
}
} else {
this.runcounter = int(random(10,40));
dir = (dir+1+int(random(0,2))*2)%4;
}
} else if (this.walkmode==2) { // LEFTRIGHT
if (dir!=1 && dir!=3) dir = 3;
else {
x = newx;
y = newy;
if ((dir==1 && x<=this.x1) || (dir==3 && x>=this.x2))
dir = (dir+2)%4;
}
} else if (this.walkmode==3) { // UPDOWN
if (dir!=0 && dir!=2) dir = 2;
else {
x = newx;
y = newy;
if ((dir==0 && y<=this.y1) || (dir==2 && y>=this.y2))
dir = (dir+2)%4;
}
} else if (this.walkmode==4) { // RECTANGLE
x = newx;
y = newy;
if ((dir==0 && y<=this.y1) || (dir==1 && x<=this.x1) ||
(dir==2 && y>=this.y2) || (dir==3 && x>=this.x2))
dir = (dir+3)%4;
}
if (this.walkmode>1 && this.runcounter<=0)
this.runcounter = 20;
message;
timeout = 0.05;
}
// Sword attacking stuff
if (timeout && (this.mode==0 || this.mode==2)) {
// Look for players
mindist = 1000;
for (index=0; index<playerscount; index++)
if (players[index].hearts>0 && players[index].id>=0) {
dx = players[index].x - x;
dy = players[index].y - y;
if (abs(dx)>abs(dy)) {
if (dx>0) pdir=3; else pdir=1;
} else {
if (dy>0) pdir=2; else pdir=0;
}
if (pdir==dir) {
dist = (dx*dx+dy*dy)^0.5;
if (dist<mindist) {
cansee = 1;
if (abs(dx)>abs(dy)) k = int(abs(dx));
else k = int(abs(dy));
for (j=0; j<=k-2; j++)
if (onwall(x+1.5+dx*j/k,y+2+dy*j/k)) cansee = 0;
if (cansee!=0) {
mindist = dist;
aimplayer = index;
this.aimx = players[index].x;
this.aimy = players[index].y;
}
}
}
}
if (mindist<=3) {
this.runcounter = -1;
this.mode = 3; // SLAYING
setcharani sword,;
timeout = 0.05;
} else if (mindist<20) {
if (this.mode!=2) message Stop!;
this.runcounter = 100;
this.mode = 2; // HUNTING
} else timeout = 0.05;
}
if (timeout && this.mode==3) { // SLAYING
this.runcounter++;
if (this.runcounter>4) {
this.runcounter = 100;
this.mode = 2; // HUNTING
setcharani idle,;
}
message;
timeout = 0.05;
}
if (timeout && this.mode==2) { // HUNTING
setcharani walk,;
this.runcounter--;
if (this.runcounter>0 && aimplayer<playerscount && players[aimplayer].hearts>0) {
// Get new direction
dx = players[aimplayer].x-x;
dy = players[aimplayer].y-y;
if (abs(dx)>abs(dy)) {
if (dx>0) dir=3; else dir=1;
} else {
if (dy>0) dir=2; else dir=0;
}
// Test if we can do a step
dx = this.aimx-x;
dy = this.aimy-y;
if (abs(dx)<=1 && abs(dy)<=1) {
this.aimx = players[aimplayer].x;;
this.aimy = players[aimplayer].y;
dx = this.aimx-x;
dy = this.aimy-y;
}
if (abs(dx)>abs(dy)) {
if (dx>0) testdir=3; else testdir=1;
} else {
if (dy>0) testdir=2; else testdir=0;
}
len = (dx*dx+dy*dy)^0.5;
addx = (dx/len)*this.huntspeed;
addy = (dy/len)*this.huntspeed;
testx = x + 1.5;
testy = y + 2;
if (!onwall(testx+addx,testy+addy)) {
// Do a step
x += addx;
y += addy;
} else if (!onwall(testx+addx,testy)) x += addx;
else if (!onwall(testx,testy+addy)) y += addy;
} else {
this.mode = 0; // WALKING
this.walkmode = 1; // RANDOM
this.runcounter = int(random(10,40));
setcharani idle,;
dir = (dir+2)%4;
message;
}
timeout = 0.05;
}
// Hurting stuff
if (wa**** && this.mode!=1 && hearts>0) {
dx = x-playerx;
dy = y-playery;
len = (dx*dx+dy*dy)^0.5;
hurtdx = dx/len;
hurtdy = dy/len;
setcharani hurt,;
hideimg 1;
hearts -= playerswordpower/2;
}
if ((hurtdx!=0 || hurtdy!=0) && isleader && this.mode!=4) {
this.hurtdx = hurtdx;
this.hurtdy = hurtdy;
hurtdx = 0;
hurtdy = 0;
this.mode = 1; // HURTED
this.runcounter = 20;
setcharani hurt,;
if (hearts<=0) {
this.mode = 4; // DYING
this.runcounter = 24;
setcharani dead,;
}
timeout = 0.05;
}
if (timeout && this.mode==1) { // HURTED
this.runcounter--;
if (this.runcounter>10) {
testx = x + 1.5 + this.hurtdx*2;
testy = y + 2+ this.hurtdy*2;
if (!onwall(testx,testy)) {
x += this.hurtdx;
y += this.hurtdy;
}
}
if (this.runcounter<=0) {
if (swordpower>0) this.mode = 2; // HUNTING
else this.mode = 0; // WALKING
this.runcounter = 100;
setcharani idle,;
}
timeout = 0.05;
}
if (timeout && this.mode==4) { // DYING
if (this.runcounter>0) {
message;
if ((this.runcounter%2)==0) dir = (dir+3)%4;
this.runcounter--;
if (this.runcounter<=0) {
gift = random(0,100);
if (gift<10) lay greenrupee;
else if (gift<15) lay bluerupee;
else if (gift<30) lay heart;
} else timeout = 0.05;
}
}
Hope you liked it,
Somar
[Edited by Somar on 06-12-2001 at 06:13 PM]
-
Senior Member
-
Thats some nice code... did you make that yourself?
-
Senior Member
If I get this correctly the basic walk code is hit-turn based. Basicaly the guys keeps walking till it hits something then turns. Is that correct ?
mad_sci
-
Booya Climber: Someone made a very simple code, so i just used the same vars, and hugely expanded it =]
Mad-Sci: Well there are a bunch of modes
stand complete still (not used)
moving (has 3 sub modes)
attacking
getting hurt
dying
the mode starts walking. While walking, it'll do a random to find out whether it's moving up and down, left and right or in a rectangle. Mean while, a counter (the var is runcounter) is random composed, it then begisn to counbt downset. When it hits 0 a random new walking method is selected. The NPC also checks the x's and y's of all the players in the room, if the hero gets in the site of the NPC, and the hero is not behind a wall, the attacking mode is initiated. The NPC will follow the hero, and if it gets close enough, will attack, and possibly, kill >=].If the hero hits the NPC, the getting hurt mode is activated, but before the animation of getting hurt, it checks to see if the NPC's hearts are <=0. If they are, the dying animation is instituted.
I'll convert it to actionscript soon.
-
Senior Member
Im interested in moving thing in a maze. Solving a maze is very cool exersise. here is what I came up with.
1. check wich directions are available for moving.
Pseudo code:
if ( Im currantly going up ){
if ( hero_x < my_x and I can move left){ move left}else
if ( hero_x > my_x and I can move right){ move right)else
if ( I can move left){ move left}else
if ( I can move right){ move right}}else
if ( Im currantly goin down){ etc..etc.. for all 4 dirs.
now I have one variable dir wich is 1=up,-1=down,2=right,-2=left. each time I change dir I change one var..
http://members.nbci.com/savco/tutorials/mazeAI.swf
now it looks like the red_buddy chooses strange way of finding the green ball it eventually will..just stay on one place.
mad_sci
-
Well one of your problems, that you probably haven't enountered is if the AI is lower and far to the right then
and it can go up and left. Since "I am currently going up" flag is first, he will ALWAYS turn left and never up, in this perdicament. Plus your AI, started to follow me after a while! Accept when it had the choice to go down or left, down and to the left of it, it went down, instead of left, which was closer. but fear not! I have THE most amazing code for detecting direction, (scripted by me of course) MUAHAHA! I'll post it when i get back from school.
now I have one variable dir wich is 1=up,-1=down,2=right,-2=left. each time I change dir I change one var..
I don't quite understand what those vars correspond to.
IMO, theres no point in the else if's, since it's either on one side or the other, you could you simply use an else.
You might want to impliment this too:
//inizialize
// Find a random number above .3
while (counter<.3) {
counter = random();
}
counter*=50;
if (counter>0) {
if ( hero._x < my_x and Icanmoveleft = true) {
moveleft();
}
...
} else {
changedir();
while (counter<.3) {
counter = random();
}
counter*=50;
}
...
counter--;
-
Here it is!
There are two ways of finding the direction superbly. These codes is 100% mine, and i converted it to ActionScript
just for you ;] Just paste either one inside of your AI MC.
This is the ABS one:
Code:
if (Math.abs(Math.abs((_root.hero._y)-(y))) < Math.abs(Math.abs((_root.hero._x)-(_x)))){
if ((_root.hero._x)<(_x)){
dir = 1;
}
if ((hero._x)>=(_x)){
dir = 3;
}
}
if (Math.abs(Math.abs((_root.hero._y)-(_y))) >= Math.abs(Math.abs((_root.hero._x)-(_x)))){
if ((_root.hero._y)<(_y)){
dir = 0;
}
if ((_root.hero._y)>=(_y)){
dir = 2;
}
}
And this is the trigonometerical one (I programmed it to work with any number of directions, as long as they all have equal angle (4 directions has 90 degrees while 3 directions has 120 degrees) works with any number of directions):
Code:
dir = 4; //number of directions
dir = 360 / dir;
dx = _root.hero._x-_x;
dy = _root.hero._y-_y;
distance = Math.sqrt(dx*dx+dy*dy);
movex = dx/distance;
movey = dy/distance;
if (_root.hero._x<_x) {
if (_root.hero._y<_y) {
angle = Math.asin(movex);
angle = 180/Math.PI*angle;
angle += 360;
}
if (_root.hero._y>_y) {
angle = Math.acos(movey);
angle = 180/Math.PI*angle;
angle += 180;
}
}
if (_root.hero._x>_x) {
if (_root._ymouse<_y) {
angle = Math.asin(movex);
angle = 180/Math.PI*angle;
}
if (_root.hero._y>_y) {
angle = Math.acos(movex);
angle = 180/Math.PI*angle;
angle += 90;
}
}
side = int(angle/dir)+1;
Hope this helps too,
Somar
-
Senior Member
Ok been there, check this out:
http://members.nbci.com/savco/games/snake/snake2.swf
now lets put this in the maze situation. See in your code you will force the baddie to go towards the hero, but this is not always the optimal way. Sometimes going away from the hero if preferable then strait to it for example if you want to go arround a wall.. how do you deal with it ? A+ algorithm for example will explore all posible nodes for their fitness.
Otherwise the code is perfect..
mad_sci
-
I don't know algorithm, but I do know that that snake game, doesn't use it, and if it does it shouldn't have, and I also know that it's very proccessor intensive.
BTW do you like my direction scripts?
-
Senior Member
Yes of course. You have working examples BTW..I want to see it in action.
mad_sci
-
A few things
This AI script is NOT for a tile-based world, The AI should be able to move around freely, unless of course it hits a wall or tree or what not.
A working example of directional movement using trigonmeterical formula can be found here (It's Sidra, I'm not sure if you've seen the beta yet =\)
And i I said I don't know alogrithm, lol, I meant I don't know A+ Alogrithm, what is it? Just an advanced alogrithm?
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|