FPS Physics Engine Class

Hello,

My first attampt at python script, creating a physics based first person camera. Excuse my python, still getting head round lack of encapsulation!

Anyone is free to use this as they please with one caviate that if they make any changes/imporvements they post it here for all to share.

I put all supporting classes in one file to make it easier to share, plus our wonderful proxy server blocks most sites related to file sharing or games!

TODO List:
1 - Make person jump
2 - Make movement by force so gravity can be changed for slowing down motion in water etc
3 - Stop user being able to look between legs, backwards and upside down!
4 - Hide sphere used for collision detection
5 - Add animated model to self.player (Option)
6 - Add weapon to self.player (As option by function so user can start with no weapon)
7 - Add Zoom function for scope on gun or key for binoculars
8 - Couch key option
9 - Prone key option
10- Jet pack key option
11- Torch key option
12- HUD for bullets, mags, lives etc
13- Sounds
14- Toggle third person camera Key option

NOTE: you need to have

set in you egg file for the ground if you don’t want to fall through! (Loads of help on this in other topics, just search)

Please note i modified the following script to use physics engine, so many thanks to treeform for the starting point: https://discourse.panda3d.org/viewtopic.php?t=4068&highlight=fps

Also many thanks to IT-UNIVERSITETET I KØBENHAVN as got most of Phisics engine information from there: http://www.itu.dk/courses/MSU/E2006/Lectures/

"""

Start of a physics based 

CameraControl.FPS(sphereDiameter, CamHeight, gravity,speed, keyForward, keyBack, keyLeft, keyRight, keyJump)

E.g.
CameraControl.FPS(5,10,9.82,20,"w","s","a","d","space")

"""

import direct.directbase.DirectStart
from pandac.PandaModules import *
from direct.actor import Actor
from direct.task import Task
from direct.showbase import DirectObject
import sys

#################################################################################
#	Supporting class
#################################################################################

class Entity(NodePath):
	def __init__(self):
		NodePath.__init__(self,"Entity")

	def setCollisionSolid( self, solid ):
		collNode = CollisionNode( "CollisionNode" )
		collNode.addSolid( solid )
		collNodePath = self.attachNewNode( collNode )
		collNodePath.show()
		return collNodePath
	
	def setModel( self, actor ):
		# Setup the ActorNode
		actor.reparentTo( self )

#################################################################################
#	Supporting class to make physics effected entity
#################################################################################

class DynamicEntity(Entity):
	forceNode = 0
	actorNode = 0

	def __init__(self):
		self.actorNode = ActorNode("DynamicEntity")
		NodePath.__init__(self,self.actorNode)
		# init collision
		self._collisionHandler = PhysicsCollisionHandler()
		base.cTrav = CollisionTraverser()
	
	def createForceNode(self):
		# set up the ForceNode. This contains all the forces that
		# act on this Entity.
		self.forceNode = ForceNode("ForceNode")
		self.attachNewNode( self.forceNode )
		base.physicsMgr.attachPhysicalnode( self.actorNode )
	
	def addLinearForce( self, force ):
		if ( self.forceNode == 0 ):
			self.createForceNode()
		self.forceNode.addForce( force )
		base.physicsMgr.addLinearForce( force )

	def setCollisionSolid( self, solid ):
		collNodePath = Entity.setCollisionSolid( self, solid )
		base.cTrav.addCollider( collNodePath, self.collisionHandler() )
		self.collisionHandler().addCollider( collNodePath, self )
	
	def collisionHandler(self):
		return self._collisionHandler
	
#################################################################################
#	TODO - Make class do something!
#################################################################################

class bullet(object):
	delme = 1	
	def __init__(self):
		#dsfsd
		self.delme = 0
	
#################################################################################
#	TODO - Make class do something!
#################################################################################

class weapon(object):
	delme = 1	
	def __init__(self):
		#dsfsd
		self.delme = 0
			
#################################################################################
#	MAIN First person shooter class
#
#	TODO List:
#	1 - Make person jump
#	2 - Make movement by force so gravity can be changed for slowing down motion in water etc
#	3 - Stop user being able to look between legs, backwards and upside down!
#	4 - Hide sphere used for collision detection
#	5 - Add animated model to self.player (Option)
#	6 - Add weapon to self.player (As option by function so user can start with no weapon)
#	7 - Add Zoom function for scope on gun or key for binoculars
#	8 - Couch key option
#	9 - Prone key option
#	10- Jet pack key option
#	11- Torch key option
#	12- HUD for bullets, mags, lives etc
#	13- Sounds
#	14- Toggle third person camera Key option
#################################################################################

class FPS(object):
	speed = 20
	FORWARD = Vec3(0,2,0)
	BACK = Vec3(0,-1,0)
	LEFT = Vec3(-1,0,0)
	RIGHT = Vec3(1,0,0)
	STOP = Vec3(0)
	walk = STOP
	strafe = STOP
	readyToJump = False
	jump = 0
	sphereDia = 5
	
	def __init__(self, sphereDia, CamHeight,gravity,speed,keyF,keyB,keyL,keyR,keyJ):
		self.sphereDia = sphereDia
		self.gravity = gravity
		self.speed = speed
		
		#Disable standard mouse camera movement
		base.disableMouse()
		
		#Exit app on escape key
		base.accept( "escape" , sys.exit)

		# enable the physics engine in panda
		globalClock.setMaxDt(0.2)   # not sure if this is necessary
		
		# enable the physics manager (and the particle manager...) and
		# add base.updateManagers to the task manager in ShowBase.
		# This causes base.physicsMgr.doPhysics(dt) to be called each frame
		base.enableParticles()
		# we don't actually care about particles, so disable them again.
		base.particleMgrEnabled = 0
		
		# We probably need this to do angular velocity
		#base.addAngularIntegrator()
		
		self.setGravity(gravity)
		
		self.player = DynamicEntity()
		self.loadModel()
		self.setUpCamera(CamHeight)
		
		self.attachControls(keyF,keyB,keyL,keyR,keyJ)
		# init mouse update task
		taskMgr.add(self.mouseUpdate, 'mouse-task')
		taskMgr.add(self.moveUpdate, 'move-task')
		taskMgr.add(self.jumpUpdate, 'jump-task')
		
	def loadModel(self):
		""" make the nodepath for player """
  		#self.player.setModel( Actor.Actor("panda") )
  		self.player.createForceNode()
  		self.player.setCollisionSolid( CollisionSphere(0,0,0,self.sphereDia) )
  		self.player.setPos( 0,0,0)
		self.player.reparentTo( render )
  
	def setUpCamera(self,CamHeight):
		""" puts camera at the players node """
		pl =  base.cam.node().getLens()
		pl.setFov(70)
		base.cam.node().setLens(pl)
		base.camera.setPos(0,0,CamHeight)
		base.camera.reparentTo(self.player)      
		
	def attachControls(self,keyF,keyB,keyL,keyR,keyJ):
		""" attach key events """
		base.accept( keyJ, self.__setattr__,["readyToJump",True])
		base.accept( keyJ+"-up" , self.__setattr__,["readyToJump",False])
		base.accept( keyB , self.__setattr__,["walk",self.STOP] )
		base.accept( keyF , self.__setattr__,["walk",self.FORWARD])
		base.accept( keyB, self.__setattr__,["walk",self.BACK] )
		base.accept( keyB+"-up" , self.__setattr__,["walk",self.STOP] )
		base.accept( keyF+"-up" , self.__setattr__,["walk",self.STOP] )
		base.accept( keyL , self.__setattr__,["strafe",self.LEFT])
		base.accept( keyR , self.__setattr__,["strafe",self.RIGHT] )
		base.accept( keyL+"-up" , self.__setattr__,["strafe",self.STOP] )
		base.accept( keyR+"-up" , self.__setattr__,["strafe",self.STOP] )  
  
	def mouseUpdate(self,task):
	    """ this task updates the mouse """
	    md = base.win.getPointer(0)
	    x = md.getX()
	    y = md.getY()
	    if base.win.movePointer(0, base.win.getXSize()/2, base.win.getYSize()/2):
	    	self.player.setH(self.player.getH() -  (x - base.win.getXSize()/2)*0.1)
	        base.camera.setP(base.camera.getP() - (y - base.win.getYSize()/2)*0.1)
	    return task.cont
		
	def moveUpdate(self,task): 
		""" this task makes the player move """
		# move where the keys set it
		self.player.setPos(self.player,self.walk*globalClock.getDt()*self.speed)
		self.player.setPos(self.player,self.strafe*globalClock.getDt()*self.speed)
		return task.cont
		
	def jumpUpdate(self,task): 
		""" TODO make the player jump  """
		#if self.readyToJump:
        #	self.jump = 1
        #	self.player.addLinearForce( LinearVectorForce(0.0, 0.0, 1.0))
        #else:
        #	self.player.addLinearForce( LinearVectorForce(0.0, 0.0, 0.0))
		return task.cont
		
	def setGravity(self, gravity):
		gravityFN=ForceNode('world-forces')
		gravityFNP=render.attachNewNode(gravityFN)
		gravityForce=LinearVectorForce(0,0, -gravity) #gravity acceleration
		gravityFN.addForce(gravityForce)
		base.physicsMgr.addLinearForce(gravityForce)

#################################################################################

[/code]

I am guessing you are long gone, TALO, but just in case you get the message I have a question for you: did you actually managed to run this code?
I tried to fix it but there are so many things that are broken that I’ve finally gave up. Is there a v2?

1 Like