Obstacle avoiding

In fact, I should maybe add something about my view of path calculation :

I based it on memory cells to be able to compute AI layers :

  • one for spatial reasoning
  • another for influence map
  • strategy (terrain analysis, line of fire for example)

This could correspond to the openness+occupancy+static cover layers described in the Paul Tozour paper in AI Game Wisdom 2.

As I am new to Panda, I thought the better should be to go from that Pygame A* Example, that is working very well and after could be reworked (smoothing the path for example).
For now, my Roaming Ralph reworked + draw.py patchwork taken from post here give me a litlle beginning

# Left click on the ground to move.
# Rotate the camera by moving the mouse pointer to the edges of the screen or
# with the left & right arrow keys.
# Zoom the camera with the mouse wheel or the up & down arrow keys.

import direct.directbase.DirectStart # Start Panda.
from pandac.PandaModules import * # Import the Panda Modules.
from direct.showbase.DirectObject import DirectObject # To handle Events.
from direct.task import Task # To use Tasks.
from direct.actor import Actor # To use animated Actors.
from direct.interval.IntervalGlobal import * # To use Intervals.
# We need to import this function for the player's rotation to work properly.
from direct.showbase.PythonUtil import closestDestAngle
from direct.gui.OnscreenText import OnscreenText
from direct.gui.OnscreenImage import OnscreenImage
import sys
from draw import *


class Controls(DirectObject):
    def __init__(self):
        base.disableMouse() # Disable default camera.
        self.loadModels()
        self.setupCollisions()
        self.drawGrid()
      
        # Declare variables.
        self.position = None

        self.playerMovement = None
        self.movementSpeed = 6.0 # Controls how long it takes the player to
        # move to the clicked destination.
        self.speed = .10 # Controls the speed of the camera's rotation and zoom.
        # Setup controls
        self.accept("escape", sys.exit)
        self.accept("player-stopped", self.stopWalkAnim)
        self.accept("mouse1", self.moveToPosition)
        self.accept("arrow_left", self.cameraTurn,[-1])
        self.accept("arrow_right", self.cameraTurn,[1])
        self.accept("arrow_up", self.cameraZoom,[-1])
        self.accept("arrow_down", self.cameraZoom,[1])
        self.accept("wheel_up", self.cameraZoom,[-1])
        self.accept("wheel_down", self.cameraZoom,[1])
##        self.accept("g",self.drawGrid)
        
        textObject = OnscreenText(text = 'Du tExte', pos = (-1, 0.7), scale = 0.07)
        
        
        taskMgr.add(self.edgeScreenTracking, "edgeScreenTracking")
        # End __init__

    def drawGrid(self):
     # Create the static elements of the test environment. Use one Draw
            # object for all the static elements.
        d = Draw()

           # Make a 30x30 grid centered at the origin, in Purple.
        d.drawXYGrid(Vec2(-15.5,-15.2), numSquares=30,squareSize=1.03,color=(0.66,0,0.66,1))

      # Draw a grey 100x100x100 cuboid, with the grid we previously drew as the floor of the cuboid.

        d.drawCuboid(Vec3(-5,-5,0), Vec3(5,5,2.5), color=(0.2,0.3,0.9,1))

        node = d.create() # A special GeomNode that draws the shapes.
        np = NodePath(node)
        np.reparentTo(render)


    def loadModels(self):
        # Load an environment
        self.environ = loader.loadModel("models/terrain2.egg")
        self.environ.reparentTo(render) # Place it in the scene.
        self.environ.setPos(0, 0, 0)
        self.environ.setHpr(0, 0, 0)
##        texture = loader.loadTexture("models/rock03.jpg")
##        self.environ.setTexture(texture)
        

        # For the camera to rotate independently of the player a 'player dummy
        # node' and a 'camera dummy node' need to be created. Both dummy nodes
        # are then 'parented' to the 'player dummy node' making them "siblings"
        # under the player dummy node. This means that any transformations
        # performed on the dummy node will be inherited by the player model and
        # the camera. Moving the player dummy node will move both the player
        # model and the camera, but moving or rotating the player model itself
        # won't effect the camera (because the camera isn't directly parented
        # to it).

        # Create the player's dummy node.
        self.player_dummy_node = render.attachNewNode("player_dummy_node")
        # Position the dummy node.
        self.player_dummy_node.setPos(0, 0, 0)
        self.player_dummy_node.setHpr(0, 0, 0)
        # The terrain model was edited by hand to include a start position for
        # the player. Use the Find command to locate it.
        self.playerStart = self.environ.find("**/start_point").getPos()
        # Now load the player model and its animations.
        self.player = Actor.Actor("models/ralph",{"walk":"models/ralph-walk"})
        # Set the player to the start position.
        self.player.setPos(self.playerStart)
        # Attach/parent the player model to the player dummy node.
        self.player.reparentTo(self.player_dummy_node)
        # The player model is too large, so scale it down by 50%.
        self.player.setScale(.5)
        # Now create the camera dummy node.
        self.camera_dummy_node = render.attachNewNode("camera_dummy_node")
        # Attach/parent the camera dummy node to the player dummy node.
        self.camera_dummy_node.reparentTo(self.player_dummy_node)
        # Attach/parent the main camera to the camera dummy node.
        camera.reparentTo(self.camera_dummy_node)
        # Position the main camera.
        camera.setPos(0, -35, 18) # X = left & right, Y = zoom, Z = Up & down.
        camera.setHpr(0, -25, 0) # Heading, pitch, roll.
        # End loadModels

    # Define a function to setup collision detection. We need two rays, one
    # attached to the camera for mouse picking and one attached to the player
    # for collision with the terrain. The rays must only cause collisions and
    # not collide with each other so their Into bitMasks are set to allOff().
    def setupCollisions(self):
        # The terrain model was edited by hand to include the following tag:
        # <Collide> Plane01 { Polyset keep descend }.
        #Once we have the collision tags in the model, we can get to them using
        # the NodePath's find command.
        self.ground = self.environ.find("**/terrain")
        # Set the model's Into collide mask to bit (0). Now only objects that
        # have their From bitmask also set to (0) can collide with the terrain.
        self.ground.node().setIntoCollideMask(BitMask32.bit(0))
        # Create a CollisionTraverser for the picker ray. CollisionTraversers
        # are what do the job of calculating collisions.
        self.picker = CollisionTraverser()
        # Create a handler for the picker ray
        self.queue = CollisionHandlerQueue()
        # Make a collision node for our picker ray
        self.pickerNode = CollisionNode('mouseRay')
        # Attach that node to the camera since the ray will need to be positioned
        # relative to it.
        self.pickerNP = camera.attachNewNode(self.pickerNode)
        # Set the collision node's From collide mask. Now the ray can only cause
        # collisions with objects that have bitMask(0) such as the terrain.
        self.pickerNode.setFromCollideMask(BitMask32.bit(0))
        # Set the collision node's Into collide mask to allOff so that nothing
        # can collide into the ray.
        self.pickerNode.setIntoCollideMask(BitMask32.allOff())
        # Make our ray
        self.pickerRay = CollisionRay()
        # Add it to the collision node
        self.pickerNode.addSolid(self.pickerRay)
        #Register the ray as something that can cause collisions with the traverser
        self.picker.addCollider(self.pickerNP, self.queue)

        # Setup collision stuff to handle the player's collision with the terrain.
        # Make a collision node for the player's ray.
        self.groundCol = CollisionNode('playerRay')
        # Make a collision ray for the player.
        self.groundRay = CollisionRay()
        # Attach the collision node to the player dummy node.
        self.groundColNp = self.player_dummy_node.attachNewNode(self.groundCol)
        # Set the height of the ray (7 units above the player's head)
        self.groundRay.setOrigin(0, 0, 7)
        # Set the rays direction (pointing down on the Z axis)
        self.groundRay.setDirection(0, 0, -1)
        # Add the collision node to the collision ray
        self.groundCol.addSolid(self.groundRay)
        # Set the collision node's From collide mask. Now the ray can collide
        # with objects (like the terrain) that also have bitMask(0).
        self.groundCol.setFromCollideMask(BitMask32.bit(0))
        # Set the collision node's Into collide mask to allOff so that nothing
        # can collide into the ray.
        self.groundCol.setIntoCollideMask(BitMask32.allOff())
        # Make a CollisionTraverser. This will be used in the correctPlayerZ
        # function.
        self.Zcoll = CollisionTraverser()
        # Make a handler for the ground ray. This will be used in the
        # correctPlayerZ function.
        self.ZcollQueue = CollisionHandlerQueue()
        # Register it as something that can cause collisions with the traverser.
        self.Zcoll.addCollider(self.groundColNp, self.ZcollQueue)

        # Uncomment this line to see the collisions
        # self.Zcoll.showCollisions(render)

        # Uncomment this line to see the collision rays
        # self.groundColNp.show()
        # End setupCollisions


    # Define a task to monitor the position of the mouse pointer & rotate
    # the camera when the mouse pointer moves to the edges of the screen.
    def edgeScreenTracking(self,task):
        # Check if the mouse is available
        if not base.mouseWatcherNode.hasMouse():
            return Task.cont
        # Get the relative mouse position, its always between 1 and -1
        mpos = base.mouseWatcherNode.getMouse()
        if mpos.getX() > 0.99:
            self.cameraTurn(1)
        elif mpos.getX() < -0.99:
            self.cameraTurn(-1)
        return Task.cont
        # End edgeScreenTracking

    # Define the CameraTurn function.
    def cameraTurn(self,dir):
        self.camTurn = LerpHprInterval(self.camera_dummy_node, self.speed, Point3(self.camera_dummy_node.getH()-(10*dir), 0, 0))
        self.camTurn.start()
        # End cameraTurn

    # Define the cameraZoom function.
    def cameraZoom(self,dir):
        self.camZoom = LerpPosInterval(camera, self.speed, Point3(camera.getX(), camera.getY()-(2*dir), camera.getZ()+(.8*dir)))
        self.camZoom.start()
        # End cameraZoom

    # Define a function to correct the player's Z axis so that he follows the
    # contours of the ground.
    def correctPlayerZ(self, time):
        startpos = self.player.getPos()
        # Check for collisions
        self.Zcoll.traverse(render)

        #Gestion de la collision : Retir? au profit d'une d?claration d'obstacles
        if self.ZcollQueue.getNumEntries > 0:
         self.ZcollQueue.sortEntries()
         point = self.ZcollQueue.getEntry(0).getSurfacePoint(self.environ)
         self.player.setZ(point.getZ())
        else:
           self.player.setPos(startpos)
        # End correctPlayerZ

    # Define a function to get the position of the mouse click on the terrain.
    def getPosition(self, mousepos):
        self.pickerRay.setFromLens(base.camNode, mousepos.getX(),mousepos.getY())
        # Now check for collisions.
        self.picker.traverse(render)
        if self.queue.getNumEntries() > 0:
            self.queue.sortEntries()
            # This is the clicked position.
            self.position = self.queue.getEntry(0).getSurfacePoint(self.environ)
            # Set its Z axis to remain on the ground.
            self.position.setZ(0)
            return None
        # End getPosition

    # Define a function to make the player turn towards the clicked position
    # and then move to that position.
    def moveToPosition(self):
        # Get the clicked position.
        self.getPosition(base.mouseWatcherNode.getMouse())
        if self.position==None:
           return
        # Create a dummy node.
        self.npLook = render.attachNewNode("npLook")
        # Calculate its position.
        self.npLook.setPos(self.player.getPos(render))
        # Make it look at the clicked position.
        self.npLook.lookAt(self.position)
        # Prevent overturning or 'wrap-around' by adjusting the player's heading
        # by 360 degrees.
        reducedH = self.player.getH()%360.0
        # Set the player's heading to that value.
        self.player.setH(reducedH)
        # Get the player's new heading.
        currH = self.player.getH()
        # Get the dummy node's heading.
        npH = self.npLook.getH()
        # Ralph was modeled facing backwards so we need to add 180 degrees to
        # stop him walking backwards. If your model is not modeled backwards
        # then delete the + 180.0.
        newH = closestDestAngle(currH, npH + 180.0)
        # Create a turn animation from current heading to the calculated new heading.
        playerTurn = self.player.hprInterval(.2, Point3(newH, 0, 0))
        # Calculate the distance between the start and finish positions.
        # This is then used to calculate the duration it should take to
        # travel to the new coordinates based on self.movementSpeed.
        travelVec = self.position - self.player_dummy_node.getPos()
        distance = travelVec.length()
        # Create an animation to make the player move to the clicked position.
        playerMove = self.player_dummy_node.posInterval((distance / self.movementSpeed), self.position)
        # We create a LerpFunc Interval to correct the Z axis as we go along.
        # So that the player stays on the ground.
        playerPositionZ = LerpFunc(self.correctPlayerZ, duration=(distance / self.movementSpeed))

        # Put the animations into a parallel sequence and set the doneEvent.
        if self.playerMovement:
           self.playerMovement.setDoneEvent("")
        self.playerMovement = Parallel(playerTurn, playerMove, playerPositionZ)
        self.playerMovement.setDoneEvent("player-stopped")
        # Play the walk animation.
        self.player.loop("walk")
        self.playerMovement.start()
        # End moveToPosition

    def stopWalkAnim(self):
        # This is called when the movement animation has finished.
        # We can then stop the walk animation.
        self.player.stop("walk")
        self.player.pose("walk",17)
        self.playerMovement = None

c = Controls()

run()

As I said this is just a learning approach no code is mine and I still try to understand how to put a cube for each cekk that will be a wall as also the possibility to toggle the camera to a top-view(editor-type).

David