Theres quite a few indi developers in the community that dont know where to start when it comes to AI. It makes sense, how do you make a computer do what a human would do? It seems difficult, but the basis behind AI is pretty straight forward. If event A happens, do event B. If im shot, run in a random direction. If im close to an enemy, follow the enemy. If Im very close to an enemy, shoot the enemy. Etc.
To ease the process a bit I made some basic functions to handle the main things you'll find AI "bots" doing. Those being;
- Traveling to a destination
- Turning to look at a destination
- Running from a destination
With the 3 functions you can expand them to do a lot of different things. Instead of travelling to a static point in 3D space, you could travel to a player's old position, making the bot follow 2the player. You then wouldn't have to take into concideration collisions, as the player the bot is following would do so for the bot (ofcourse there are exceptions). You could use the evade function in unison with the travel function to set up a race track, making the bots travel towards the waypoints on the track, while "evading" or staying away from other players and the walls.
These aren't meant for ground breaking intelligence in AI, its just a starter kit for newcommers that are trying to figure out the logic behind how some versions of AI work. I might expand on it later, but for now the system is fairly small.
The functions;
FUNCTION AI_travel(bot,x#,y#,z#,distance#,speed#)
`store the bot's current position
botX# = OBJECT POSITION X(bot)
botY# = OBJECT POSITION Y(bot)
botZ# = OBJECT POSITION Z(bot)
`calculate the distance between the bot and the new location to travel to
botDist# = math_getDist3D(botX#,botY#,botZ#,x#,y#,z#)
`if the bot is less than the specified allowed distance away,
`make the bot face the new location and move forward
IF botDist# > distance#
POINT OBJECT bot,x#,y#,z#
MOVE OBJECT bot,speed#
ELSE
`If the task is completed, return a 1 signifying completion.
complete = 1
ENDIF
ENDFUNCTION complete
FUNCTION AI_look(bot,x#,y#,z#,cycles,allowance#)
`store the bot's current angles
botXA# = OBJECT ANGLE X(bot)
botYA# = OBJECT ANGLE Y(bot)
botZA# = OBJECT ANGLE Z(bot)
`rotate the bot to face the specified position
POINT OBJECT bot,x#,y#,z#
`store the bot's new angles (z not required)
botNXA# = OBJECT ANGLE X(bot)
botNYA# = OBJECT ANGLE Y(bot)
`Check if the bot is already facing the direction specified (within allowance), if so
`skip the rest and return a completion point. Otherwise, continue with the
`calculations.
IF botXA# >= (botNXA#-allowance#) AND botXA# <= (botNXA#+allowance#) AND botYA# >= (botNYA#-allowance#) AND botYA# <= (botNYA#+allowance#)
completed = 1
ELSE
`calculate the bot's new angles
botXA# = CURVEANGLE(botNXA#,botXA#,cycles)
botYA# = CURVEANGLE(botNYA#,botYA#,cycles)
ENDIF
`re-rotate the bot
ROTATE OBJECT bot,botXA#,botYA#,botZA#
ENDFUNCTION completed
FUNCTION AI_evade(bot,x#,y#,z#,distance#,speed#)
`store the bot's current position
botX# = OBJECT POSITION X(bot)
botY# = OBJECT POSITION Y(bot)
botZ# = OBJECT POSITION Z(bot)
`calculate the distance from the bot's position to the evade position
botDist# = math_getDist3D(x#,y#,z#,botX#,botY#,botZ#)
`if the distance is less than the specified distance, begin running.
IF botDist# <= distance#
`calculate the bot's new position, running from the x#/y#/z#.
POINT OBJECT bot,x#,y#,z#
MOVE OBJECT bot,1
POINT OBJECT bot,botX#,botY#,botZ#
MOVE OBJECT bot,1
`move the bot away
MOVE OBJECT bot,speed#
ELSE
`if the task is completed, return a 1 signifying completion.
complete = 1
ENDIF
ENDFUNCTION complete
FUNCTION math_setup()
`setup required vectors for distance calculations
null = MAKE VECTOR3(1)
null = MAKE VECTOR2(2)
#CONSTANT vecDist3D = 1
#CONSTANT vecDist2D = 2
ENDFUNCTION
FUNCTION math_getDist3D(X1#,Y1#,Z1#,X2#,Y2#,Z2#)
SET VECTOR3 vecDist3D,X1#-X2#,Y1#-Y2#,Z1#-Z2#
dist# = LENGTH VECTOR3(vecDist3D)
ENDFUNCTION dist#
FUNCTION math_getDist2D(X1#,Y1#,X2#,Y2#)
SET VECTOR2 vecDist2D,X1#-X2#,Y1#-Y2#
dist# = LENGTH VECTOR2(vecDist2D)
ENDFUNCTION dist#
Included in that library is 2 math functions for getting 2D/3D distances, as the AI functions use this. Make sure to use the setup math function before calling any of the math functions.
Overview of the commands:
Quote: "
AI_Travel(bot,x#,y#,z#,distance#,speed#)
o bot: the object you want to travel
o x#/y#/z#: the position you want the bot to travel to
o distance#: the distance the bot will stop at from the travel destination
o speed#: the speed of travel
AI_look(bot,x#,y#,z#,cycles,allowance#)
o bot: the object you want to look
o x#/y#/z#: the location you want the bot to look towards
o cycles: the amount of loops it should take the bot to finish the task
o allowance#: a "leeway" amount, its just a way of saying "if the bot is kind of close to looking directly at the position, it's good enough", as you'll rarely ever get the bot looking perfectly at a location since the angles are floats. Allowance is the range below and above the ending angle you decide is "ok".
AI_evade(bot,x#,y#,z#,distance#,speed#)
o bot: you get the idea.
o x#/y#/z#: the position the bot should run away from
o distance#: how close to the x#/y#/z# the bot will hold its ground until it decides to run.
o speed#: the speed the bot runs away at"
The math commands are pretty generic so Ill skip explaining them.
Demo Program;
SYNC ON:SYNC RATE 0:AUTOCAM OFF
MAKE OBJECT BOX 1,5,2,10
MAKE MATRIX 1,50,50,10,10
POSITION MATRIX 1,-25,0,-25
POSITION CAMERA 0,50,-100
POINT CAMERA 0,0,0
math_setup()
DO
TEXT 0,0,"Press the following keys:"
TEXT 0,15,"1: travel to 0,0,0"
TEXT 0,30,"2: look at point 0,0,0"
TEXT 0,45,"3: run away from 0,0,0 until 50 units away"
IF KEYSTATE(2) = 1 THEN AI_travel(1,0,0,0,1,.5)
IF KEYSTATE(3) = 1 THEN AI_look(1,0,0,0,100,2)
IF KEYSTATE(4) = 1 THEN AI_evade(1,0,0,0,50,1)
IF UPKEY() = 1 THEN MOVE OBJECT 1,.5
IF DOWNKEY() = 1 THEN MOVE OBJECT 1,-.5
IF LEFTKEY() = 1 THEN YROTATE OBJECT 1,WRAPVALUE(OBJECT ANGLE Y(1)-.5)
IF RIGHTKEY() = 1 THEN YROTATE OBJECT 1,WRAPVALUE(OBJECT ANGLE Y(1)+.5)
SYNC
LOOP
FUNCTION AI_travel(bot,x#,y#,z#,distance#,speed#)
`store the bot's current position
botX# = OBJECT POSITION X(bot)
botY# = OBJECT POSITION Y(bot)
botZ# = OBJECT POSITION Z(bot)
`calculate the distance between the bot and the new location to travel to
botDist# = math_getDist3D(botX#,botY#,botZ#,x#,y#,z#)
`if the bot is less than the specified allowed distance away,
`make the bot face the new location and move forward
IF botDist# > distance#
POINT OBJECT bot,x#,y#,z#
MOVE OBJECT bot,speed#
ELSE
`If the task is completed, return a 1 signifying completion.
complete = 1
ENDIF
ENDFUNCTION complete
FUNCTION AI_look(bot,x#,y#,z#,cycles,allowance#)
`store the bot's current angles
botXA# = OBJECT ANGLE X(bot)
botYA# = OBJECT ANGLE Y(bot)
botZA# = OBJECT ANGLE Z(bot)
`rotate the bot to face the specified position
POINT OBJECT bot,x#,y#,z#
`store the bot's new angles (z not required)
botNXA# = OBJECT ANGLE X(bot)
botNYA# = OBJECT ANGLE Y(bot)
`Check if the bot is already facing the direction specified (within allowance), if so
`skip the rest and return a completion point. Otherwise, continue with the
`calculations.
IF botXA# >= (botNXA#-allowance#) AND botXA# <= (botNXA#+allowance#) AND botYA# >= (botNYA#-allowance#) AND botYA# <= (botNYA#+allowance#)
completed = 1
ELSE
`calculate the bot's new angles
botXA# = CURVEANGLE(botNXA#,botXA#,cycles)
botYA# = CURVEANGLE(botNYA#,botYA#,cycles)
ENDIF
`re-rotate the bot
ROTATE OBJECT bot,botXA#,botYA#,botZA#
ENDFUNCTION completed
FUNCTION AI_evade(bot,x#,y#,z#,distance#,speed#)
`store the bot's current position
botX# = OBJECT POSITION X(bot)
botY# = OBJECT POSITION Y(bot)
botZ# = OBJECT POSITION Z(bot)
`calculate the distance from the bot's position to the evade position
botDist# = math_getDist3D(x#,y#,z#,botX#,botY#,botZ#)
`if the distance is less than the specified distance, begin running.
IF botDist# <= distance#
`calculate the bot's new position, running from the x#/y#/z#.
POINT OBJECT bot,x#,y#,z#
MOVE OBJECT bot,1
POINT OBJECT bot,botX#,botY#,botZ#
MOVE OBJECT bot,1
`move the bot away
MOVE OBJECT bot,speed#
ELSE
`if the task is completed, return a 1 signifying completion.
complete = 1
ENDIF
ENDFUNCTION complete
FUNCTION math_setup()
`setup required vectors for distance calculations
null = MAKE VECTOR3(1)
null = MAKE VECTOR2(2)
#CONSTANT vecDist3D = 1
#CONSTANT vecDist2D = 2
ENDFUNCTION
FUNCTION math_getDist3D(X1#,Y1#,Z1#,X2#,Y2#,Z2#)
SET VECTOR3 vecDist3D,X1#-X2#,Y1#-Y2#,Z1#-Z2#
dist# = LENGTH VECTOR3(vecDist3D)
ENDFUNCTION dist#
FUNCTION math_getDist2D(X1#,Y1#,X2#,Y2#)
SET VECTOR2 vecDist2D,X1#-X2#,Y1#-Y2#
dist# = LENGTH VECTOR2(vecDist2D)
ENDFUNCTION dist#
Ill make up a more complex demo a bit later on showing some cool stuff you can get working (Im a bit surprised how something that simple can do quite a lot :/).
Anyways, hope it helps,
- RUC'