예제 #1
0
class GameModel:
    #Represents the world data.

    def __init__(self, base, mapNo):
        self.isListening = False

        # Holds rigid bodies, joints, controls global params
        self.world = OdeWorld()
        self.world.setGravity(0, 0, -9.8)

        st = SurfaceType()
        st.load(self.world)
        del st

        self.contactgroup = OdeJointGroup()

        self.space = OdeHashSpace()
        self.space.setAutoCollideWorld(self.world)
        self.space.setAutoCollideJointGroup(self.contactgroup)
        self.space.setCollisionEvent(EventType.ODE_COLLISION)
        base.accept(EventType.ODE_COLLISION, self.onCollision)

        self.ball = Ball(self.world, self.space, "Johanneksen pallo")

        self.level = Level(self, mapNo)
        self.player = Player("Johannes")

        self.camera = Camera(base, self.ball)

    def turnGravityTask(self):
        ''''''
        g = self.world.getGravity()
        g = -g
        self.world.setGravity(g)
        self.camera.turn()

    def turnGravityTask2(self):
        ''''''
        g = self.world.getGravity()
        g2 = self.ball.perpendicularUnitVec3WithFixedX(g)
        g2 *= g.length()
        self.world.setGravity(g2)

    def updateObjects(self):
        '''
		Update objects after one physics iteration
		@see GameLoop.simulationTask
		'''
        self.level.updateModelNode()
        self.camera.updateModelNode()
        #Has to be last for RESTART to work inside Ball
        self.ball.updateModelNode()

    def getBall(self):
        return self.ball

    def getPlayer(self):
        return self.player

    # http://www.panda3d.org/wiki/index.php/Collision_Detection_with_ODE
    def onCollision(self, entry):
        geom1 = entry.getGeom1()
        geom2 = entry.getGeom2()
        body1 = entry.getBody1()
        body2 = entry.getBody2()

        # Is the ball touching something?
        if body1 == self.ball.getBody() or body2 == self.ball.getBody():
            self.ball.refreshCollisionTime(entry)

        for coin in self.level.getCoins():
            if body1 == coin.getBody() and body2 == self.ball.getBody():
                coin.collect()
                messenger.send(EventType.UPDATE_HUD)

        exit = self.level.getExit()
        if geom1 == exit or geom2 == exit:
            if Coin.collectable == self.level.getGoal():
                # todo: make event based
                messenger.send(EventType.NEXT_LEVEL)

    def cleanUp(self):
        self.level.removeLevel()
        self.ball.removeNode()
예제 #2
0
class World:
	def __init__(self, game):
		self.game = game
		self.world = OdeWorld()
		self.world.setGravity(0, 0, -9.81 * 3)
		self.group = OdeJointGroup()
		self.space = OdeHashSpace()
		self.space.setAutoCollideWorld(self.world)
		self.space.setAutoCollideJointGroup(self.group)
		self.setSurfaceTables()
		self.objects = []
		self.objectsToRemove = []
		self.postStepTasks = []

		self.engineRunning = True
		self.dtAccumulator = 0.0
		self.physicsFps = 90
		self.physicsMinFps = 10
		base.taskMgr.doMethodLater(0.1, self.processPhysics, "Physics")
		base.accept("escape", self.togglePhysics)

		self.space.setCollisionEvent("odeCollision")
		base.accept("odeCollision", self.onCollision)
		
	def setSurfaceTables(self):
		self.surfaces = {}
		self.surfaces["plane"] = 0
		self.surfaces["box"] = 1
		self.surfaces["sphere"] = 2
		self.surfaces["bullet"] = 3
		n = len(self.surfaces)

		self.world.initSurfaceTable(n)
		for i in range(n):
			for j in range(n):
				# id1, id2, mu (0 to inf), bounce (1 = bouncy), min_bounce_vel, erp (1 = hard), cfm (0 = hard), slip, dampen
				# sample:   150,             0.0,                    9.1,       0.9,          0.00001,          0.0,  0.002
				self.world.setSurfaceEntry(i, j, 10.0, 1.0, 0.0, 0.9, 0.0, 0.5, 0.001) # Default value for unspecified pairs.
		self.world.setSurfaceEntry(self.surfaces["box"], self.surfaces["box"],
			200.0, 0.2, 0.3, 1.0, 0.0, 0.0, 0.01)
		self.world.setSurfaceEntry(self.surfaces["plane"], self.surfaces["box"],
			200.0, 0.2, 0.3, 1.0, 0.0, 0.0, 0.01)
		self.world.setSurfaceEntry(self.surfaces["box"], self.surfaces["bullet"],
			10.0, 0.1, 0.5, 1.0, 0.0, 0.0, 0.01)
		self.world.setSurfaceEntry(self.surfaces["plane"], self.surfaces["bullet"],
			100.0, 0.01, 0.1, 1.0, 0.0, 0.0, 1.0)

	def addObject(self, obj):
		self.objects.append(obj)

	def removeObject(self, obj):
		if obj not in self.objectsToRemove:
			self.objectsToRemove.append(obj)

	def removeDestroyedObjects(self):
		while len(self.objectsToRemove) > 0:
			obj = self.objectsToRemove.pop()
			if obj in self.objects:
				self.objects.remove(obj)
				obj.doDestroy()

	def togglePhysics(self):
		self.engineRunning = not self.engineRunning
		self.dtAccumulator = 0.0

	def processPhysics(self, task):
		stepSize = 1.0 / self.physicsFps
		maxDt = 1.0 / self.physicsMinFps
		if self.engineRunning:
			self.dtAccumulator += globalClock.getDt()
			self.dtAccumulator = min(self.dtAccumulator, maxDt)
			while self.dtAccumulator >= stepSize:
				self.space.autoCollide()
				self.world.quickStep(stepSize)
				for obj in self.objects:
					obj.updatePosFromPhysics()
				self.group.empty()
				self.performPostStepTasks()
				self.removeDestroyedObjects()
				self.dtAccumulator -= stepSize
		return task.cont

	def onCollision(self, entry):
		body1 = entry.getBody1()
		body2 = entry.getBody2()
		if not body1.isEmpty():
			body1.getData().onCollision(body2, entry)
		if not body2.isEmpty():
			body2.getData().onCollision(body1, entry)

	def performAfterStep(self, method, params):
		self.postStepTasks.append([method, params])

	def performPostStepTasks(self):
		for task in self.postStepTasks:
			method = task[0]
			params = task[1]
			method(*params)
		self.postStepTasks = []