Hi, i was searching for information about artificial intelligence middleware to use in the BGE. Does anyone tried it anytime?
-What i have fount:
seems to exist to opensource middlewares http://www.simbionic.com/games.htm simbionic is a opensource AI development tool, but seems quite old, maybe from 10 years ago. Anyway it provides a graphic logic blocs interface for non programers.
http://opensteer.sourceforge.net/ provides steer behaviours.
i didnt have tried it , dont know if they cam be used whith the BGE, did amybody tried?
please post more AI tools, there is a big lake about this.
If I need an AI for my computer game, I code it myself. Computer game AI’s are so specialized for there game, that generic AI libraries are pretty much useless.
Just my opinion thouh.
There’s also commonly a misunderstanding about what video game AI is/does. Concepts like machine learning usually aren’t that valuable in making a basic computer opponent that’s fun to play.
Many people seem to be completely out there when they think they need AI. Most of them just need a function that picks one out of three on more or less arbitrary basis. Take it from something very simple and start refining if you feel like it’s still too dumb.
AI stands for Artificial Intelligence. As demonstrated by a number of species (and humans themselves), intelligence is a very relative concept.
All forms of decision making approximate intelligence. Depending upon how serious the application may be, you will choose a different solution.
Most of the aforementioned libraries are skewed towards offline intelligence used in interpreting data, with use cases aligned towards robotics / obscure forms of mathematics.
Better describe what capabilities your NPC characters (assumed) require, and then we can look at proposing methods (not libraries) to achieve them.
The problem with an AI middleware, as mentioned already, is the broad set of algorithms that fall under the AI category. Often times an AI middleware focuses on a particular aspect of AI, such as decision making, path finding (Recast), steering (Detour), machine learning (PyBrain), etc. In other words, simply asking for an AI middleware without first explaining what you need, will yield many results, and not all of them useful.
As for a bge AI library, I feel like there may be a few user created libraries for AI floating around these forums. I have also written my own simple libraries for decision making (using a state machine) and steering behaviors in a couple of personal projects. I could clean up the most recent one and put it on GitHub if anyone is interested in it. It is very simple, but could be used as a starting point for game specific AI.
That’s actually exactly what AI is most of the time. AI doesn’t refer to any particular class of intelligent algorithms, it just means a procedure that can make decisions (even if they aren’t necessarily smart).
So making a brief about this topic…
what an average BGE user need is an standalone program or script capable of doing at least:
path tracer, a way to locate the enemies in the game and find a good path to arrive there.
Steer behaviours, what does the bot when not in “hunting mode”.
Select between a few list of options when some events happen in game.
Not exactly AI related but i think that could be very usefull for this kind of problems…is to have some kind of scripts like the ones knowed in second life as ANIMATION OVERRIDERS (are scripts that load automatically between a list of loaded animation loops when an event hapens or simply automatically.
Anyone have developed things like this, or we are still on the “only for coders” stage?
About the “pathtracer”, if there’s some sort of library for it, you’d have to find out a way to pass geometry data to it (write an exporter for with it’s geometry format), which can significantly slow down the load time of your game.
About steering behaviour, it’s already very basic to script it given the position, radius of the obstacle, player position and player’s direction vector.
About the last one, this is a very gameplay specific feature, just create those animations and specify the events that run them.
All of that is way too game-specific to be a plug-and-play asset. Stuff like that everyone (including myself at least) implements personally for each of their games.
Pathfinding you can already find built-in in BGE. Look for tutorials on how to use it.
import bge
import math
def main():
cont = bge.logic.getCurrentController()
own = cont.owner
on = cont.sensors['On']
if own['Health']<=1:
own.scene.addObject('Explode',own,30)
for child in own.childrenRecursive:
if not child.invalid:
child.endObject()
own.endObject()
else:
if cont.sensors['Near'].positive:
d=100
for hit in cont.sensors['Near'].hitObjectList:
dist = own.getDistanceTo(hit)
if dist<d:
own['Target']=hit
own['Reset']=60
own['On']=True
d = dist
if 'parts' not in own:
p = []
c = []
for child in own.childrenRecursive:
if 'B_Tag' in child:
p.append( [ child, own.children[child['B_Tag'] ] ] )
if 'c' in child:
c.append(child)
child.color = [.25,.25,.25,1]
own['parts']=p
own['colorParts']=c
else:
for p in own['parts']:
p[1].removeParent()
p[1].worldPosition =p[0].worldPosition
p[1].worldOrientation = p[0].worldOrientation
p[1].setParent(own,1,0)
if on.positive:
if own['init']<=34:
cont.activate(cont.actuators['Wake'])
own['init']+=1
else:
cont.deactivate(cont.actuators['Wake'])
if own['BombTime']<15:
if own.localAngularVelocity.z < own.localLinearVelocity.magnitude:
if own.localLinearVelocity.magnitude>.15:
if abs(own.localLinearVelocity.x)>abs(own.localLinearVelocity.y):
own.children['Spider']['W']+=own.localLinearVelocity.x*.25
if own.children['Spider']['W']>40:
own.children['Spider']['W']=0
elif own.children['Spider']['W']<0:
own.children['Spider']['W']=40
cont.activate(cont.actuators['Walk'])
cont.deactivate(cont.actuators['Idle'])
cont.deactivate(cont.actuators['Wake'])
else:
#crab walk state
cont.deactivate(cont.actuators['Walk'])
cont.deactivate(cont.actuators['Idle'])
else:
#idle state
own['W']=0
cont.deactivate(cont.actuators['Walk'])
cont.activate(cont.actuators['Idle'])
elif abs(own.localAngularVelocity.z) >.25 :
#rotate in place state
pass
if 'Target' in own and own['init']>14:
if 'Path' not in own:
if own.getDistanceTo(own['Target'])>3:
own['Path'] = cont.actuators['Steering'].navmesh.findPath(own.worldPosition,own['Target'].worldPosition)
else:
v2 = own.getVectTo(own['Target'])
own.applyForce(v2[1] *( 5 + (15*v2[0]*v2[0]*v2[0])))
own.localLinearVelocity.y*=.25
own.localLinearVelocity.x*=.25
cont.activate(cont.actuators['Blow'])
cont.deactivate(cont.actuators['Walk'])
cont.deactivate(cont.actuators['Idle'])
cont.deactivate(cont.actuators['Wake'])
own.applyForce((0,0,9.9),0)
own.applyTorque((0,0,2),0)
if own['BombTime']<=99:
own['BombTime']+=1
for part in own['colorParts']:
part.color = [ .5+ math.cos((own['BombTime']*own['BombTime'])*.0125),0,0,1 ]
elif len(own['Path'])>=1:
if own.getDistanceTo(own['Target'])>=4:
p1 = own['Path'][0].copy()
p1.z = own.worldPosition.z
local = own.worldOrientation.inverted()*(p1 - own.worldPosition)
if local.magnitude>.75:
if local.x>0:
own.localLinearVelocity.y*=.75
own.alignAxisToVect(own.getVectTo(p1)[1],0,.125)
if abs(local.y) < local.x:
if own.localLinearVelocity.x<5:
own.applyForce((25,0,0),1)
else:
if local.y>0:
own.applyRotation((0,0,.1),0)
else:
own.applyRotation((0,0,-.1),0)
else:
own['Path'].pop(0)
else:
del own['Path']
else:
del own['Path']
if own['Reset']>=1:
own['Reset']-=1
elif 'Target' in own:
del own['Target']
if 'Target' in own:
if own.getDistanceTo(own['Target'])>6 and own['BombTime']>=1:
cont.deactivate(cont.actuators['Blow'])
own['BombTime']-=1
for p in own['colorParts']:
p.color = p.color.lerp([.25,.25,.25,1],.1)
elif own.getDistanceTo(own['Target'])<=2:
own.scene.addObject('Explode',own,15)
own.endObject()
if own['BombTime']>=100:
own.scene.addObject('Explode',own,15)
own.endObject()
main()
This is my ai for our recent bgmc 28 Lost star tribe
nothing fancey
turn in place if next point is behind -> run to path -> get to player -> explode.
import bge
import math
# spider bot ai controller by jacob merrill
def main():
cont = bge.logic.getCurrentController()
own = cont.owner
on = cont.sensors['On']
# am I dead yet?
if own['Health']<=1:
# yeah I am dead lets explode
own.scene.addObject('Explode',own,30)
for child in own.childrenRecursive:
if not child.invalid:
child.endObject()
own.endObject()
else:
# if I am not dead and something is near me set my target
# to the closest on the list of hitobjects
# later we could cast rays and only go at something we see
if cont.sensors['Near'].positive:
d=100
for hit in cont.sensors['Near'].hitObjectList:
dist = own.getDistanceTo(hit)
if dist<d:
own['Target']=hit
own['Reset']=60
own['On']=True
d = dist
# this is used for compound phyiscs
# tags are parented to the armature
# child shapes are stored in conjunction with their tags
# we also gather parts we will be flashing later with object color
#have we stored the list of parts?
if 'parts' not in own:
#no we need to store it
p = []
c = []
#roll through all child shapes
for child in own.childrenRecursive:
if 'B_Tag' in child:
#child is a armature bone tag
p.append( [ child, own.children[child['B_Tag'] ] ] )
if 'c' in child:
#child will get object color animated
c.append(child)
child.color = [.25,.25,.25,1]
#store the data
own['parts']=p
own['colorParts']=c
#data is found use it
else:
#this updates the child shapes to match the armature
for p in own['parts']:
p[1].removeParent()
# move child shape to match bone position and rot
p[1].worldPosition =p[0].worldPosition
p[1].worldOrientation = p[0].worldOrientation
p[1].setParent(own,1,0)
#if we activate play wake up animation
if on.positive:
if own['init']<=34:
cont.activate(cont.actuators['Wake'])
own['init']+=1
else:
#if we are awake animate actor based on linV
cont.deactivate(cont.actuators['Wake'])
if own['BombTime']<15:
if own.localAngularVelocity.z < own.localLinearVelocity.magnitude:
if own.localLinearVelocity.magnitude>.15:
#if we are moving animate actor
if abs(own.localLinearVelocity.x)>abs(own.localLinearVelocity.y):
#if we move forward / backward play walk
own.children['Spider']['W']+=own.localLinearVelocity.x*.25
if own.children['Spider']['W']>40:
#this is setting the animation frames in the armature
own.children['Spider']['W']=0
elif own.children['Spider']['W']<0:
own.children['Spider']['W']=40
cont.activate(cont.actuators['Walk'])
cont.deactivate(cont.actuators['Idle'])
cont.deactivate(cont.actuators['Wake'])
else:
#I did not add a crab walk animation yet
#crab walk state
cont.deactivate(cont.actuators['Walk'])
cont.deactivate(cont.actuators['Idle'])
else:
#idle state
own['W']=0
cont.deactivate(cont.actuators['Walk'])
cont.activate(cont.actuators['Idle'])
elif abs(own.localAngularVelocity.z) >.25 :
#rotate in place state
#I did not add a rotate in place animation yet
pass
#if we have a target and we are awake check to see if we have a path
if 'Target' in own and own['init']>14:
if 'Path' not in own:
#we don't have a path
if own.getDistanceTo(own['Target'])>3:
#if we don't have a path grab one if the target is far away
own['Path'] = cont.actuators['Steering'].navmesh.findPath(own.worldPosition,own['Target'].worldPosition)
else:
#if we are really close we should probably kill it
v2 = own.getVectTo(own['Target'])
own.applyForce(v2[1] *( 5 + (15*v2[0]*v2[0]*v2[0])))
own.localLinearVelocity.y*=.25
own.localLinearVelocity.x*=.25
cont.activate(cont.actuators['Blow'])
cont.deactivate(cont.actuators['Walk'])
cont.deactivate(cont.actuators['Idle'])
cont.deactivate(cont.actuators['Wake'])
own.applyForce((0,0,9.9),0)
own.applyTorque((0,0,2),0)
if own['BombTime']<=99:
own['BombTime']+=1
#set self to explode at 100
for part in own['colorParts']:
#this makes the parts flash faster and faster as boom boom time approaches
part.color = [ .5+ math.cos((own['BombTime']*own['BombTime'])*.0125),0,0,1 ]
# this is what to do if we have a path and are not too close to target
elif len(own['Path'])>=1:
#check to see if we are close enough to target to explode on them
if own.getDistanceTo(own['Target'])>=4:
#if not continue pathfinding
p1 = own['Path'][0].copy()
p1.z = own.worldPosition.z
#place point in local space so we can decide what to do next.
local = own.worldOrientation.inverted()*(p1 - own.worldPosition)
#are we at the point on the path?
if local.magnitude>.75:
#is the next point ahead of me?
if local.x>0:
#the point is ahead of me seek it
own.localLinearVelocity.y*=.75
own.alignAxisToVect(own.getVectTo(p1)[1],0,.125)
#if point inside cone apply forces
#this math defines a cone
if abs(local.y) < local.x:
if own.localLinearVelocity.x<5:
own.applyForce((25,0,0),1)
else:
#the point is behind me turn in place
if local.y>0:
own.applyRotation((0,0,.1),0)
else:
own.applyRotation((0,0,-.1),0)
else:
#remove point from path as we visit it
own['Path'].pop(0)
else:
#I am near target, better rethink things
del own['Path']
else:
#my path is empty time to rethink things
del own['Path']
#if I don't see anything this clock ticks down
if own['Reset']>=1:
own['Reset']-=1
elif 'Target' in own:
#forget target if they run too far away and I don't see them in near
del own['Target']
if 'Target' in own:
#if we have a target and they run away before we can explode reset our boom clock
if own.getDistanceTo(own['Target'])>6 and own['BombTime']>=1:
cont.deactivate(cont.actuators['Blow'])
own['BombTime']-=1
for p in own['colorParts']:
p.color = p.color.lerp([.25,.25,.25,1],.1)
elif own.getDistanceTo(own['Target'])<=2:
own.scene.addObject('Explode',own,15)
own.endObject()
#if our boom clock is high enough exlplode
if own['BombTime']>=100:
own.scene.addObject('Explode',own,15)
#clean up phyiscs shapes
for child in own.childrenRecursive:
if not child.invalid:
child.endObject()
own.endObject()
main()