class Line(DirectObject): """ For drawing a line when picking target for attack """ def __init__(self): self.meshDrawer = MeshDrawer() self.meshDrawer.setBudget(2) mdNode = self.meshDrawer.getRoot() mdNode.reparentTo(base.render) mdNode.setDepthWrite(False) mdNode.setTransparency(True) mdNode.setTwoSided(True) # mdNode.setTexture(loader.loadTexture("pixel.png")) mdNode.setBin("fixed", 0) mdNode.setLightOff(True) def draw(self, start, end): self.meshDrawer.begin(base.cam, render) self.meshDrawer.segment( Vec3(*start), Vec3(*end), frame=Vec4(0, 0, 1, 1), # Use entire texture thickness=0.1, color=Vec4(0, 0, 0, 255)) self.meshDrawer.end() def clear(self): self.meshDrawer.begin(base.cam, render) self.meshDrawer.end()
class Panda3dViewer(BaseViewer, ShowBase): def __init__(self, params=None, **kwargs): # Load 3d-Model and parameter super(Panda3dViewer, self).__init__(params=params) self.world_x_range = kwargs.pop("x_range", [-40, 40]) self.world_y_range = kwargs.pop("y_range", [-40, 40]) self.follow_agent_id = kwargs.pop("follow_agent_id", -1) self.screen_dims = kwargs.pop("screen_dims", [1024, 1024]) self.path = os.path.join(os.path.dirname(os.path.abspath(__file__))) # TODO(@fortiss): load into parameter at a earlier stage self.agent_model_path = kwargs.pop("model_path", self.path + "/models/box_car") self.agent_scale = kwargs.pop("model_scale", np.array([3.65, 1.8, 0.8], dtype=float)) self.agent_orientation = \ kwargs.pop("model_orientation",np.array([180, 0,0], dtype=float)) self.agent_translation = kwargs.pop("model_translation", np.array([3.2, 0.9], dtype=float)) self.range_for_zoom = kwargs.pop("is_zoom_range", False) self.line_thicknesses = kwargs.pop("line_thickness", { #Dict of keys cameras and values [line thickness, height] which are needed to calculate the dynamic thickness -2: [0.35, 700], -1: [0.35, 700], 0: [0.1, 70] }) # Parameter for agent camera views # [driving direction offset, height, x-orientation,y-orientation,z-orientation offset to driving direction, LookAt?] self.agent_cam_parameter = kwargs.pop( "agent_view", { "bird_agent": [0, 70, 0, 270, 270, False], "third": [-35, 15, 0, 0, 0, True], "first": [1.2, 2.7, 180, 190, 90, False] }) # Set Window Size self.wp = WindowProperties().getDefault() self.wp.setSize(self.screen_dims[0], self.screen_dims[1]) self.wp.setTitle("BARK Panda3d Viewer") WindowProperties.setDefault(self.wp) ShowBase.__init__(self) # Render Objects Dict self.agent_nodes = {} # Agent Poses Dict self.agent_poses = {} self.setLight() # Creating a plane as floor #TODO parameter from map parameter frame = [ -self.screen_dims[0] / 2, self.screen_dims[0] / 2, -self.screen_dims[1] / 2, self.screen_dims[1] / 2 ] color = VBase4(self.plane_color[0], self.plane_color[1], self.plane_color[2], self.plane_alpha) self.createPlane(frame=frame, color=color) # Set up the camera loop task self.camera_list = [-1] self.initCam() self.taskMgr.add(self.spinCameraTask, "SpinCameraTask") # Set up the line generator self.setDrawer(budget=100000) # -2 : global camera with camera control, -1: transition state for enabling mouse control, 0: agent cameras self.perspectives = { -2: ["birdview", "autozoom"], -1: ["None"], 0: ["bird_agent", "third", "first"] } self.perspective = self.perspectives[self.camIndex( self.follow_agent_id)] self.line_thickness = self.line_thicknesses[self.camIndex( self.follow_agent_id)][0] self.addButtons() def setDrawer(self, budget=100000): """Initializes the MeshDrawer() generator to draw lines in Panda3d Keyword Arguments: budget {int} -- maximum triangles for rendering the mesh (default: {100000}) """ self.generator = MeshDrawer() self.generator.setBudget(budget) self.generatorNode = self.generator.getRoot() self.generatorNode.reparentTo(self.render) def createPlane(self, frame=None, color=VBase4(1, 1, 1, 1)): """ Creates a Plane/Card with the Panda3d Cardmaker() class Keyword Arguments: frame {list} -- The coordinates [x1,y1,x2,y2] of the planes/cards edges (default: {[-1, -1, 1, 1]}) color {VBase4} -- The color of the planes/cards (default: {VBase4(1, 1, 1, 1)}) """ frame = frame or [-1, -1, 1, 1] card = CardMaker("plane") card.set_color(color) card.set_frame(frame[0], frame[1], frame[2], frame[3]) n = NodePath() self.plane = n.attach_new_node(card.generate()) self.plane.reparentTo(self.render) self.plane.setHpr(0, 270, 0) def setLight(self, color=VBase4(1, 1, 1, 1)): """Sets an ambient and omnidirectional light for rendering Keyword Arguments: color {VBase4} -- color of the ambient light (default: {VBase4(1, 1, 1, 1)}) """ alight = AmbientLight('alight') alight.setColor(color) alnp = self.render.attachNewNode(alight) self.render.setLight(alnp) def addButtons(self): self.cam_btn = DirectButton( text="Camera", scale=0.05, command=self.switchCamera, pos=Vec3(0.9, 0, 0.9)) self.per_btn = DirectButton( text="View", scale=0.05, command=self.switchView, pos=Vec3(0.9, 0, 0.85)) def camIndex(self,follow_id): return np.minimum(follow_id, 0) def switchCamera(self): # Switches between global and agent cameras self.follow_agent_id = self.camera_list.pop(0) self.camera_list.append(self.follow_agent_id) self.perspective = self.perspectives[self.camIndex( self.follow_agent_id)].copy() self.line_thickness = self.line_thicknesses[self.camIndex( self.follow_agent_id)][0] def switchView(self): # Switches between the perspectives defined by the camera self.perspective.append(self.perspective[0]) self.perspective.pop(0) def updateCamera(self, lookAt=False): """Updates the camera position from calls using variables self.cam_pose and self.cam_or Keyword Arguments: lookAt {bool} -- If true the orientation is calculated by the agents position (default: {False}) """ self.camera.setPos(self.cam_pose[0], self.cam_pose[1], self.cam_pose[2]) if lookAt: self.camera.lookAt(self.agent_nodes[self.follow_agent_id]) else: self.camera.setHpr(self.cam_or[2], self.cam_or[1], self.cam_or[0]) def spinCameraTask(self, task): """This function sets and updates the camera according to environment variables and parameters Arguments: task {task} -- Panda3d Task Returns: Task.cont -- Panda3d Task Return """ if self.follow_agent_id is -1: # Transition into camera control view self.setMouseControl() if self.follow_agent_id is -2: # Global Camera if (self.perspective[0] is self.perspectives[-2][1]): self.setAutoZoomCam(self.agent_poses) if self.follow_agent_id >= 0: # Camera for all agents self.setAgentCam(self.perspective[0], self.agent_poses[self.follow_agent_id]) return Task.cont def initCam(self, poses=None, orientation=None):#TODO Calculate from map parameter before poses = poses or [0, 0, 700] orientation = orientation or [0, 270, 0] self.cam_pose = np.array(poses, dtype=float) self.cam_or = np.array(orientation, dtype=float) def setMouseControl(self): # Enables Panda3d Standard Mouse Control # Right mouse button: zoom, left mouse Button: move, middle mouse button: tilt self.initCam() self.updateCamera(lookAt=False) self.mat = Mat4(self.camera.getMat()) self.mat.invertInPlace() base.mouseInterfaceNode.setMat(self.mat) base.enableMouse() self.follow_agent_id = -2 self.perspective = self.perspectives[self.camIndex( self.follow_agent_id)].copy() def setAutoZoomCam(self, agent_poses): """This function calculates the camera position so that all agents are visible Arguments: agent_poses {[dict]} -- [look up table of all agent poses] """ points = np.array([[]], dtype=float) if ((self.world_x_range is not None) and (self.world_y_range is not None) and self.range_for_zoom): points = np.array([[self.world_x_range[0], self.world_y_range[0]], [self.world_x_range[1], self.world_y_range[1]]]) # Build concat matrix of all positions for _, agent in agent_poses.items(): if points.size is 0: points = np.array([[agent[0], agent[1]]], dtype=float) else: points = np.append(points, [[agent[0], agent[1]]], axis=0) # Calculate maximum distance between min,max of x or y poses max_dist = np.max(np.max(points, axis=0) - np.min(points, axis=0)) # Calculate mean positions as center for camera center = (np.max(points, axis=0) + np.min(points, axis=0)) / 2 # Lower bound for vieweable area max_dist = np.maximum(max_dist * 1.25, 40) # Calculate camera height zoom = max_dist * np.tan(pi * (60 / 180)) self.cam_pose = np.array([center[0], center[1], zoom], dtype=float) self.cam_or = np.array([0, 270, 0], dtype=float) self.updateCamera(lookAt=False) def setAgentCam(self, perspective, agent_poses): """Sets up the class variable for the camerea position and orientation Arguments: perspective {list} -- List of strings describing the perspective currently ["bird_agent","third","first"] which is used as an index for the parameters dict agent_poses {np.array([x,y,theta])} -- Describes the agent position """ base.disableMouse() self.cam_pose[0] = agent_poses[0] + self.agent_cam_parameter[ perspective][0] * np.cos(agent_poses[2]) self.cam_pose[1] = agent_poses[1] + self.agent_cam_parameter[ perspective][0] * np.sin(agent_poses[2]) self.cam_pose[2] = self.agent_cam_parameter[perspective][1] self.cam_or = np.array([ self.agent_cam_parameter[perspective][2], self.agent_cam_parameter[perspective][3], (agent_poses[2] * 180) / pi + self.agent_cam_parameter[perspective][4] ], dtype=float) self.updateCamera(lookAt=self.agent_cam_parameter[perspective][5]) def calcLineThickness(self,cameras=None): """Uses a linear approximation between two cameras to calculate the line thickness Arguments: cameras {int array} -- Sets the indices of the target cameras Returns: [float] -- [The approximated thickness] """ cameras = cameras or [-1,0] incline = (self.line_thicknesses[cameras[0]][0] - self.line_thicknesses[cameras[1]][0]) / (self.line_thicknesses[cameras[0]][1]-self.line_thicknesses[cameras[1]][1]) return np.maximum((self.line_thicknesses[cameras[1]][0] + incline * (self.camera.getZ() - self.line_thicknesses[cameras[1]][1]) ), 0.01) def drawPolygon2d(self, polygon, color, alpha): # Draws a polygon with drawLine2d points = polygon.toArray() self.line_thickness = self.calcLineThickness() for point in points: self.generator.link_segment( Vec3(point[0], point[1], 2), Vec4(0, 0, 1, 1), self.line_thickness, self.getColor(color)) self.generator.link_segment_end(Vec4(0, 0, 1, 1), self.getColor(color)) def drawLine2d(self, line2d, color=Viewer.Color.Blue, alpha=1.0): line2d_np = line2d.toArray() for point in line2d_np: self.generator.link_segment( Vec3(point[0], point[1], 2), Vec4(0, 0, 1, 1), self.line_thickness, self.getColor(color)) self.generator.link_segment_end(Vec4(0, 0, 1, 1), self.getColor(color)) def drawAgent(self, agent): """Draws an agent object with a model previosly set in set with self.agent_model_path Arguments: agent -- Agent object from world """ # Adds new agent to dict of Panda3d nodes if not agent.id in self.agent_nodes: self.agent_nodes[agent.id] = self.loader.loadModel( self.agent_model_path) self.agent_nodes[agent.id].reparentTo(self.render) self.agent_nodes[agent.id].setPos(0, 0, 2) self.agent_nodes[agent.id].setScale( self.agent_scale[0], self.agent_scale[1], self.agent_scale[2]) self.agent_poses[agent.id] = np.array([0, 0, 0], dtype=float) self.camera_list.insert(len(self.camera_list), agent.id) # Set new pose of agent in world cordinates state = agent.followed_trajectory[-1, :] self.agent_poses[agent.id][0] = state[int(StateDefinition.X_POSITION)] self.agent_poses[agent.id][1] = state[int(StateDefinition.Y_POSITION)] self.agent_poses[agent.id][2] = state[int( StateDefinition.THETA_POSITION)] transformed_polygon = agent.shape.transform(self.agent_poses[agent.id]) self.drawPolygon2d(transformed_polygon, self.color_agents, 1.0) # Fitting of 3d-Model frame to agent positon angle = ((self.agent_poses[agent.id][2] * 180) / pi + self.agent_orientation[0]) self.agent_nodes[agent.id].setHpr(angle, self.agent_orientation[1], self.agent_orientation[2]) translation = self.agent_translation if not np.all(translation == 0): r = np.array([[ np.cos(self.agent_poses[agent.id][2]), np.sin(self.agent_poses[agent.id][2]) ], [ np.cos(self.agent_poses[agent.id][2] + pi * 0.5), np.sin(self.agent_poses[agent.id][2] + pi * 0.5) ]], dtype=float) translation = np.dot(translation, r) self.agent_nodes[agent.id].setPos( self.agent_poses[agent.id][0] + translation[0], self.agent_poses[agent.id][1] + translation[1], 2) if self.draw_route: self.drawRoute(agent) def getColor(self, color): if isinstance(color, Viewer.Color): return { Viewer.Color.White: Vec4(1, 1, 1, 1), Viewer.Color.Red: Vec4(1, 0, 0, 1), Viewer.Color.Blue: Vec4(0, 0, 1, 1), Viewer.Color.Magenta: Vec4(100.0 / 255.0, 1, 100.0 / 255.0, 1), Viewer.Color.Brown: Vec4(150.0 / 255.0, 50.0 / 255.0, 50.0 / 255.0, 1), Viewer.Color.Black: Vec4(0, 0, 0, 1) }.get(color, Vec4(0, 0, 0, 1)) else: return Vec4(color[0], color[1], color[2], 1) def drawWorld(self, world): self.generator.begin(base.cam, self.render) super(Panda3dViewer, self).drawWorld(world) self.generator.end() self.taskMgr.step()
class Player(GameObject, ArmedObject): def __init__(self, shipSpec): GameObject.__init__(self, Vec3(0, 0, 0), None, None, shipSpec.maxShields, shipSpec.maxSpeed, "player", MASK_INTO_PLAYER, 2) ArmedObject.__init__(self) self.acceleration = shipSpec.acceleration self.turnRate = shipSpec.turnRate self.numGuns = len(shipSpec.gunPositions) self.numMissiles = shipSpec.numMissiles self.maxEnergy = shipSpec.maxEnergy self.energyRechargeRate = shipSpec.energyRechargeRate self.shieldRechargeRate = shipSpec.shieldRechargeRate self.energy = shipSpec.maxEnergy for gunPos in shipSpec.gunPositions: np = self.actor.attachNewNode(PandaNode("gun node")) np.setPos(gunPos) gun = BlasterWeapon() self.addWeapon(gun, 0, np) missileSetCounter = 1 for missilePos in shipSpec.missilePositions: np = self.actor.attachNewNode(PandaNode("missile node")) np.setPos(missilePos) gun = RocketWeapon() self.addWeapon(gun, missileSetCounter, np) missileSetCounter += 1 self.numMissileSets = missileSetCounter - 1 self.missileSetIndex = 0 light = PointLight("basic light") light.setColor(Vec4(1, 1, 1, 1)) light.setAttenuation((1, 0.01, 0.001)) self.lightNP = self.root.attachNewNode(light) self.lightNP.setZ(1) Common.framework.showBase.render.setLight(self.lightNP) self.colliderNP.node().setFromCollideMask(MASK_WALLS | MASK_FROM_PLAYER) Common.framework.pusher.addCollider(self.colliderNP, self.root) Common.framework.traverser.addCollider(self.colliderNP, Common.framework.pusher) Common.framework.showBase.camera.reparentTo(self.actor) Common.framework.showBase.camera.setPos(0, 0, 0) Common.framework.showBase.camera.setHpr(0, 0, 0) lens = Common.framework.showBase.camLens lens.setNear(0.03) ratio = lens.getAspectRatio() lens.setFov(75 * ratio) self.lastMousePos = Vec2(0, 0) self.mouseSpeedHori = 50.0 self.mouseSpeedVert = 30.0 self.mouseSensitivity = 1.0 self.targetingRay = CollisionSegment(0, 0, 0, 0, 100, 0) self.targetingRayNode = CollisionNode("lock ray") self.targetingRayNode.addSolid(self.targetingRay) self.targetingRayNode.setFromCollideMask(MASK_ENEMY_LOCK_SPHERE) self.targetingRayNode.setIntoCollideMask(0) self.targetingRayNP = self.actor.attachNewNode(self.targetingRayNode) self.targetingQueue = CollisionHandlerQueue() self.prospectiveLockTarget = None self.lockTargetTimer = 0 self.lockDuration = 1 Common.framework.traverser.addCollider(self.targetingRayNP, self.targetingQueue) #rayNodePath.show() self.uiRoot = aspect2d.attachNewNode(PandaNode("player UI")) cardMaker = CardMaker("UI maker") cardMaker.setFrame(-1, 1, -1, 1) self.centreSpot = self.uiRoot.attachNewNode(cardMaker.generate()) self.centreSpot.setTexture( Common.framework.showBase.loader.loadTexture( "../Section2SpaceflightDocking/UI/spot.png")) self.centreSpot.setTransparency(True) self.centreSpot.setPos(0, 0, 0) self.centreSpot.setScale(0.01) self.centreSpot.setAlphaScale(0.5) self.directionIndicator = self.uiRoot.attachNewNode( cardMaker.generate()) self.directionIndicator.setTexture( Common.framework.showBase.loader.loadTexture( "../Section2SpaceflightDocking/UI/directionIndicator.png")) self.directionIndicator.setTransparency(True) self.directionIndicator.setScale(0.05) self.directionIndicator.hide() self.lockMarkerRoot = self.uiRoot.attachNewNode( PandaNode("lock marker root")) for i in range(4): markerRotationNP = self.lockMarkerRoot.attachNewNode( PandaNode("lock marker rotation")) marker = markerRotationNP.attachNewNode(cardMaker.generate()) marker.setTexture( Common.framework.showBase.loader.loadTexture( "../Section2SpaceflightDocking/UI/lockMarker.png")) marker.setTransparency(True) markerRotationNP.setScale(0.04) markerRotationNP.setR(i * 90) self.lockMarkerRoot.hide() self.lockBar = Common.framework.showBase.loader.loadModel( "../Section2SpaceflightDocking/UI/uiLockBar") self.lockBar.reparentTo(self.uiRoot) self.lockBar.setScale(0.15) #self.lockBar.hide() cardMaker.setFrame(-1, 1, 0, 1) self.cockpit = Common.framework.showBase.loader.loadModel( "../Section2SpaceflightDocking/Models/{0}".format( shipSpec.cockpitModelFile)) self.cockpit.reparentTo(self.actor) healthBarRoot = self.cockpit.find("**/healthBar") if healthBarRoot is None or healthBarRoot.isEmpty(): healthBarRoot = self.uiRoot.attachNewNode( PandaNode("health bar root")) print("No health bar root found!") energyBarRoot = self.cockpit.find("**/energyBar") if energyBarRoot is None or energyBarRoot.isEmpty(): energyBarRoot = self.uiRoot.attachNewNode( PandaNode("energy bar root")) print("No energy bar root found!") missileCounterRoot = self.cockpit.find("**/missileCounter") if missileCounterRoot is None or missileCounterRoot.isEmpty(): missileCounterRoot = self.uiRoot.attachNewNode( PandaNode("missile counter root")) print("No missile counter root found!") radarRoot = self.cockpit.find("**/radar") if radarRoot is None or radarRoot.isEmpty(): radarRoot = self.uiRoot.attachNewNode(PandaNode("radar root")) print("No radar root found!") speedometerRoot = self.cockpit.find("**/speedometer") if speedometerRoot is None or speedometerRoot.isEmpty(): speedometerRoot = self.uiRoot.attachNewNode( PandaNode("speedometer root")) print("No speedometer root found!") self.radarDrawer = MeshDrawer() self.radarDrawer.setBudget(4096) self.radarDrawerNP = self.radarDrawer.getRoot() self.radarDrawerNP.reparentTo(radarRoot) self.radarDrawerNP.setTwoSided(True) self.radarDrawerNP.setLightOff() self.radarDrawerNP.setDepthWrite(False) self.radarDrawerNP.setTransparency(True) self.healthBar = healthBarRoot.attachNewNode(cardMaker.generate()) self.healthBar.setSx(0.05) self.energyBar = energyBarRoot.attachNewNode(cardMaker.generate()) self.energyBar.setSx(0.05) self.healthBarScalar = 0.00175 self.energyBarScalar = 0.00175 self.missileCounter = DirectLabel(text="", text_mayChange=True, scale=0.09, relief=None, parent=missileCounterRoot) self.maxRadarRange = 700 self.radarSize = 0.3 self.speedometer = DirectLabel(text="", text_mayChange=True, scale=0.09, relief=None, parent=speedometerRoot) self.updateHealthUI() self.updateEnergyUI() self.updateMissileUI() self.updateRadar() self.updateSpeedometer() self.updatingEffects = [] def update(self, keys, dt): GameObject.update(self, dt) self.updateSpeedometer() self.walking = False quat = self.root.getQuat(Common.framework.showBase.render) forward = quat.getForward() right = quat.getRight() up = quat.getUp() if keys["up"]: self.walking = True self.velocity += forward * self.acceleration * dt if keys["down"]: self.walking = True self.velocity -= forward * self.acceleration * dt if keys["left"]: self.walking = True self.velocity -= right * self.acceleration * dt if keys["right"]: self.walking = True self.velocity += right * self.acceleration * dt if self.walking: self.inControl = True mouseWatcher = base.mouseWatcherNode if mouseWatcher.hasMouse(): xSize = base.win.getXSize() ySize = base.win.getYSize() xPix = float(xSize % 2) / xSize yPix = float(ySize % 2) / ySize mousePos = Vec2(base.mouseWatcherNode.getMouse()) mousePos.addX(-xPix) mousePos.addY(-yPix) if abs(mousePos.x) < xPix: mousePos.x = 0 if abs(mousePos.y) < yPix: mousePos.y = 0 else: mousePos = self.lastMousePos if mousePos.length() > 0.01: axis = right * (mousePos.y) + up * (-mousePos.x) axis.normalize() angle = mousePos.length() * self.turnRate * dt rotQuat = Quat() rotQuat.setFromAxisAngle(angle, axis) self.root.setQuat(quat * rotQuat) if not self.weaponSets[0][0].active: self.alterEnergy( math.sin(1.071 * self.energy / self.maxEnergy + 0.5) * self.energyRechargeRate * dt) self.updateEnergyUI() self.updateHealthUI() self.updateRadar() #self.root.setH(self.root.getH() - mousePos.x*self.mouseSpeedHori*self.mouseSensitivity) #self.actor.setP(self.actor.getP() + mousePos.y*self.mouseSpeedVert*self.mouseSensitivity) if keys["shoot"]: self.startFiringSet(0) else: self.ceaseFiringSet(0) if keys["shootSecondary"]: self.startFiringSet(self.missileSetIndex + 1) else: for i in range(self.numMissileSets): self.ceaseFiringSet(i + 1) [effect.update(self, dt) for effect in self.updatingEffects] [ effect.cleanup() for effect in self.updatingEffects if not effect.active ] self.updatingEffects = [ effect for effect in self.updatingEffects if effect.active ] if self.targetingQueue.getNumEntries() > 0: self.targetingQueue.sortEntries() entry = self.targetingQueue.getEntry(0) intoNP = entry.getIntoNodePath() if intoNP.hasPythonTag(TAG_OWNER): other = intoNP.getPythonTag(TAG_OWNER) if other is self.prospectiveLockTarget and other is not self.lockedTarget: self.lockTargetTimer += dt if self.lockTargetTimer >= self.lockDuration: self.lockedTarget = other else: self.lockTargetTimer = 0 self.prospectiveLockTarget = other else: self.lockTargetTimer = 0 else: self.lockTargetTimer = 0 perc = self.lockTargetTimer / self.lockDuration self.lockBar.setTexOffset(TextureStage.getDefault(), 0, -perc * 1.1) if self.lockedTarget is not None: if self.lockedTarget.health <= 0: self.lockedTarget = None else: relPos = self.lockedTarget.root.getPos(self.root) planarVec = relPos.getXz() relDist = relPos.length() if relDist == 0: angle = 0 else: angle = math.acos(relPos.y / relDist) if relDist > 200 or angle > 1.7453: self.lockedTarget = None else: if self.lockMarkerRoot.isHidden(): self.lockMarkerRoot.show() camPt = Point2() convertedPt = Common.framework.showBase.cam.getRelativePoint( Common.framework.showBase.render, self.lockedTarget.root.getPos( Common.framework.showBase.render)) if Common.framework.showBase.camLens.project( convertedPt, camPt): self.lockMarkerRoot.setPos( Common.framework.showBase.render2d, camPt.x, 0, camPt.y) if self.lockMarkerRoot.isHidden(): self.lockMarkerRoot.show() for child in self.lockMarkerRoot.getChildren(): child.getChild(0).setZ( (1.0 - min(1, relDist / 100)) * 5 + 0.2) elif not self.lockMarkerRoot.isHidden(): self.lockMarkerRoot.hide() if relPos.y < 0 or angle > 0.6: planarVec.normalize() self.directionIndicator.setPos(planarVec.x * 0.4, 0, planarVec.y * 0.4) angle = math.degrees( math.atan2(planarVec.x, planarVec.y)) self.directionIndicator.setR(angle) if self.directionIndicator.isHidden(): self.directionIndicator.show() elif not self.directionIndicator.isHidden(): self.directionIndicator.hide() else: if not self.directionIndicator.isHidden(): self.directionIndicator.hide() if not self.lockMarkerRoot.isHidden(): self.lockMarkerRoot.hide() def weaponReset(self, weapon): ArmedObject.weaponFired(self, weapon) if isinstance(weapon, RocketWeapon): self.ceaseFiringSet(self.missileSetIndex + 1) self.missileSetIndex += 1 if self.missileSetIndex >= self.numMissileSets: self.missileSetIndex = 0 def attackPerformed(self, weapon): ArmedObject.attackPerformed(self, weapon) def postTraversalUpdate(self, dt): ArmedObject.update(self, dt) def alterHealth(self, dHealth, incomingImpulse, knockback, flinchValue, overcharge=False): GameObject.alterHealth(self, dHealth, incomingImpulse, knockback, flinchValue, overcharge) self.updateHealthUI() #self.hurtSound.play() def alterEnergy(self, dEnergy): self.energy += dEnergy if self.energy < 0: self.energy = 0 elif self.energy > self.maxEnergy: self.energy = self.maxEnergy def alterMissileCount(self, dMissiles): self.numMissiles += dMissiles if self.numMissiles < 0: self.numMissiles = 0 self.updateMissileUI() def updateHealthUI(self): perc = self.health / self.maxHealth newVal = max(0.01, self.health * self.healthBarScalar) self.healthBar.setSz(newVal) self.healthBar.setColorScale(1.0 - (perc - 0.5) / 0.5, min(1, perc / 0.5), 0, 1) #self.healthCounter.setText("{0:-.0f}".format(self.health)) #self.healthCounter.setColorScale(1.0 - (perc - 0.5)/0.5, min(1, perc/0.5), 0, 1) def updateEnergyUI(self): perc = self.energy / self.maxEnergy newVal = max(0.01, self.energy * self.energyBarScalar) self.energyBar.setSz(newVal) self.energyBar.setColorScale(1.0 - (perc - 0.5) / 0.5, min(1, perc / 0.5), 0, 1) def updateMissileUI(self): self.missileCounter["text"] = "Missiles:\n{0}".format(self.numMissiles) self.missileCounter.setText() self.missileCounter.resetFrameSize() def updateSpeedometer(self): self.speedometer["text"] = "Speed:\n{0:0=2.0f}m/s".format( self.velocity.length() * 2) self.speedometer.setText() self.speedometer.resetFrameSize() def updateRadar(self): if Common.framework.currentLevel is not None: self.radarDrawer.begin(Common.framework.showBase.cam, Common.framework.showBase.render) uvs = Vec2(0, 0) spotSize = 0.015 self.radarDrawer.tri(Vec3(-spotSize, 0, -spotSize), Vec4(0, 1, 0, 1), uvs, Vec3(spotSize, 0, -spotSize), Vec4(0, 1, 0, 1), uvs, Vec3(-spotSize, 0, spotSize), Vec4(0, 1, 0, 1), uvs) self.radarDrawer.tri(Vec3(-spotSize, 0, spotSize), Vec4(0, 1, 0, 1), uvs, Vec3(spotSize, 0, -spotSize), Vec4(0, 1, 0, 1), uvs, Vec3(spotSize, 0, spotSize), Vec4(0, 1, 0, 1), uvs) selfForward = Vec3(0, 1, 0) for enemy in Common.framework.currentLevel.enemies: enemyPos = enemy.root.getPos(self.root) dist = enemyPos.length() if dist < self.maxRadarRange: distPerc = dist / self.maxRadarRange enemyPos.normalize() anglePerc = selfForward.angleDeg(enemyPos) / 180 enemyPos.setY(0) enemyPos.normalize() enemyPos *= anglePerc * self.radarSize colour = Vec4(1, 0, 0, math.sin(max(0, 1 - distPerc) * 1.571)) self.radarDrawer.tri( Vec3(-spotSize, 0, 0) + enemyPos, colour, uvs, Vec3(spotSize, 0, 0) + enemyPos, colour, uvs, Vec3(0, 0, spotSize) + enemyPos, colour, uvs) self.radarDrawer.tri( Vec3(spotSize, 0, 0) + enemyPos, colour, uvs, Vec3(-spotSize, 0, 0) + enemyPos, colour, uvs, Vec3(0, 0, -spotSize) + enemyPos, colour, uvs) self.radarDrawer.end() def addUpdatingEffect(self, effect): self.updatingEffects.append(effect) effect.start(self) def cleanup(self): if self.uiRoot is not None: self.uiRoot.removeNode() self.uiRoot = None self.healthBar = None if self.lightNP is not None: Common.framework.showBase.render.clearLight(self.lightNP) self.lightNP.removeNode() self.lightNP = None for effect in self.updatingEffects: effect.cleanup() self.updatingEffects = [] ArmedObject.cleanup(self) GameObject.cleanup(self)