I have an Basic Idea to realize a AI for my Game (a little Drone-demolish-derby) and want that my cpu enemy random follow me and attacks(bumped) me or try to kick me from the arena have try some sort of steering actuator-> not the result I want.
here is a little test code from my experimentation:
from bge import logic
def position(cont):
own = cont.owner
scene = logic.getCurrentScene()
objList = scene.objects
#ray_player = cont.sensors["Ray"]
steering_act = cont.actuators["Steering"]
settings = objList["settings_block"]
player = objList["Player"]
player_life = player["Life"]
own_life = own["Life"]
player_dist = (player.worldPosition - own.worldPosition).magnitude
print(player_dist)
obj_enemy = [o for o in scene.objects if "player_ai" in o]
enemy = obj_enemy
dist = lambda o: (o.worldPosition - own.worldPosition).magnitude
object_distance = [(id(o), dist(o)) for o in enemy]
object_distance.sort(key=lambda t: t[1])
closest = object_distance[1][0]
enemy_id = closest
enemy_life = objList.from_id(enemy_id)["Life"]
#print(object_distance[1], objList.from_id(enemy_id)["Life"])
steering_act.navmesh = objList["Navmesh"]
steering_act.behavior = logic.KX_STEERING_PATHFOLLOWING
steering_act.pathUpdatePeriod = 0
steering_act.velocity = 3.0
steering_act.acceleration = 3.0
steering_act.turnspeed = 120.0
steering_act.distance = 1.0
steering_act.selfterminated = False
steering_act.enableVisualization = True
steering_act.target = player
#if settings["all_cpu_against_player"] == False:
# if enemy_life < player_life:
# attack(steering_act, player)
# steering_act.target = player
# else:
# attack(steering_act, objList.from_id(enemy_id))
# steering_act.target = objList.from_id(enemy_id)
#else:
# attack(steering_act, player)
# steering_act.target = player
def attack(actuator, obj_to_attack):
#actuator.target = obj_to_attack
print("I current attack: " + str(obj_to_attack))
def enemy_position(cont):
pass
is it possible to get all vertex, face-midpoints possible positions and get an own inGame navmesh and an custom path following?
this is the Arena:
Hello, I am a quite concerning programming who cannot help but point out this is not AI unless it iterates over it’s own decision making skill’s thus because it duz not realize that it’s ability for attack depends on it’s distance to the target it cannot adapt to you running backward’s and shootin, I had the same problem the second Time I played descent 3… so no worry’s I think you should write the code and then have it iterate through it’s own decompiled code via opcode.py in your Lib path and generate genetic signatures for efficiency… see my contest under member contests for more info soon.
Instead of dynamically generating navmeshes, try continuously changing steering_act.target to points you calculate in real time.
If you really wanted to play with changing navmeshes, you could alter the actual navmesh in-game by changing its vertex points/location. The AI will then adapt to the changing navmesh.
For every vertex you obtain, you can use AI.getDistanceTo(VertexPoint) to store in a variable with the shortest distance information (enumerate, and have a list called ‘shortest’ or something to keep track of what vertex has the shortest distance so far. Don’t forget to also store in the vertex.
You can refer to the documentation for getDistanceTo(): https://www.blender.org/api/blender_python_api_2_78a_release/bge.types.KX_GameObject.html#bge.types.KX_GameObject
I’m assuming you want to gather a lot of points for the navmesh anyway, so I think gathering distances
through brute force might be an ideal solution for your case. Hope that helps.
def get_faces_position(mesh):
positions = []
for pn in range(mesh.numPolygons):
poly = mesh.getPolygon(pn)
mn = poly.getMaterialIndex()
verts = []
for pvn in range(poly.getNumVertex()):
vn = poly.getVertexIndex(pvn)
vertex = mesh.getVertex(mn, vn)
verts.append(vertex)
if verts:
position = Vector([sum(values) for values in zip(*[v.XYZ for v in verts])])/len(verts)
positions.append(position)
return positions
local_points = get_faces_position(navmesh.meshes[0])
global_points = [navmesh.worldTransform*lp for lp in local_points]
Basically, your code didn’t work because you didn’t cont.activate() the actuator
when you changed the targeting object. Also, if you put the ‘player_ai’ variable
for your tracking object, it will measure the distance to itself, which will be
a distance of 0.0.
Brute force may or may not be required. This depends on what is desired.
There are many methods other than simple brute force.
@MarcoIT
your code looks a little familiar to other thinks I have done before spawn Player at Vertexpoint (not the same but I know how to do it)
I think about KDTree / BVHTree or maybe something from this mathutils.geometry
@Mirror
forgot to set it to active <-- ok
distance to itself <-- no, this line “object_distance[1][0]” is the second object that is near to itself (first is it self) by “player_ai”
ok, I get all Vertex points from mesh and but have some trouble to get the nearest vertex point to the interpolated midpoint/s didn’t know if this work anybody has some experience with KDTree -> find-n(co, n)
from bge import logic
from mathutils import Vector
def get_possible_points(navobj):
position_list = []
mesh = navobj.meshes[0]
got_last_v = (mesh.getVertexArrayLength(0)-1)
for v in range(mesh.getVertexArrayLength(0)):
if v != got_last_v:
vert = mesh.getVertex(0, v)
vert_position = vert.getXYZ()
position_list.append(vert_position)
else:
return position_list
def near_vertex_points(startpoint, endpoint, inpo_num, possible_position):
#dist = lambda o: (startpoint - endpoint).magnitude
#object_distance = [(id(o), dist(o)) for o in possible_position]
#print(object_distance)
#point = object_distance.sort(key=lambda t: t[1])
#closest = point[0][0]
#print(closest)
#possible_position
def main(cont):
own = cont.owner
scene = logic.getCurrentScene()
scObj = scene.objects
destination = scObj["Player"].worldPosition
now_position = own.worldPosition
points = get_possible_points(scObj["Plane.001"])
accurate = 2
near_vertex_points(now_position, destination, accurate, points)
#print(points)
the code sniped from MarcoIT is great but it will not produce the vertex list I want because
“for pn in range(mesh.numPolygons):” this range is every time = 0 so I got only the last vertex position.
i tried it in different conditions and it work ever.
try to open a new blend, copyu and paste this code in script mode (always without true)
it should add the object visualizer for each face of the obj “own” , own just must be a mesh object (it can be also a navmesh obj)
import bge
from mathutils import Vector
def get_faces_position(mesh):
positions = []
for pn in range(mesh.numPolygons):
poly = mesh.getPolygon(pn)
mn = poly.getMaterialIndex()
verts = []
for pvn in range(poly.getNumVertex()):
vn = poly.getVertexIndex(pvn)
vertex = mesh.getVertex(mn, vn)
verts.append(vertex)
if verts:
position = Vector([sum(values) for values in zip(*[v.XYZ for v in verts])])/len(verts)
positions.append(position)
return positions
cont = bge.logic.getCurrentController()
own = cont.owner
navmesh = own
local_points = get_faces_position(navmesh.meshes[0])
global_points = [navmesh.worldTransform*lp for lp in local_points]
name_obj_visualizer_face = "Icosphere"
for point in global_points:
obj_point = own.scene.addObject(name_obj_visualizer_face, own)
obj_point.worldPosition = point
obj_point.setParent(own)