from panda3d.core import NodePath, Plane, Vec3, Point3, CollisionPlane, CollisionNode from direct.showbase.RandomNumGen import RandomNumGen from direct.showbase.DirectObject import DirectObject from direct.showbase.PythonUtil import bound as clamp import CogdoUtil import CogdoFlyingGameGlobals as Globals from CogdoFlyingLevelQuadrant import CogdoFlyingLevelQuadrant from CogdoFlyingObjects import CogdoFlyingGatherableFactory, CogdoFlyingPlatform, CogdoFlyingLevelFog from CogdoFlyingObstacles import CogdoFlyingObstacleFactory from CogdoGameExit import CogdoGameExit from otp.otpbase import OTPGlobals class CogdoFlyingLevel(DirectObject): notify = directNotify.newCategory('CogdoFlyingLevel') def __init__(self, parent, frameModel, startPlatformModel, endPlatformModel, quadLengthUnits, quadVisibilityAhead, quadVisibiltyBehind): self.parent = parent self.quadLengthUnits = quadLengthUnits self._halfQuadLengthUnits = quadLengthUnits / 2.0 self.quadVisibiltyAhead = quadVisibilityAhead self.quadVisibiltyBehind = quadVisibiltyBehind self._frameModel = frameModel self.root = NodePath('CogdoFlyingLevel') self.quadrantRoot = NodePath('QuadrantsRoot') self.quadrantRoot.reparentTo(self.root) self._startPlatformModel = startPlatformModel self._startPlatformModel.reparentTo(self.root) self._startPlatformModel.setZ(Globals.Level.StartPlatformHeight) self._endPlatformModel = endPlatformModel self._endPlatformModel.reparentTo(self.root) self._endPlatformModel.setZ(Globals.Level.EndPlatformHeight) self.wallR = self._frameModel.find('**/wallR') self.wallL = self._frameModel.find('**/wallL') self._exit = CogdoGameExit() self._exit.reparentTo(self._endPlatformModel) loc = self._endPlatformModel.find('**/exit_loc') offset = loc.getPos(render) self._exit.setPos(render, offset) self.quadrants = [] self.visibleQuadIndices = [] self._numQuads = 0 self._currentQuadNum = -1 self._camera = None self._initCollisions() self.upLimit = self._frameModel.find('**/limit_up').getZ(render) self.downLimit = self._frameModel.find('**/limit_down').getZ(render) self.leftLimit = self._frameModel.find('**/limit_left').getX(render) - 30.0 self.rightLimit = self._frameModel.find('**/limit_right').getX(render) + 30.0 self.backLimit = -self.quadLengthUnits self.forwardLimit = self.quadLengthUnits * 20 self._frameModel.flattenStrong() self.gatherableFactory = CogdoFlyingGatherableFactory() self.obstacleFactory = CogdoFlyingObstacleFactory() return def getExit(self): return self._exit def getBounds(self): return ((self.leftLimit, self.rightLimit), (self.backLimit, self.forwardLimit), (self.downLimit, self.upLimit)) def getGatherable(self, serialNum): for quadrant in self.quadrants: for gatherable in quadrant.gatherables: if gatherable.serialNum == serialNum: return gatherable return None def ready(self): self.gatherableFactory.destroy() del self.gatherableFactory self.obstacleFactory.destroy() del self.obstacleFactory self._initStartEndPlatforms() self._frameModel.reparentTo(self.root) self.root.reparentTo(self.parent) self.root.stash() def _initStartEndPlatforms(self): self.startPlatform = CogdoFlyingPlatform(self._startPlatformModel, Globals.Level.PlatformTypes.StartPlatform) self.endPlatform = CogdoFlyingPlatform(self._endPlatformModel, Globals.Level.PlatformTypes.EndPlatform) self._endPlatformModel.setY(self.convertQuadNumToY(self._numQuads)) self.backLimit = self._startPlatformModel.getY(render) - Globals.Level.StartPlatformLength * 0.7 self.forwardLimit = self._endPlatformModel.getY(render) + Globals.Level.EndPlatformLength * 0.7 def _initCollisions(self): self.collPlane = CollisionPlane(Plane(Vec3(0, 0, 1.0), Point3(0, 0, 10))) self.collPlane.setTangible(0) self.collNode = CollisionNode('fogPlane') self.collNode.setIntoCollideMask(OTPGlobals.FloorBitmask) self.collNode.addSolid(self.collPlane) self.collNodePath = self.root.attachNewNode(self.collNode) self.collNodePath.hide() def destroy(self): del self.collPlane self.collNodePath.removeNode() del self.collNodePath del self.collNode for quadrant in self.quadrants: quadrant.destroy() self._exit.destroy() del self._exit self.root.removeNode() del self.root def onstage(self): self.root.unstash() self.update(0.0) def offstage(self): self.root.stash() def start(self, startTime = 0.0): self._startTime = startTime def stop(self): pass def getLength(self): return self.quadLengthUnits * self.getNumQuadrants() def appendQuadrant(self, model): quadrant = CogdoFlyingLevelQuadrant(self._numQuads, model, self, self.root) if self._numQuads == 0: quadrant.generateGatherables(self._startPlatformModel) quadrant.offstage() self.quadrants.append(quadrant) self._numQuads = len(self.quadrants) def getNumQuadrants(self): return self._numQuads def setCamera(self, camera): self._camera = camera def getCameraActualQuadrant(self): camY = self._camera.getY(render) y = self.root.getY(render) return self.convertYToQuadNum(camY - y) def update(self, dt = 0.0): if self._camera is None: return quadNum = clamp(self.getCameraActualQuadrant(), 0, self._numQuads - 1) if quadNum < self._numQuads: self.quadrants[quadNum].update(dt) if quadNum + 1 < self._numQuads: self.quadrants[quadNum + 1].update(dt) if quadNum != self._currentQuadNum: self._switchToQuadrant(quadNum) return def _switchToQuadrant(self, quadNum): self.visibleQuadIndices = [] if quadNum >= 0: if quadNum > 0: self.quadrants[max(quadNum - self.quadVisibiltyBehind, 0)].onstage() for i in xrange(quadNum, min(quadNum + self.quadVisibiltyAhead + 1, self._numQuads)): self.quadrants[i].onstage() self.visibleQuadIndices.append(i) if i == 0: self.startPlatform.onstage() elif i == self._numQuads - 1: self.endPlatform.onstage() self._currentQuadNum = quadNum for i in range(0, max(self._currentQuadNum - self.quadVisibiltyBehind, 0)) + range(min(self._currentQuadNum + self.quadVisibiltyAhead + 1, self._numQuads), self._numQuads): self.quadrants[i].offstage() if i == 0: self.startPlatform.offstage() elif i == self._numQuads - 1: self.endPlatform.offstage() def convertQuadNumToY(self, quadNum): return quadNum * self.quadLengthUnits def convertYToQuadNum(self, y): return int(y / self.quadLengthUnits) def convertCenterYToQuadNum(self, y): return self.convertYToQuadNum(y + self._halfQuadLengthUnits) class CogdoFlyingLevelFactory: def __init__(self, parent, quadLengthUnits, quadVisibilityAhead, quadVisibiltyBehind, rng = None): self.parent = parent self.quadLengthUnits = quadLengthUnits self.quadVisibiltyAhead = quadVisibilityAhead self.quadVisibiltyBehind = quadVisibiltyBehind self._rng = rng or RandomNumGen(1) self.isOrg = self._rng.randint(0, 1) self._level = None return def loadAndBuildLevel(self, safezoneId): levelNode = NodePath('level') frameModel = CogdoUtil.loadFlyingModel('level') startPlatformModel = CogdoUtil.loadFlyingModel('levelStart') ver = '_org' if self.isOrg else '' endPlatformModel = CogdoUtil.loadFlyingModel('levelEnd%s' % ver) for fan in frameModel.findAllMatches('**/*wallFan'): fan.flattenStrong() frameModel.find('**/fogOpaque').setBin('background', 1) frameModel.find('**/ceiling').setBin('background', 2) frameModel.find('**/fogTranslucent_bm').setBin('fixed', 1) frameModel.find('**/wallR').setBin('opaque', 2) frameModel.find('**/wallL').setBin('opaque', 2) frameModel.find('**/fogTranslucent_top').setBin('fixed', 2) frameModel.getChildren().reparentTo(levelNode) if not self.isOrg: levelNode.hide() self._level = CogdoFlyingLevel(self.parent, levelNode, startPlatformModel, endPlatformModel, self.quadLengthUnits, self.quadVisibiltyAhead, self.quadVisibiltyBehind) if Globals.Dev.WantTempLevel: quads = Globals.Dev.DevQuadsOrder else: levelInfo = Globals.Level.DifficultyOrder[safezoneId] quads = [] for difficulty in levelInfo: quadList = Globals.Level.QuadsByDifficulty[difficulty] quads.append(quadList[self._rng.randint(0, len(quadList) - 1)]) for i in quads: ver = '_org' if self.isOrg else '' filePath = CogdoUtil.getModelPath('quadrant%i%s' % (i, ver), 'flying') quadModel = loader.loadModel(filePath) for np in quadModel.findAllMatches('**/*lightCone*'): CogdoUtil.initializeLightCone(np, 'fixed', 3) self._level.appendQuadrant(quadModel) self._level.ready() def createLevel(self, safezoneId = 2000): if self._level is None: self.loadAndBuildLevel(safezoneId) return self._level def createLevelFog(self): if self._level is None: self.loadAndBuildLevel() if self.isOrg: return CogdoFlyingLevelFog(self._level, (0,0,0,1)) else: return CogdoFlyingLevelFog(self._level)