Having a few issues with my game

Hello, everyone!

I’m creating a game for a class, and this is my first time programming or using panda at all. So I’m having trouble, obviously. I’ve mostly got my game down, but I’m having a few issues.
First off, this is a maze game that’s going to have some glowing plants and stuff in it. It’s supposed to be a labyrinth with stones for walls and whatnot, that’s about all I have right now.

The biggest one of my issues is the collisions. They work, but not for long. If i run straight into a wall, after maybe a second I’ll go right through. How can I fix this?

Also, it seems that I can’t get the texturing to appear as I want it to. I don’t want the image to stretch onto the walls; how do I get the image to appear as it is, and just have it repeat instead of stretch?

Additionally, I’ve noticed my camera is sort of a little off. I would like it to rotate on the axis instead of around it (it is very slightly, but it’s causing me some problems so I would like to change that). Is there a way to do that? I couldn’t figure out where in the code that would be changed.

Here is my code in its entirety. Can someone help me figure out these problems? Collisions is probably the most important of all. Thank you!

from panda3d.core import loadPrcFileData
# Configure the parallax mapping settings (these are just the defaults)
loadPrcFileData("", "parallax-mapping-samples 3")
loadPrcFileData("", "parallax-mapping-scale 0.1")

from panda3d.core import WindowProperties
from panda3d.core import Filename,Shader
from panda3d.core import AmbientLight,PointLight
from panda3d.core import TextNode
from panda3d.core import Point3,Vec3,Vec4
from pandac.PandaModules import *
from direct.showbase.ShowBase import ShowBase
from direct.task.Task import Task
from direct.actor.Actor import Actor
from direct.gui.OnscreenText import OnscreenText
from direct.showbase.DirectObject import DirectObject
from direct.filter.CommonFilters import *
import sys,os



# Function to put instructions on the screen.
def addInstructions(pos, msg):
    return OnscreenText(text=msg, style=1, fg=(1,1,1,1),
                        pos=(-1.3, pos), align=TextNode.ALeft, scale = .05)

# Function to put title on the screen.
def addTitle(text):
    return OnscreenText(text=text, style=1, fg=(1,1,1,1),
                        pos=(1.3,-0.95), align=TextNode.ARight, scale = .07)

class BumpMapDemo(ShowBase):

    def __init__(self):
		
        ShowBase.__init__(self)
        base.cTrav = CollisionTraverser()
        base.cTrav.setRespectPrevTransform(True)
        collisionHandler = CollisionHandlerPusher()
        sphereMask = BitMask32.bit(1)
        
        self.filters = CommonFilters(base.win, base.cam)
        filterok = self.filters.setBloom(blend=(0,0,0,1), desat=-0.5, intensity=8.0, size="small")
        if (filterok == False):
            addTitle("Toon Shader: Video card not powerful enough to do image postprocessing")
            return
        self.glowSize=1

        # Check video card capabilities.
        

        if (base.win.getGsg().getSupportsBasicShaders() == 0):
            addTitle("Bump Mapping: Video driver reports that shaders are not supported.")
            return
            
        self.keyMap = {"camera-forward":0}

        # Post the instructions
        self.title = addTitle("shitty labyrinth")
        self.inst1 = addInstructions(0.95, "Press ESC to exit")
        self.inst2 = addInstructions(0.90, "Move mouse to rotate camera")
        self.inst3 = addInstructions(0.85, "Left mouse button: Move forwards")
        self.inst4 = addInstructions(0.80, "Right mouse button: Move backwards")
        
        
        
        self.crystal = loader.loadModel("models/crystals")
        self.crystal.reparentTo(render)
        self.crystal.setScale(0.5,0.5,0.5)
        self.crystal.setHpr(0,-30,30)
        self.crystal.setPos(-11,-68,1)
        
        self.mushroom = loader.loadModel("models/mushroom")
        self.mushroom.reparentTo(render)
        self.mushroom.setScale(0.3,0.3,0.3)
        self.mushroom.setPos(80,-62,5)

        self.room = loader.loadModel("models/mesh")
        texture = loader.loadTexture("models/UV.jpg")
        self.room.setTexture(texture)
        texture.setWrapU(Texture.WM_mirror)
        texture.setWrapV(Texture.WM_mirror)
        self.room.setHpr(0,90,0)
        self.room.setScale(3.0,3.0,3.0)
        self.room.reparentTo(render)
        roomCollider = self.room.find("**/polygons")
        roomCollider.node().setIntoCollideMask(sphereMask)
        
        
        
        self.ball = loader.loadModel("models/ball")
        ballCollider = self.camera.attachNewNode(CollisionNode('cnode'))
        ballCollider.node().addSolid(CollisionSphere(0, 0, 0, 2))
        ballCollider.node().setFromCollideMask(sphereMask)
        base.cTrav.addCollider(ballCollider, collisionHandler)
        collisionHandler.addCollider(ballCollider, self.camera, base.drive.node())
        
        DO = DirectObject()
        DO.accept('cnode-into-polygons', self.collideEventIn)

        collisionHandler.addInPattern('%fn-into-%in')
        collisionHandler.addOutPattern('%fn-out-%in')
        
        mySound = base.loader.loadSfx("cavesound.ogg")
        mySound.play()
        mySound.setVolume(0.5)
        mySound.setLoop(1)
        mySound.setLoopCount(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(80,-62,10)
        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:
        sound = self.loader.loadSfx("running.ogg")
        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("enter", self.toggleShader)
        self.accept("j", self.rotateLight, [-1])
        self.accept("k", self.rotateLight, [1])
        

        #Add a light to the scene.
        self.light = render.attachNewNode("lightpivot")
        self.light.setPos(-50,-25,75)
        #self.light.hprInterval(10,Point3(360,0,0)).loop()
        plight = PointLight('plight')
        plight.setColor(Vec4(1, 1, 1, 1))
        plight.setAttenuation(Vec3(0.7,0.05,0))
        plnp = self.light.attachNewNode(plight)
        plnp.setPos(45, 0, 0)
        self.room.setLight(plnp)
        
        # Add an ambient light
        alight = AmbientLight('alight')
        alight.setColor(Vec4(0.2, 0.2, 0.2, 1))
        alnp = render.attachNewNode(alight)
        self.room.setLight(alnp)

        # create a sphere to denote the light
        sphere = loader.loadModel("models/sphere")
        sphere.reparentTo(plnp)

        # load and apply the shader.  This is using panda's
        # built-in shader generation capabilities to create the
        # shader for you.  However, if desired, you can supply
        # the shader manually.  Change this line of code to:
        #   self.room.setShaderInput("light", plnp)
        #   self.room.setShader(Shader.load("bumpMapper.sha"))
        self.room.setShaderAuto()

        self.shaderenable = 1
        
    def collideEventIn(self,entry):
			colliderINTO = entry.getIntoNodePath().getParent()
			colliderFROM = entry.getFromNodePath().getParent()
			print "hit!"
        
    def setKey(self, key, value):
		self.keyMap[key] = value
        
    def setMouseBtn(self, btn, value):
        self.mousebtn[btn] = value
        

    def rotateLight(self, offset):
        self.lightpivot.setH(self.lightpivot.getH()+offset*0)

    #def rotateCam(self, offset):
        #self.heading = self.heading - offset*10
        
    def toggleGlow(self):
        self.glowSize = self.glowSize + 1
        if (self.glowSize == 4): self.glowSize = 0
        self.filters.setBloom(blend=(0,0,0,1), desat=-0.5, intensity=8.0, size=self.glowSize)

    def toggleShader(self):
        self.inst5.destroy()
        if (self.shaderenable):
            self.inst5 = addInstructions(0.75, "Enter: Turn bump maps On")
            self.shaderenable = 0
            self.room.setShaderOff()
        else:
            self.inst5 = addInstructions(0.75, "Enter: Turn bump maps Off")
            self.shaderenable = 1
            self.room.setShaderAuto()

    def controlCamera(self, task):
        
        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.camera.setHpr(self.heading,self.pitch,0)
        dir = self.camera.getMat().getRow3(1)
        elapsed = task.time - self.last
        if (self.last == 0): elapsed = 0
        if (self.mousebtn[0]):
            self.focus = self.focus + dir * elapsed*30
            
        if (self.mousebtn[1]) or (self.mousebtn[2]):
            self.focus = self.focus - dir * elapsed*30
            
        self.camera.setFluidPos(self.focus - (dir*5))
        if (base.camera.getZ() <   8.0): base.camera.setZ(  8)
        if (base.camera.getZ() >  8.0): base.camera.setZ( 8)
        
        if (self.keyMap["camera-forward"]!=0):
			self.camera.setFluidPos(self.camera.getPos + 100)
        
        self.focus = self.camera.getPos() + (dir*5)
        self.last = task.time
        
        return Task.cont
        
        


t = BumpMapDemo()

run()

That’s likely an issue of UV-mapping: your walls presumably have UV-coordinates ranging from 0 to 1 on both axes, causing the image to be stretched over the entire polygon. However, if the coordinates were to extend outside of that range, then the image should be repeated accordingly (presuming that the texture is set up appropriately). For example, if I’m not much mistaken, if the U-coordinate extends from 0 to 2, then the image should repeat once on that axis (appearing twice in total on the wall); if both axes extend from 0 to 2, then the image should repeat once on both axes, thus appearing four times in total on the wall.

Two ways of achieving this might be to either edit the model’s UV-map in your 3D modelling program, or to apply a scalar to your object’s texture coordinates in code using one of the versions of the “setTexScale” method. See this page for more information.

As to your collision problem, I’m honestly not sure of where the problem lies–you’re using the collision system in a manner that I’m not familiar with, and there’s a fair chunk of code to comb through there.

One thing that may or may not be an issue in some part of your game’s functioning is a line that I spotted towards the end of the code that you posted:

if (self.keyMap["camera-forward"]!=0):
         self.camera.setFluidPos(self.camera.getPos + 100)

In that call to “setFluidPos”, you appear to be passing the method “getPos” of your camera object, rather than the result of a call to it (in short, you’ve left out the brackets after “getPos”); after that, you’re adding 100 to it–the result of which I’m not sure of.

If that’s just a typo, then I’m not entirely sure that it’s doing what you want it to do; I’m not sure of what the result of adding a single value (100) to a three-element vector would be, or is implemented by Panda to be–perhaps it adds 100 to all of the elements? What are you trying to do there?