A few questions regarding panda3D.

Hi there. My name is Ciprian, I’m an 19 year old game enthusiast from Romania. I’ve been programming in C++ for a little over 4 years, and I managed to complete a few games till now (small experiments tbh). Since I’m in my 4th year of Highschool, I had to choose between doing a 1 month end-year course on Python or Visual Basic, and I decided to choose Python. While doing some research I ran over Panda3D, and saw that I could embed the .p3d files and ran the games from a browser. So I decided to re-write some of my old games using Python and Panda3D, and make a portfolio website where I could showcase them.

Anyway, I’ve started rewriting an old SHUMP game of mine and I’m having a few problems regarding movement. It seems a tad to ‘jerky’. I’m a total newcomer when it comes to python and I have a few problems adapting to the syntax. I don’t quite know if what I’m doing is write. Would it be to much to ask for some feedback or suggestions?

# Author: Bacioiu Constantin Ciprian
# Last Update: May 20 2010
#
# Project Name: Negative Space P3DR (Remake using Panda3D)
# Project Details: A classic Shoot 'Em Up. 4 axis movement,
# space key to shoot. It features 3 levels: 2 normal levels
# in which the player has to dodge enemie drones and a 3rd
# one that features an end game boss fight.
#
# Note: The original game was designed using C++ and DarKGDK
# In game sprites and images have been designed by Victorovschi
# Victor from @LiquidPetrifiedStudios. Music was made available
# courtesy of Dragan C. 

from direct.showbase.ShowBase import ShowBase
#from direct.showbase import DirectObject
from panda3d.core import TextNode
from panda3d.core import Point2,Point3,Vec3,Vec4
from direct.gui.OnscreenText import OnscreenText
from direct.showbase.DirectObject import DirectObject
from direct.task.Task import Task
from math import sin, cos, pi
from random import randint, choice, random
from direct.interval.MetaInterval import Sequence
from direct.interval.FunctionInterval import Wait,Func

p3dApp = ShowBase()

#Disable the mouse
base.disableMouse()

background = p3dApp.loader.loadModel("plane")
background.reparentTo(render)
background.setScale(8.0, 1.0, 6.0)
background.setPos(0,10,0)

#Load the background texture
backgroundTexture = p3dApp.loader.loadTexture("layer1.png")
background.setTexture(backgroundTexture,1)




class World(DirectObject):
	def __init__(self):
		self.SetupEvents()
		self.LoadShip()

	def LoadShip(self):
		#Loads a static mesh as a plane and then textures it with our shit texture.
		self.playerShip = p3dApp.loader.loadModel("plane")
		self.playerShip.reparentTo(render)
		self.playerShip.setScale(0.25, 0.25, 0.25)

		#Loads and applies the ship texture.
		self.playerTexture = p3dApp.loader.loadTexture("ship3.png")
		self.playerShip.setTexture(self.playerTexture,1)
		self.playerShip.setPos(0, 7, 0)
		self.playerShip.setAlphaScale(1)
		self.playerShip.setTransparency(1)



	def EventKeyW(self):
		#self.playerShip.setPos(self.playerShip, self.playerShip.getX(), 0, self.playerShip.getZ()+0.1)
		self.playerShip.setZ(self.playerShip.getZ() + 0.0454)

	def EventKeyS(self):
		#self.playerShip.setPos(self.playerShip, self.playerShip.getX(), 0, self.playerShip.getZ()-0.1)
		self.playerShip.setZ(self.playerShip.getZ() - 0.0454)


	def EventKeyD(self):
		self.playerShip.setX(self.playerShip.getX() + 0.0454)


	def EventKeyA(self):
		self.playerShip.setX(self.playerShip.getX() - 0.0454)

	def SetupEvents(self):
		for i in 'wsad':
			self.accept(i, getattr(self, 'EventKey%s'%(i.upper())))
			self.accept(i+'-repeat', getattr(self, 'EventKey%s'%(i.upper())))

w = World()
p3dApp.run()

The game runs ok, both planes have been loaded and textured. But movement seems rather awkward, it’s not fluid enough. Am I using the write approach? I tried following the code from the “asteroids example”, but it’s a little hard to follow.
Thank you, and sorry if I’m wasting your time.

Hi, welcome to the forums!

The movement appears jerky because in your code, every time WASD is pressed, the position of the player ‘jumps’ with a distance of 0.0454 units. You should look into moving the ship gradually in a task. Have you seen the sample programs, specifically the Roaming Ralph sample? It should show how to achieve this.

Hi rdb, thanks for welcoming me. I checked out Roaming-Ralph and made the following changes:

# Author: Bacioiu Constantin Ciprian
# Last Update: May 20 2010
#
# Project Name: Negative Space P3DR (Remake using Panda3D)
# Project Details: A classic Shoot 'Em Up. 4 axis movement,
# space key to shoot. It features 3 levels: 2 normal levels
# in which the player has to dodge enemie drones and a 3rd
# one that features an end game boss fight.
#
# Note: The original game was designed using C++ and DarKGDK
# In game sprites and images have been designed by Victorovschi
# Victor from @LiquidPetrifiedStudios. Music was made available
# courtesy of Dragan C. 

from direct.showbase.ShowBase import ShowBase
import direct.directbase.DirectStart
from panda3d.core import CollisionTraverser,CollisionNode
from panda3d.core import CollisionHandlerQueue,CollisionRay
from panda3d.core import Filename,AmbientLight,DirectionalLight
from panda3d.core import PandaNode,NodePath,Camera,TextNode
from panda3d.core import Vec3,Vec4,BitMask32
from direct.gui.OnscreenText import OnscreenText
from direct.actor.Actor import Actor
from direct.showbase.DirectObject import DirectObject
import random, sys, os, math

SPEED = 0.5

p3dApp = ShowBase()

#Disable the mouse
base.disableMouse()

background = p3dApp.loader.loadModel("plane")
background.reparentTo(render)
background.setScale(8.0, 1.0, 6.0)
background.setPos(0,10,0)

#Load the background texture
backgroundTexture = p3dApp.loader.loadTexture("layer1.png")
background.setTexture(backgroundTexture,1)




class World(DirectObject):
	def __init__(self):
		#self.SetupEvents()
		#self.LoadShip()

		self.keyMap = {"left":0, "right":0, "forward":0}
		#Loads a static mesh as a plane and then textures it with our shit texture.
		self.playerShip = p3dApp.loader.loadModel("plane")
		self.playerShip.reparentTo(render)
		self.playerShip.setScale(0.25, 0.25, 0.25)

		#Loads and applies the ship texture.
		self.playerTexture = p3dApp.loader.loadTexture("ship3.png")
		self.playerShip.setTexture(self.playerTexture,1)
		self.playerShip.setPos(0, 7, 0)
		self.playerShip.setAlphaScale(1)
		self.playerShip.setTransparency(1)

		# Accept the control keys for movement and rotation

		self.accept("escape", sys.exit)
		self.accept("arrow_left", self.setKey, ["left",1])
		self.accept("arrow_right", self.setKey, ["right",1])
		self.accept("arrow_up", self.setKey, ["forward",1])
		self.accept("arrow_left-up", self.setKey, ["left",0])
		self.accept("arrow_right-up", self.setKey, ["right",0])
		self.accept("arrow_up-up", self.setKey, ["forward",0])

		#self.accept("arrow_left-up", self.setKey, ["left",0])
		#self.accept("arrow_right-up", self.setKey, ["right",0])
		#self.accept("arrow_up-up", self.setKey, ["forward",0])


		taskMgr.add(self.move,"moveTask")

	#Records the state of the arrow keys
	def setKey(self, key, value):
		self.keyMap[key] = value

	# Accepts arrow keys to move either the player or the menu cursor,
	# Also deals with grid checking and collision detection
	def move(self, task):

        	# save playerShip's initial position so that we can restore it,

		startpos = self.playerShip.getPos()

		# If a move-key is pressed, move playerShip in the specified direction.

		if (self.keyMap["forward"]!=0):
			self.playerShip.setZ(self.playerShip.getZ() + 0.3 * globalClock.getDt())
		if (self.keyMap["left"]!=0):
			self.playerShip.setX(self.playerShip.getX() - 0.3 * globalClock.getDt())
		if (self.keyMap["right"]!=0):
			self.playerShip.setX(self.playerShip.getX() + 0.3 * globalClock.getDt())

		return task.cont






	#def EventKeyW(self):
		#self.playerShip.setPos(self.playerShip, self.playerShip.getX(), 0, self.playerShip.getZ()+0.1)
		#self.playerShip.setZ(self.playerShip.getZ() + 0.0454)

	#def EventKeyS(self):
		#self.playerShip.setPos(self.playerShip, self.playerShip.getX(), 0, self.playerShip.getZ()-0.1)
		#self.playerShip.setZ(self.playerShip.getZ() - 0.0454)


	#def EventKeyD(self):
		#self.playerShip.setX(self.playerShip.getX() + 0.0454)


	#def EventKeyA(self):
		#self.playerShip.setX(self.playerShip.getX() - 0.0454)

	#def SetupEvents(self):
		#for i in 'wsad':
			#self.accept(i, getattr(self, 'EventKey%s'%(i.upper())))
			#self.accept(i+'-repeat', getattr(self, 'EventKey%s'%(i.upper())))

w = World()
p3dApp.run()

But it outputs the following errors:

  File "main.py", line 90, in move
    if (self.keyMap["forward"]!=0):
AttributeError: World instance has no attribute 'keyMap'
:task(error): Exception occurred in PythonTask moveTask
Traceback (most recent call last):
  File "main.py", line 124, in <module>
    p3dApp.run()
  File "/usr/share/panda3d/direct/showbase/ShowBase.py", line 2531, in run
    self.taskMgr.run()
  File "/usr/share/panda3d/direct/task/Task.py", line 496, in run
    self.step()
  File "/usr/share/panda3d/direct/task/Task.py", line 454, in step
    self.mgr.poll()
  File "main.py", line 90, in move
    if (self.keyMap["forward"]!=0):
AttributeError: World instance has no attribute 'keyMap

As far as I can see, keyMap has been ‘declared’, and I don’t see any difference between my implementation and the one in Roaming-Ralph-tut.py. Any suggestions?

Edit: Ouch, I feel like a fool. Forgot to add self.keyMap = {“left”:0, “right”:0, “forward”:0}