camera conect to collision ray

Hay another newbie,

I’m trying to combine several tutorials.
But it isn’t working the way it should.

I’m tryng to get a first person camera that interacts with the envirment, so that it collides with it’s surroundings.

this is the code i have so far.

#

import direct.directbase.DirectStart
from pandac.PandaModules import CollisionTraverser,CollisionNode 
from pandac.PandaModules import CollisionHandlerQueue,CollisionRay 
from pandac.PandaModules import WindowProperties 
from pandac.PandaModules import Filename,Shader 
from pandac.PandaModules import PerspectiveLens
from pandac.PandaModules import NodePath,LightAttrib
from pandac.PandaModules import AmbientLight,DirectionalLight
from pandac.PandaModules import TextNode,PandaNode,NodePath,Camera 
from direct.task.Task import Task 
from direct.actor.Actor import Actor 
from pandac.PandaModules import Point3,Vec3,Vec4,BitMask32 # Point3 - 2 BitMask32
from direct.gui.OnscreenText import OnscreenText
from direct.showbase.DirectObject import DirectObject
import math, sys, colorsys,random, os # os - 2 random

SPEED = 0.5 

#Simple function to keep a value in a given range (by default 0 to 1)
def restrain(i, mn = 0, mx = 1): return min(max(i, mn), mx)

class World(DirectObject):
  #Macro-like function to reduce the amount of code needed to create the
  #onscreen instructions
  def makeStatusLabel(self, i):
    return OnscreenText(
      style=1, fg=(1,1,0,1), pos=(-1.3, 0.95 - (.05 * i)),
      align=TextNode.ALeft, scale = .05, mayChange = 1)

  def controlCamera(self, task):
        # figure out how much the mouse has moved (in pixels)
        md = base.win.getPointer(0)
        x = md.getX()
        y = md.getY()
        if base.win.movePointer(0, 100, 100):
            self.heading = self.heading - (x - 100)*0.2
            self.pitch = self.pitch - (y - 100)*0.2
        if (self.pitch < -45): self.pitch = -45
        if (self.pitch >  45): self.pitch =  45
        base.camera.setHpr(self.heading,self.pitch,0)
        dir = base.camera.getMat().getRow3(1)
        dirs = base.camera.getMat().getRow3(0)
        elapsed = task.time - self.last
        if (self.last == 0): elapsed = 0
        if (self.keyMap["forward"]): #2 self.keyMap[0]
            self.focus = self.focus + dir * elapsed*30
        if (self.keyMap["back"]): #3 self.keyMap[0]
            self.focus = self.focus - dir * elapsed*30
        if (self.keyMap["left"]): #3 self.keyMap[0]
            self.focus = self.focus - dirs * elapsed*30
        if (self.keyMap["right"]): #3 self.keyMap[0]
            self.focus = self.focus + dirs * elapsed*30
        base.camera.setPos(self.focus - (dir*5))
        #if (base.camera.getX() < -49.0): base.camera.setX(-49)
        #if (base.camera.getX() >  49.0): base.camera.setX( 49)
        #if (base.camera.getY() < -49.0): base.camera.setY(-49)
        #if (base.camera.getY() >  49.0): base.camera.setY( 49)
        #if (base.camera.getZ() <   1.0): base.camera.setZ(  1)
        #if (base.camera.getZ() >  49.0): base.camera.setZ( 49)
        self.focus = base.camera.getPos() + (dir*5)
        self.last = task.time
        return Task.cont

  def setMouseBtn(self, btn, value):
        self.mousebtn[btn] = value

  # key definitie
  def setKey(self, key, value):
        self.keyMap[key] = value

 
  # This function takes a list of lights and toggles their state. It takes in a
  # list so that more than one light can be toggled in a single command
  def toggleLights( self, lights ): 
    for light in lights:
      #If the given light is in our lightAttrib, remove it.
      #This has the effect of turning off the light
      if self.lightAttrib.hasLight(light):   
        self.lightAttrib = self.lightAttrib.removeLight( light )
      #Otherwise, add it back. This has the effect of turning the light on
      else:
        self.lightAttrib = self.lightAttrib.addLight( light )

    #Reset the lightAttrib on render to tell it that the lighting has changed
    render.node().setAttrib( self.lightAttrib )
    self.updateStatusLabel()

  #This function reads the color of the light, uses a built-in python function
  #(from the library colorsys) to convert from RGB (red, green, blue) color
  #representation to HSB (hue, saturation, brightness), so that we can get the
  #brighteness of a light, change it, and then convert it back to rgb to chagne
  #the light's color
  def addBrightness( self, light, amount ):
    color = light.getColor()
    h, s, b = colorsys.rgb_to_hsv( color[0], color[1], color[2] )
    brightness = restrain(b + amount)
    r, g, b = colorsys.hsv_to_rgb( h, s, brightness )
    light.setColor( Vec4( r, g, b, 1 ) )

    self.updateStatusLabel()

  #Builds the onscreen instruction labels
  def updateStatusLabel( self ):
    self.updateLabel(self.ambientText, "(a) ambient is",
                     self.lightAttrib.hasLight( self.ambientLight ) )
    self.updateLabel(self.directionalText, "(d) directional is",
                     self.lightAttrib.hasLight( self.directionalLight ) )
    self.ambientBrightnessText.setText(
      "(z,x) Ambient Brightness: " +
      self.getBrightnessString(self.ambientLight))
    self.directionalBrightnessText.setText(
      "(c,v) Directional Brightness: " +
      self.getBrightnessString(self.directionalLight))
    
  #Appends eitehr (on) or (off) to the base string based on the bassed value
  def updateLabel(self, obj, base, var):
    if var: s = " (on)"
    else:   s = " (off)"
    obj.setText(base + s)
    
  #Returns the brightness of a light as a string to put it in the instruction
  #labels
  def getBrightnessString( self, light ):
    color = light.getColor()
    h, s, b = colorsys.rgb_to_hsv( color[0], color[1], color[2] )
    return "%.2f" % b

  def __init__( self ):
  #The main initialization of our class
    #This creates the on screen title that is in every tutorial
    self.title = OnscreenText(text="BGaa 118-400, Heiloo",
                              style=1, fg=(1,1,0,1),
                              pos=(0.87,-0.95), scale = .07)


    self.keyMap = {"forward":0, "back":0, "left":0, "right":0}
      


    #Creates labels used for onscreen instructions
    self.ambientText = self.makeStatusLabel(0)
    self.directionalText = self.makeStatusLabel(1)
    self.spinningText = self.makeStatusLabel(2)
    self.ambientBrightnessText = self.makeStatusLabel(3)
    self.directionalBrightnessText = self.makeStatusLabel(4)
    
    self.environ = loader.loadModel("models/disco_hall")
    self.environ.reparentTo(render)
    self.environ.setScale(0.025,0.025,0.025) 
    self.environ.setPosHpr(0, 25, 0, 90, 0, 0)

    # Make the mouse invisible, turn off normal mouse controls
    base.disableMouse()
    props = WindowProperties()
    props.setCursorHidden(True)
    base.win.requestProperties(props)

    # Set the current viewing target
    self.focus = Vec3(48,0,25)
    self.heading = 180
    self.pitch = 0
    self.mousex = 0
    self.mousey = 0
    self.last = 0
    self.mousebtn = [0,0,0]
  

    # Start the camera control task
    taskMgr.add(self.controlCamera, "camera-task")
    self.accept("escape", sys.exit, [0])
    self.accept("mouse1", self.setMouseBtn, [0, 1])
    self.accept("mouse1-up", self.setMouseBtn, [0, 0])
    self.accept("mouse2", self.setMouseBtn, [1, 1])
    self.accept("mouse2-up", self.setMouseBtn, [1, 0])
    self.accept("mouse3", self.setMouseBtn, [2, 1])
    self.accept("mouse3-up", self.setMouseBtn, [2, 0])
    self.accept("arrow_left", self.setKey, ["left", 1])
    self.accept("arrow_left-up", self.setKey, ["left", 0])
    self.accept("arrow_right", self.setKey, ["right", 1])
    self.accept("arrow_right-up", self.setKey, ["right", 0])
    self.accept("arrow_up", self.setKey, ["forward", 1]) #2
    self.accept("arrow_up-up", self.setKey, ["forward", 0]) #2
    self.accept("arrow_down", self.setKey, ["back", 1]) #3
    self.accept("arrow_down-up", self.setKey, ["back", 0]) #3

    # To light a scene, we will first create a LightAttrib, which is a container
    # to manager our lights. We will then create the lights, add them to the
    # lightAttrib, and finally set them to affect a node and all nodes below it
    # in our scene

    #Default lightAttrib with no lights
    self.lightAttrib = LightAttrib.makeAllOff() 

    # First we create an ambient light. All objects are affected by ambient
    # light equally
    #Create and name the ambient light
    self.ambientLight = AmbientLight( "ambientLight" )
    #Set the color of the ambient light
    self.ambientLight.setColor( Vec4( .2, .2, .2, 1 ) )
    #add the newly created light to the lightAttrib
    self.lightAttrib = self.lightAttrib.addLight( self.ambientLight )

    # Now we create a directional light. Directional lights add shading from a
    # given angle. This is good for far away sources like the sun
    self.directionalLight = DirectionalLight( "directionalLight" )
    self.directionalLight.setColor( Vec4( .7, .7, .7, 1 ) )
    # The direction of a directional light is set as a 3D vector
    self.directionalLight.setDirection( Vec3( 1, 1, -2 ) )
    self.lightAttrib = self.lightAttrib.addLight( self.directionalLight ) 

    #Finally we set the light attrib to a node. In this case we are using render
    #so that the lights will effect everything, but you could put it on any
    #part of the scene
    render.node().setAttrib( self.lightAttrib )

    # listen to keys for controlling the lights
    self.accept( "escape", sys.exit)
    self.accept( "a", self.toggleLights, [[self.ambientLight]] )
    self.accept( "d", self.toggleLights, [[self.directionalLight]] )
    self.accept( "z", self.addBrightness, [self.ambientLight, -.05] )
    self.accept( "x", self.addBrightness, [self.ambientLight, .05] )
    self.accept( "c", self.addBrightness, [self.directionalLight, -.05] )
    self.accept( "v", self.addBrightness, [self.directionalLight, .05] )
   
    #Finally call the function that builds the instruction texts
    self.updateStatusLabel()

    #3 Create a floater object.  We use the "floater" as a temporary
    #3 variable in a variety of calculations.
 
    self.floater = NodePath(PandaNode("floater"))
    self.floater.reparentTo(render)

    #3 Game state variables
    self.isMoving = False
    
    #3 We will detect the height of the terrain by creating a collision
    #3 ray and casting it downward toward the terrain.  One ray will
    #3 start above ralph's head, and the other will start above the camera.
    #3 A ray may hit the terrain, or it may hit a rock or a tree.  If it
    #3 hits the terrain, we can detect the height.  If it hits anything
    #3 else, we rule that the move is illegal.

    self.cTrav = CollisionTraverser()
    self.environ.setCollideMask(BitMask32.bit(1))
 
    self.camGroundRay = CollisionRay()
    self.camGroundRay.setOrigin(0,0,2000)
    self.camGroundRay.setDirection(0,0,-1)
    self.camGroundCol = CollisionNode('camRay')
    self.camGroundCol.addSolid(self.camGroundRay)
    self.camGroundCol.setFromCollideMask(BitMask32.bit(1))
    self.camGroundCol.setIntoCollideMask(BitMask32.allOff())
    self.camGroundColNp = base.camera.attachNewNode(self.camGroundCol)
    self.camGroundHandler = CollisionHandlerQueue()
    self.cTrav.addCollider(self.camGroundColNp, self.camGroundHandler)

    #3 Uncomment this line to see the collision rays
    self.camGroundColNp.show()
    self.cTrav.showCollisions(render)

    #3 save ralph's initial position so that we can restore it,
    #3 in case he falls off the map or runs into something.
    startpos = base.camera.getPos()
   

    #3 Now check for collisions.

    self.cTrav.traverse(render)
 
    entries = []
    for i in range(self.camGroundHandler.getNumEntries()):
        entry = self.camGroundHandler.getEntry(i)
        entries.append(entry)
    entries.sort(lambda x,y: cmp(y.getSurfacePoint(render).getZ(),
                                 x.getSurfacePoint(render).getZ()))
    if (len(entries)>0) and (entries[0].getIntoNode().getName() == "Plane01"):
        base.camera.setZ(entries[0].getSurfacePoint(render).getZ()+1.0)
    else:
        base.camera.setPos(startpos)
 


#Make an instance of our class and run the world
w = World()
run()

The problem is the camera works fine, but it’s not connected to the collisionray i can see the collisionray and the colliding polygons, The camera needs to be a few feet above ground level.

please help, and can you explaine what you do, i really want to master this.

thanks
[/code]

The most obvious problem here is, you are not checking for collisions every frame. If you look at roaming ralph demo carefully, you’ll see that collision detection (a for loop dealing with self.camGroundHandler) occurs inside a task called move, which is called every frame. I think this is the first thing you should fix.

You can use your existing camera control task for a start.

OK, I fixed it:

# Author: Jason Pratt (pratt@andrew.cmu.edu)
# Last Updated: 10/20/2003

#
# This project demonstrates how to use various types of
# lighting
#

import direct.directbase.DirectStart
from pandac.PandaModules import CollisionTraverser,CollisionNode #2
from pandac.PandaModules import CollisionHandlerQueue,CollisionRay #2
from pandac.PandaModules import WindowProperties #
from pandac.PandaModules import Filename,Shader #
from pandac.PandaModules import PerspectiveLens
from pandac.PandaModules import NodePath,LightAttrib
from pandac.PandaModules import AmbientLight,DirectionalLight
from pandac.PandaModules import TextNode,PandaNode,NodePath,Camera #2 PandaNode,NodePath,Camera
from direct.task.Task import Task #
from direct.actor.Actor import Actor #
from pandac.PandaModules import Point3,Vec3,Vec4,BitMask32 # Point3 - 2 BitMask32
from direct.gui.OnscreenText import OnscreenText
from direct.showbase.DirectObject import DirectObject
import math, sys, colorsys,random, os # os - 2 random

SPEED = 0.5 #2

#Simple function to keep a value in a given range (by default 0 to 1)
def restrain(i, mn = 0, mx = 1): return min(max(i, mn), mx)

class World(DirectObject):
  #Macro-like function to reduce the amount of code needed to create the
  #onscreen instructions
  def makeStatusLabel(self, i):
    return OnscreenText(
      style=1, fg=(1,1,0,1), pos=(-1.3, 0.95 - (.05 * i)),
      align=TextNode.ALeft, scale = .05, mayChange = 1)

  def controlCamera(self, task):
        # figure out how much the mouse has moved (in pixels)
        md = base.win.getPointer(0)
        x = md.getX()
        y = md.getY()
        if base.win.movePointer(0, 100, 100):
            self.heading = self.heading - (x - 100)*0.2
            self.pitch = self.pitch - (y - 100)*0.2
        if (self.pitch < -45): self.pitch = -45
        if (self.pitch >  45): self.pitch =  45
        self.mycam.setHpr(self.heading,self.pitch,0)
        dir = self.mycam.getMat().getRow3(1)
        dir.setZ(0)
        dirs = self.mycam.getMat().getRow3(0)
        elapsed = task.time - self.last
        if (self.last == 0): elapsed = 0
        if (self.keyMap["forward"]): #2 self.keyMap[0]
            self.focus = self.focus + dir * elapsed*30*SPEED
        if (self.keyMap["back"]): #3 self.keyMap[0]
            self.focus = self.focus - dir * elapsed*30*SPEED
        if (self.keyMap["left"]): #3 self.keyMap[0]
            self.focus = self.focus - dirs * elapsed*30*SPEED
        if (self.keyMap["right"]): #3 self.keyMap[0]
            self.focus = self.focus + dirs * elapsed*30*SPEED
        self.mycam.setPos(self.focus - (dir*5))
        if (self.mycam.getX() < -49.0): self.mycam.setX(-49)
        if (self.mycam.getX() >  49.0): self.mycam.setX( 49)
        if (self.mycam.getY() < -49.0): self.mycam.setY(-49)
        if (self.mycam.getY() >  49.0): self.mycam.setY( 49)
        if (self.mycam.getZ() <   1.0): self.mycam.setZ(  1)
        if (self.mycam.getZ() >  49.0): self.mycam.setZ( 49)
        self.focus = self.mycam.getPos() + (dir*5)
        self.last = task.time
        return Task.cont

  def setMouseBtn(self, btn, value):
        self.mousebtn[btn] = value

  #2 key definitie
  def setKey(self, key, value):
        self.keyMap[key] = value

 
  # This function takes a list of lights and toggles their state. It takes in a
  # list so that more than one light can be toggled in a single command
  def toggleLights( self, lights ): 
    for light in lights:
      #If the given light is in our lightAttrib, remove it.
      #This has the effect of turning off the light
      if self.lightAttrib.hasLight(light):   
        self.lightAttrib = self.lightAttrib.removeLight( light )
      #Otherwise, add it back. This has the effect of turning the light on
      else:
        self.lightAttrib = self.lightAttrib.addLight( light )

    #Reset the lightAttrib on render to tell it that the lighting has changed
    render.node().setAttrib( self.lightAttrib )
    self.updateStatusLabel()

  #This function reads the color of the light, uses a built-in python function
  #(from the library colorsys) to convert from RGB (red, green, blue) color
  #representation to HSB (hue, saturation, brightness), so that we can get the
  #brighteness of a light, change it, and then convert it back to rgb to chagne
  #the light's color
  def addBrightness( self, light, amount ):
    color = light.getColor()
    h, s, b = colorsys.rgb_to_hsv( color[0], color[1], color[2] )
    brightness = restrain(b + amount)
    r, g, b = colorsys.hsv_to_rgb( h, s, brightness )
    light.setColor( Vec4( r, g, b, 1 ) )

    self.updateStatusLabel()

  #Builds the onscreen instruction labels
  def updateStatusLabel( self ):
    self.updateLabel(self.ambientText, "(a) ambient is",
                     self.lightAttrib.hasLight( self.ambientLight ) )
    self.updateLabel(self.directionalText, "(d) directional is",
                     self.lightAttrib.hasLight( self.directionalLight ) )
    self.ambientBrightnessText.setText(
      "(z,x) Ambient Brightness: " +
      self.getBrightnessString(self.ambientLight))
    self.directionalBrightnessText.setText(
      "(c,v) Directional Brightness: " +
      self.getBrightnessString(self.directionalLight))
    
  #Appends eitehr (on) or (off) to the base string based on the bassed value
  def updateLabel(self, obj, base, var):
    if var: s = " (on)"
    else:   s = " (off)"
    obj.setText(base + s)
    
  #Returns the brightness of a light as a string to put it in the instruction
  #labels
  def getBrightnessString( self, light ):
    color = light.getColor()
    h, s, b = colorsys.rgb_to_hsv( color[0], color[1], color[2] )
    return "%.2f" % b

  def __init__( self ):
  #The main initialization of our class
    #This creates the on screen title that is in every tutorial
    self.title = OnscreenText(text="BGaa 118-400, Heiloo",
                              style=1, fg=(1,1,0,1),
                              pos=(0.87,-0.95), scale = .07)

#2================
    self.keyMap = {"forward":0, "back":0, "left":0, "right":0}
      
#2================

    #Creates labels used for onscreen instructions
    self.ambientText = self.makeStatusLabel(0)
    self.directionalText = self.makeStatusLabel(1)
    self.spinningText = self.makeStatusLabel(2)
    self.ambientBrightnessText = self.makeStatusLabel(3)
    self.directionalBrightnessText = self.makeStatusLabel(4)
    
    self.environ=loader.loadModel("models/disco_hall")
    self.environ.reparentTo(render)
    self.environ.setScale(0.025,0.025,0.025) 
    self.environ.setPosHpr(0, 25, 0, 90, 0, 0)

    # Make the mouse invisible, turn off normal mouse controls
    base.disableMouse()
    props = WindowProperties()
    props.setCursorHidden(True)
    base.win.requestProperties(props)

    # Set the current viewing target
    self.focus = Vec3(48,0,25)
    self.heading = 180
    self.pitch = 0
    self.mousex = 0
    self.mousey = 0
    self.last = 0
    self.mousebtn = [0,0,0]
  

    # Start the camera control task
    taskMgr.add(self.controlCamera, "camera-task")
    self.accept("escape", sys.exit, [0])
    self.accept("mouse1", self.setMouseBtn, [0, 1])
    self.accept("mouse1-up", self.setMouseBtn, [0, 0])
    self.accept("mouse2", self.setMouseBtn, [1, 1])
    self.accept("mouse2-up", self.setMouseBtn, [1, 0])
    self.accept("mouse3", self.setMouseBtn, [2, 1])
    self.accept("mouse3-up", self.setMouseBtn, [2, 0])
    self.accept("arrow_left", self.setKey, ["left", 1])
    self.accept("arrow_left-up", self.setKey, ["left", 0])
    self.accept("arrow_right", self.setKey, ["right", 1])
    self.accept("arrow_right-up", self.setKey, ["right", 0])
    self.accept("arrow_up", self.setKey, ["forward", 1]) #2
    self.accept("arrow_up-up", self.setKey, ["forward", 0]) #2
    self.accept("arrow_down", self.setKey, ["back", 1]) #3
    self.accept("arrow_down-up", self.setKey, ["back", 0]) #3

    # To light a scene, we will first create a LightAttrib, which is a container
    # to manager our lights. We will then create the lights, add them to the
    # lightAttrib, and finally set them to affect a node and all nodes below it
    # in our scene

    #Default lightAttrib with no lights
    self.lightAttrib = LightAttrib.makeAllOff() 

    # First we create an ambient light. All objects are affected by ambient
    # light equally
    #Create and name the ambient light
    self.ambientLight = AmbientLight( "ambientLight" )
    #Set the color of the ambient light
    self.ambientLight.setColor( Vec4( .2, .2, .2, 1 ) )
    #add the newly created light to the lightAttrib
    self.lightAttrib = self.lightAttrib.addLight( self.ambientLight )

    # Now we create a directional light. Directional lights add shading from a
    # given angle. This is good for far away sources like the sun
    self.directionalLight = DirectionalLight( "directionalLight" )
    self.directionalLight.setColor( Vec4( .7, .7, .7, 1 ) )
    # The direction of a directional light is set as a 3D vector
    self.directionalLight.setDirection( Vec3( 1, 1, -2 ) )
    self.lightAttrib = self.lightAttrib.addLight( self.directionalLight ) 

    #Finally we set the light attrib to a node. In this case we are using render
    #so that the lights will effect everything, but you could put it on any
    #part of the scene
    render.node().setAttrib( self.lightAttrib )

    # listen to keys for controlling the lights
    self.accept( "escape", sys.exit)
    self.accept( "a", self.toggleLights, [[self.ambientLight]] )
    self.accept( "d", self.toggleLights, [[self.directionalLight]] )
    self.accept( "z", self.addBrightness, [self.ambientLight, -.05] )
    self.accept( "x", self.addBrightness, [self.ambientLight, .05] )
    self.accept( "c", self.addBrightness, [self.directionalLight, -.05] )
    self.accept( "v", self.addBrightness, [self.directionalLight, .05] )
   
    #Finally call the function that builds the instruction texts
    self.updateStatusLabel()

    #3 Create a floater object.  We use the "floater" as a temporary
    #3 variable in a variety of calculations.
 
    self.floater = NodePath(PandaNode("floater"))
    self.floater.reparentTo(render)

    #3 Game state variables
    self.isMoving = False
    self.mycam=render.attachNewNode("camera")
    base.camera.reparentTo(self.mycam)
    #3 We will detect the height of the terrain by creating a collision
    #3 ray and casting it downward toward the terrain.  One ray will
    #3 start above ralph's head, and the other will start above the camera.
    #3 A ray may hit the terrain, or it may hit a rock or a tree.  If it
    #3 hits the terrain, we can detect the height.  If it hits anything
    #3 else, we rule that the move is illegal.

    self.cTrav = CollisionTraverser()
    self.environ.setCollideMask(BitMask32.bit(1))
 
    self.camGroundRay = CollisionRay()
    self.camGroundRay.setOrigin(0,0,1000)
    self.camGroundRay.setDirection(0,0,-10)
    self.camGroundCol = CollisionNode('camRay')
    self.camGroundCol.addSolid(self.camGroundRay)
    self.camGroundCol.setFromCollideMask(BitMask32.bit(1))
    self.camGroundCol.setIntoCollideMask(BitMask32.allOff())
    self.camGroundColNp = self.mycam.attachNewNode(self.camGroundCol)
    self.camGroundHandler = CollisionHandlerQueue()
    self.cTrav.addCollider(self.camGroundColNp, self.camGroundHandler)

    #3 Uncomment this line to see the collision rays
    self.camGroundColNp.show()
    self.cTrav.showCollisions(render)

    #3 save ralph's initial position so that we can restore it,
    #3 in case he falls off the map or runs into something.
    self.startpos = self.mycam.getPos()
    self.mycam.setZ(10)
    taskMgr.add(self.checkCollisions,"checkColl")

  def checkCollisions(self,task):
    #3 Now check for collisions.

    self.cTrav.traverse(render)
 
    entries = []
    for i in range(self.camGroundHandler.getNumEntries()):
        entry = self.camGroundHandler.getEntry(i)
        entries.append(entry)
    entries.sort(lambda x,y: cmp(y.getSurfacePoint(render).getZ(),
                                 x.getSurfacePoint(render).getZ()))
    if (len(entries)>0) and (entries[0].getSurfacePoint(render).getZ()<self.mycam.getZ()+1.0):
        self.mycam.setZ(entries[0].getSurfacePoint(render).getZ()+1.0)
    #else:
    #    self.mycam.setPos(self.startpos)
    self.startpos=self.mycam.getPos()
    return task.cont
 


#Make an instance of our class and run the world
w = World()
run()

But, there’s a lot of things wrong with your movement code. You’d better rewrite the code. Not just c&p from the examples, cuz’ camera movement is more difficult than normal player movement.

Pro-rsoft, the script works fine.

i just want one more change, but i’am puzzeld.

    if (len(entries)>0) and (entries[0].getSurfacePoint(render).getZ()<self.mycam.getZ()+1.0): 
        self.mycam.setZ(entries[0].getSurfacePoint(render).getZ()+1.0) 

this code sets the camera on the surface, but it looks like it only checks the lowergrounds in my opinion, but the camera also steps up.

Can we change this so that it only steps up to surfaces a surtain amount above it’s currant position. (now it’s like santa clause, walks on roofs)

thanks again…

try lowering the first 1.0 value:


    if (len(entries)>0) and (entries[0].getSurfacePoint(render).getZ()<self.mycam.getZ()+0.05):
        self.mycam.setZ(entries[0].getSurfacePoint(render).getZ()+1.0) 

that doesn’t work, I lowerd the number to 0.000000002.
In my opinion the surface point is always lower than the camera point + a certain number.
The script also works if you leave out

and (entries[0].getSurfacePoint(render).getZ()<self.mycam.getZ()+0.05)

I think that some how he must compare the previous height with the new height

Maybe you can yourself do a little bit thinking.
len(entries) is the number of objects where the camera ray collides with.
entries[0].getSurfacePoint(render).getZ() is the Z point of the ground beneath the player.
self.mycam.getZ() is the Z position of the camera.
the code translated in english:

if (the ray collides with an object) and (the floor beneath the camera is lower than (the camera+0.05)) then it adjusts the position to the new one