Code example old FPS file Ai walk to player hint?

I am trying to get this AI figure to walk to the player, there is this code, I’ve read findplayer. The AI only faces the player, I removed state6 and changed it to state2 to avoid the AI attacking. In my example, the AI just needs to follow the player. navmesh.001 is the navmesh for the area, I am not sure what else I need to get this to do the task.

movecover code


import bge

cont = bge.logic.getCurrentController()
scene = bge.logic.getCurrentScene()
own = cont.owner

#self
self = scene.objects[own.name]

#properties
target = own['target']
incover = own['incover']
direction = own['direction']

#sensors
pnear = cont.sensors['Pnear']
collide = cont.sensors['Collision']
Ray = cont.sensors['Ray']
delay = cont.sensors['Delay1']
shootray = cont.sensors['shootray']

#actuators
refind = cont.actuators['State1']
attack = cont.actuators['State2']
flare = cont.actuators['flare']

#steering
findc = cont.actuators['walk']
runc = cont.actuators['runC']

#cover object
cover = scene.objects[own['target']]

#animations
runAnim = cont.actuators['run']
duck = cont.actuators['duck']

fwd = cont.actuators['fwdwalk']
back = cont.actuators['backwalk']
left = cont.actuators['walkleft']
right = cont.actuators['walkright']

fwdfire = cont.actuators['fwdwalkfire']
backfire = cont.actuators['backwalkfire']
leftfire = cont.actuators['walkleftfire']
rightfire = cont.actuators['walkrightfire']

#sound
sound = cont.actuators['sound']

#path finding
if cover['cover'] == 'safe' and pnear.positive == True and Ray.positive == False:
    findc.target = str(own['target'])
    cont.activate(findc)
    if direction == 'Run Forward':
        cont.activate(fwd)
    elif direction == 'Run Backward':
        cont.activate(back)
    elif direction == 'Run Left':
        cont.activate(left)
    elif direction == 'Run Right':
        cont.activate(right)

if cover['cover'] == 'safe' and pnear.positive == True and Ray.positive == True:
    findc.target = str(own['target'])
    cont.activate(findc)
    if direction == 'Run Forward':
        cont.activate(fwdfire)
    elif direction == 'Run Backward':
        cont.activate(backfire)
    elif direction == 'Run Left':
        cont.activate(leftfire)
    elif direction == 'Run Right':
        cont.activate(rightfire) 
        
elif cover['cover'] == 'safe' and pnear.positive == False:
    runc.target = str(own['target'])
    cont.activate(runc)
    cont.activate(runAnim)

#flare
if pnear.positive == True and Ray.positive == True and delay.positive and shootray.positive == True:
    cont.activate(flare)
    own.sendMessage("Phit", "", "player")
    cont.activate(sound)
elif pnear.positive == True and Ray.positive == True and delay.positive and shootray.positive == False:
    cont.activate(flare)
    cont.activate(sound)
    
#find new cover   
elif cover['cover'] != 'safe':
    cont.activate(refind)

#cover found
if collide.positive == True and incover == '':
    if collide.hitObject.name == str(cover):
        cont.deactivate(findc)
        cont.activate(duck)
        cover['cover'] = 'used'
        own['incover'] = 'cover'
        cont.activate(attack)

findplayer code below.

import bge

cont = bge.logic.getCurrentController()
own = cont.owner

#properties
direction = own['direction']
target = own['target']

cover_list = []
#sensors
cnear = cont.sensors['Cnear']
Ray = cont.sensors['Ray']
shootray = cont.sensors['shootray']
Delay = cont.sensors['Delay1']

#actuators
flare = cont.actuators['flare']
findP = cont.actuators['findplayer']
state1 = cont.actuators['State1']

#animations
fwd = cont.actuators['fwdwalk']
back = cont.actuators['backwalk']
left = cont.actuators['walkleft']
right = cont.actuators['walkright']

fwdfire = cont.actuators['fwdwalkfire']
backfire = cont.actuators['backwalkfire']
leftfire = cont.actuators['walkleftfire']
rightfire = cont.actuators['walkrightfire']

#sound
sound = cont.actuators['sound']

#walking
if target == '' and Ray.positive == False:
    cont.activate(findP)
    if direction == 'Run Forward':
        cont.activate(fwd)
    elif direction == 'Run Backward':
        cont.activate(back)
    elif direction == 'Run Left':
        cont.activate(left)
    elif direction == 'Run Right':
        cont.activate(right)

#walking + firing
if target == '' and Ray.positive == True:
    cont.activate(findP)
    if direction == 'Run Forward':
        cont.activate(fwdfire)
    elif direction == 'Run Backward':
        cont.activate(backfire)
    elif direction == 'Run Left':
        cont.activate(leftfire)
    elif direction == 'Run Right':
        cont.activate(rightfire)

#firing
if target == '' and Ray.positive == True and shootray.positive == False and Delay.positive:
    cont.activate(flare)
    cont.activate(sound)
if target == '' and Ray.positive == True and shootray.positive == True and Delay.positive:
    cont.activate(flare)
    cont.activate(sound)
    own.sendMessage("Phit", "", "player")

if cnear.positive == True and target == '':
    coverlist = cnear.hitObjectList
    for i in coverlist:
        if i['cover'] == 'safe':
            distance = [own.getDistanceTo(i), i]
            cover_list.append(distance)
            cover_list.sort()
            (own['target']) = cover_list[0][1]

if target != '':
    cont.activate(state1)

State 1 should be about seeking the player, I guess from the look of it.

Thank you for any hints.

To have the enemy A.I. object follow / walk-towards the player, you can dynamically assign the Steering actuator called, “walk,” to target the player object.

import bge

def main(cont):

  cont.activate("walk")
  cont.actuators["walk"].target = "player"

if you need an artificial intelligence that - 1.patrols the location, 2.check if it sees the player 3. monitors the player if the player is detected - to patrol the location, you need a timer - by which you will determine the change in the behavior of the unit for example, when the timer reaches 50, create a local variable behavior = random.randint(0,10) and if behavior in range(0,5) assign to property unit own[‘tactics’]=‘patrol’ and check all objects in scene for search patrol points - for i in scene.objects: if ‘patrol_point’ in i and not i in patrol_list: patrol_list.insert(0,i), next, we randomly select an object from the patrol list and assign it as a target to follow - rand_point = random.choice(patrol_list), steering = cont.actuators[‘Steering’].target = rand.point cont.activate(steering). When the bot moves or stands still, it should check whether it sees the player - the radar sensor in conjunction with rayCast is well suited for this - if radar.positive:
obj = radar.hitObject
if ‘player’ in obj:
start = own.worldPosition
end = obj.worldPosition
ray = own.rayCast(end, start, 15, ‘player’)
hit = ray[0]
if hit:
if ‘player’ in hit:
own[‘tactics’] = ‘player_visible’
steering.target = obj
cont.activate(steering)
elif not ‘player’ in hit:
pass
remember one thing if the unit saw the player by throwing a beam and reached the player, you either have to do a distance check or disable the steering actuator otherwise the unit will ram the player’s collider - if you need to assign another navmesh, you can refer to it as a scene object by name if the name is known navmesh1 = scene.objects[‘navmesh1’] steering.navmesh = navmesh1 or by checking all objects in the scene through the for loop - for i in scene.objects:
if ‘navmesh’ in i:
steering.navmesh = scene.objects[i.name]
for check distance use dist = own.getDistanceTo(obj) or own.getDistanceTo(obj)>= or <= and never use ==
if own.getDistanceTo(player)<=5.000:
#use rayCast function for check look line

Where does that snippet exactly go in that code? I wouldn’t know. Obviously no actual tutorial on this I think now from the file. It can’t be that difficult. :face_with_raised_eyebrow:

In findplayer.py, I’ guess, which is the following.

import bge
def main(cont):

  cont.activate("walk")
  cont.actuators["walk"].target = "player"

cont = bge.logic.getCurrentController()
own = cont.owner

#properties
direction = own['direction']
target = own['target']

cover_list = []
#sensors
cnear = cont.sensors['Cnear']
Ray = cont.sensors['Ray']
shootray = cont.sensors['shootray']
Delay = cont.sensors['Delay1']

#actuators
flare = cont.actuators['flare']
findP = cont.actuators['findplayer']
state1 = cont.actuators['State1']

#animations
fwd = cont.actuators['fwdwalk']
back = cont.actuators['backwalk']
left = cont.actuators['walkleft']
right = cont.actuators['walkright']

fwdfire = cont.actuators['fwdwalkfire']
backfire = cont.actuators['backwalkfire']
leftfire = cont.actuators['walkleftfire']
rightfire = cont.actuators['walkrightfire']

#sound
sound = cont.actuators['sound']

#walking
if target == '' and Ray.positive == False:
    cont.activate(findP)
    if direction == 'Run Forward':
        cont.activate(fwd)
    elif direction == 'Run Backward':
        cont.activate(back)
    elif direction == 'Run Left':
        cont.activate(left)
    elif direction == 'Run Right':
        cont.activate(right)

#walking + firing
if target == '' and Ray.positive == True:
    cont.activate(findP)
    if direction == 'Run Forward':
        cont.activate(fwdfire)
    elif direction == 'Run Backward':
        cont.activate(backfire)
    elif direction == 'Run Left':
        cont.activate(leftfire)
    elif direction == 'Run Right':
        cont.activate(rightfire)

#firing
if target == '' and Ray.positive == True and shootray.positive == False and Delay.positive:
    cont.activate(flare)
    cont.activate(sound)
if target == '' and Ray.positive == True and shootray.positive == True and Delay.positive:
    cont.activate(flare)
    cont.activate(sound)
    own.sendMessage("Phit", "", "player")

if cnear.positive == True and target == '':
    coverlist = cnear.hitObjectList
    for i in coverlist:
        if i['cover'] == 'safe':
            distance = [own.getDistanceTo(i), i]
            cover_list.append(distance)
            cover_list.sort()
            (own['target']) = cover_list[0][1]

if target != '':
    cont.activate(state1)

movecover.py is just the AI moving and firing in their original locations, in my example, that doesn’t work, since I changed state6 to 2 or something.

I want the AI to travel to the player, so that is the new program for it to work.

If I understand this better, this would use the steering brick listed in layer 2 of the AI, so does the code go in findplayer.py

#walking
if target == 'player' and Ray.positive == False:
    cont.activate(findP)
    if direction == 'Run Forward':
        cont.activate(fwd)
    elif direction == 'Run Backward':
        cont.activate(back)
    elif direction == 'Run Left':
        cont.activate(left)
    elif direction == 'Run Right':
        cont.activate(right)

This should do it, I think so.

Even with True that doesn’t work.

def main(cont):

  cont.activate("walk")
  cont.actuators["walk"].target = "player"

I am not sure where to put this?

import bge

cont = bge.logic.getCurrentController()
own = cont.owner

health = own['health']
crouch = own['crouch']

#knife
hknife = cont.sensors['hknife']
bknife = cont.sensors['bknife']
fknife = cont.sensors['fknife']

#bullet hit
feethit = cont.sensors['feethit']
bodyhit = cont.sensors['bodyhit']
headhit = cont.sensors['headhit']

#death states
headdeath = cont.actuators['headdeath']
bodydeath = cont.actuators['State4']
crouchdeath = cont.actuators['deathcrouch']

#hit animations
crouchhitAnim = cont.actuators['crouchhit']
bodyhitAnim = cont.actuators['hit']

#knife states
if hknife.positive and crouch == False or bknife.positive and crouch == False or fknife.positive and crouch == False:
    cont.activate(bodydeath)

elif hknife.positive and crouch == True or bknife.positive and crouch == True or fknife.positive and crouch == True:
    cont.activate(crouchdeath)

#headshot
if headhit.positive and crouch == False:
    cont.activate(headdeath)
if headhit.positive and crouch == True:
    cont.activate(crouchdeath)

#bodyshot
if bodyhit.positive and crouch == False and health > 1 or feethit.positive and crouch == False and health > 0:
    cont.activate(bodyhitAnim)
    own['health'] -= 1
if bodyhit.positive and crouch == True and health > 1 or feethit.positive and crouch == False and health > 0:
    cont.activate(crouchhitAnim)
    own['health'] -= 1
    
if bodyhit.positive and crouch == False and health == 1 or feethit.positive and crouch == False and health == 1:
    cont.activate(bodydeath)

elif bodyhit.positive and crouch == True and health == 1 or feethit.positive and crouch == True and health == 1:
    cont.activate(crouchdeath)

I tried editing this code Aihealth.py for player attack to AI melee longer duration, Knife states section changing the properties doesn’t do anything, I wanted to get the AI to be attacked a little longer with that action, instead of a ‘crouchdeath’

I am not sure if a timer is connected with state 4. Or the code needs some changing similar to a bullet hit animation change for the AI in the code.

I did change the AI property from 5 to 10. Not sure how much that would matter.

Not sure in the AI find player task. These are my ideas and task challenge.

use property string for assign and change states and only one property timer or float
if own[‘behavior’]==‘knife attack’ and own[‘timer’]<10.000:
#use attack knife and add for timer points
elif own[‘behavior’]==“knife attack” and own[‘timer’]>10.000:
#change new behavior

So there needs to be addition to the code?

#use attack knife and add for timer points
elif own[‘behavior’]==“knife attack” and own[‘timer’]>10.000:

What about the bricks there, or does the code need any bricks, I guess not. Just add the new code to the .py file.

Add a string?

Assign what or where?

Then add a timer?

if own[‘behavior’]==‘knife attack’ and own[‘timer’]<10.000:

yes right - not use states objects - because switching object states creates confusion, if you replace all states with a string, this will be the state of your object, which is more understandable and easier to read and correct logic errors.

if ['behavior']=='start_patrol':
for i in scene.objects:
if 'patrol_point' in i and own.getDistanceTo(i)>100.000:
obj = scene.objects[i.name]
steering.target = obj
cont.activate(steering)
own['behavior']='patrol'
if own['behavior']=='patrol':
for i in scene.objects:
if 'player' in i and own.getDistancetTo(i)<10.000:
start = own.worldPosition
end  = i.worldPosition
ray = own.rayCast(end, start,0,"player")
hit = ray[0]
if hit:
if "player" in hit:
steering.target = scene.objects[hit.name]
cont.activate(steering)
own['behavior'] = 'track_to_player'

this is a very simple and primitive example of using a string as the behavior of an object - instead of logical logic blocks in the code, you always control the behavior itself and the properties of the object and the distance and the goal. For better control, you will need to create logic based on the behavior dictionary, but the behavior property for the object is still needed as well as the attack timer, you will have to write all this logic (I recommend code and not logic bricks) or look for examples here on blenderartist

A reminder to everyone on this thread: when sharing long blocks of code verbatim, please use the </> button on the formatting toolbar to format that code. It makes your code much easier to read and it also condenses it so scrolling on mobile is much less of a headache :slight_smile:

ok - thanks

Hmm, I am just trying to see what can be done with what there is there, i can upload the blend. Everything there is default, I haven’t added or changed anything, except one nav mesh I made for the area where I put the AI. In time, I may remove some parts of the level, if no real use. Everything is pretty much there, just needs AI and a design. I tried some files but they didn’t work for a different AI model.

As well changed one state to stop the AI from firing, I was thinking the AI may be punches the player, so not sure exactly what my idea was. Getting the AI to go find the player is one task, and getting the knife effect to last a little longer so the AI doesn’t just drop after one attack.

This is what I have so far. I am not sure what AI weapon actions.

#bodyshot
if bodyhit.positive and crouch == False and health > 1 or feethit.positive and crouch == False and health > 0:
    cont.activate(bodyhitAnim)
    own['health'] -= 1
if bodyhit.positive and crouch == True and health > 1 or feethit.positive and crouch == False and health > 0:
    cont.activate(crouchhitAnim)
    own['health'] -= 1
    
if bodyhit.positive and crouch == False and health == 1 or feethit.positive and crouch == False and health == 1:
    cont.activate(bodydeath)

elif bodyhit.positive and crouch == True and health == 1 or feethit.positive and crouch == True and health == 1:
    cont.activate(crouchdeath)

Could I not use this for the melee weapon?

If I add a new property to the player’s empty, it has

Add some sort of property change, so the knife has a similar programming to the gun, bullet here fires.

I don’t know. :face_with_raised_eyebrow: