Pacman Mechanics

Here I come with another question!

How does one learn an enemy AI: (the ghosts of pacman)

That they can move from point A to B by hitting the wall at a specific point.

Or is this overly complicated and should I drop it for a first BGE project?

Or only support it for the player? (This kinda feels like cheating to me)

I came up with a thought whilst typing this, but I still would like to get a second opinion :smiley:

Are you talking about the tunnels that teleport you from once side of the stage to another?

Or are you talking about the ghosts making a path to the player?

Attachments


If you want to know about old fashioned tile based movement I can write a tutorial about itā€¦

You can read various analysis of the ghost AI:


http://gameai.com/wiki/index.php?title=Pac-Man
etc.

@Lordofthechings : Both actually since iā€™m not satisfied by how the navmesh and steering works!

@Smoking_mirror : That would be very nice. Take Your time and let me know when itā€™s finished.

@sdfgeoff : A little homework xD Iā€™ll be reading that right now!

Also Iā€™ve made a navmesh from a pacman-like map I made.
Totally not satisfied by how the object navigates the mesh! (I think itā€™s limited in every way)
Are ther any means of manipulating the way this works, Except from the turning and moving speed (Steering actuator)

If youā€™re making a game like pacman your best way forward would be to code it in a similar way.
That means using python quite a lot though. Are you comfortable with using python for most of the movement?
pros: total control of movement, doesnā€™t need any collision or other things, hit detection is as easy as measuring a vector.
cons: no physics, difficult to do 3d movement(up/down), no so easy to use logic bricksā€¦

No I have almost no experience in coding (very little Java)
And I have not looked into python either!

This is on my agenda though

nevermind that each ghost has its different AI :smiley:

that is a possible ghost AI (semplified)
as usual i prefer AI with ā€œalzaymerā€ (no memory)


import random
import bge
from mathutils import Vector, Matrix




"""pac-man ghost AI (iper - semplificated)


the face forward of the ghost object is +Y (green arrow)(to semplificate face_to())
the ghost obj is not a object physic (not influeced from collisions)


"""


TILE_SIZE = 2.0  # 2 meters




def face_to(own, pos): # align to position without interpolations
    own.worldOrientation = (pos - own.worldPosition).to_track_quat("Y","Z")


def get_target(own):
    # these are sort of -> north south owest east
    FOUR_DIRECTIONS = [vec * verse for verse in [-1,1] for vec in Matrix().to_3x3()[:2]]
    start = own.worldPosition
    directions = []
    for direction in FOUR_DIRECTIONS:
        end = start + direction * TILE_SIZE * 1.5
        if not own.rayCast(end, start)[0]: 
            directions.append(direction) # the ray has not found obstacle, so free way, add
            
    # is assumed that at least one direction free exist (otherwise give error) 
    direction = random.choice(directions) # pick one random
    target_position = start + (direction * TILE_SIZE)
    return target_position








def main():
    cont = bge.logic.getCurrentController()
    own = cont.owner


    if not "init" in own:
        own["target_xyz"] = None
        own["init"] = True
        own["speed"] = 0.05
        
    if not own["target_xyz"]:
        xyz = own["target_xyz"] = get_target(own)
        face_to(own, xyz)
   
    
    #debug
    bge.render.drawLine(own.worldPosition, own["target_xyz"], [1,0,0])
    
    ## move
    speed = own["speed"]
    dist = own.getDistanceTo(own["target_xyz"])
    if dist > speed:
        own.applyMovement((0,speed,0),1)
    else:
        own.worldPosition = own["target_xyz"]
        own["target_xyz"] = None
    


try:
    main()
except:
    bge.logic.endGame()
    raise
    
    

EDIT: bugfix (copy paste wrong)

@MarcoIT really cool, I changed the the speed to .1 and tile size to 2. Is there anyway to tweek the randon direction? You programmers are awesome.

Thatā€™s a really cool article. Thanks.

you mean a bit less random?

can be added more chances to the forward direction
and removed the ā€œbackā€ direction.(as is in pacman original)

ok, now is a bit better :slight_smile:


import random
import bge
from mathutils import Vector, Matrix








"""pac-man ghost AI (iper - semplificated)




the face forward of the ghost object is +Y (green arrow)(to semplificate face_to())
the ghost obj is not a object physic (not influeced from collisions)


added patch for "no direction founded"
"""




TILE_SIZE = 2.0  # 2 meters








def face_to(own, pos): # align to position without interpolations
    own.worldOrientation = (pos - own.worldPosition).to_track_quat("Y","Z")




def get_target(own):
    vx, vy = own.worldOrientation.col[:2]
    local_directions = [-vx, vx, vy, vy, vy] # more forward direction
    start = own.worldPosition
    targets_candidate = [start+vec*TILE_SIZE for vec in local_directions]
    targets_free = []
    for target in targets_candidate:
        if not own.rayCast(target, start)[0]: 
            targets_free.append(target)
    
    if not targets_free:
        return None
    target = random.choice(targets_free)
    # chunkifyze.. should be already , but to be more sure ...
    return Vector([round(v/TILE_SIZE)*TILE_SIZE for v in target])










def main():
    cont = bge.logic.getCurrentController()
    own = cont.owner




    if not "init" in own:
        own["target_xyz"] = None
        own["init"] = True
        own["speed"] = 0.1
        
    if not own["target_xyz"]:
        target = own["target_xyz"] = get_target(own)
        if not target:
            return
        face_to(own, target)
        
    
    #debug
    bge.render.drawLine(own.worldPosition, own["target_xyz"], [1,0,0])
    
    ## move
    speed = own["speed"]
    dist = own.getDistanceTo(own["target_xyz"])
    if dist > speed:
        own.applyMovement((0,speed,0),1)
    else:
        own.worldPosition = own["target_xyz"]
        own["target_xyz"] = None
    




try:
    main()
except:
    bge.logic.endGame()
    raise
    
    
    

Thank you Marco. Very cool. Iā€™ll play with it later, been really busy these past few days. :slight_smile: