class Preloader(): def __init__(self): self.progressBar = DirectWaitBar(text = "", value = 0, pos = (0,0,0), scale = 0.5, barColor = (1,0.3,0,1)) self.textObject = OnscreenText(text = "", pos = (0.0,-0.15), scale = 0.1,fg=(0,0,0,1),align=TextNode.ACenter,mayChange=1) f = open('models_2.txt', 'r') self.models = f.readlines() f.close() for N in range(len(self.models)): self.models[N] = self.models[N].replace("\n", "") self.totalItems = len(self.models) base.graphicsEngine.renderFrame() base.graphicsEngine.renderFrame() self.itemCount = 0 for M in self.models: print(M) item = loader.loadModel(M) progress = 100 / float(self.totalItems) self.progressBar['value'] += progress #text = str(self.progressBar['value'])+'%' self.textObject.setText("Loading") #self.loaderBar.setTexOffset(self.modTS, -progress + 0.15,0) base.graphicsEngine.renderFrame() base.graphicsEngine.renderFrame() self.textObject.destroy() self.progressBar.destroy()
class TeamSelectMenu(Menu): def __init__(self): Menu.__init__(self) self.LoadContent() self.accept(ListOfConnectedPlayersReceivedEvent.EventName, self.OnListOfConnectedPlayersReceivedEvent) def LoadContent(self): self.text = OnscreenText(text = 'A - Team 1 (?)\nS - Team 2 (?)\nD - Spectate (?)', pos = (0, -0.5), scale = 0.07, fg = (1, 1, 1, 1)) self.text.reparentTo(self.node) def OnTeamSelect(self, team): Globals.MY_TEAM = team TeamSelectEvent(team).Fire() def OnListOfConnectedPlayersReceivedEvent(self, event): team1 = 0 team2 = 0 spectators = 0 for pState in event.GetPlayerStates(): if(pState.GetValue(PlayerState.TEAM) == Game.TEAM_1): team1 += 1 elif(pState.GetValue(PlayerState.TEAM) == Game.TEAM_2): team2 += 1 elif(pState.GetValue(PlayerState.TEAM) == Game.SPECTATE): spectators += 1 self.text.setText('A - Team 1 (%s)\nS - Team 2 (%s)\nD - Spectate (%s)' % (team1, team2, spectators))
class GameHUD: def __init__(self): #Creates the HUD elements. self.stabilityBar = OnscreenImage(image = "../images/100.png", pos = (1.2, 0, .1)) self.stabilityBar.setScale(.05,1,.65) self.stabilityBar.setTransparency(TransparencyAttrib.MAlpha) self.actionCommand = OnscreenImage(image = '../images/open.png', pos = (.95, 0, -.75), scale = (0.33, 1, 0.2)) self.actionCommand.setTransparency(TransparencyAttrib.MAlpha) self.score = OnscreenText(text = 'Score: 0', align = TextNode.ALeft, pos = (-1.3, -.9), scale = 0.10, fg = (1,1,1,1), mayChange = True) self.score.align = TextNode.ALeft self.score.setText('Depth: 0') #self.score.setScale(.2,.2,.2) def updateHud(self, NewStability, NewScore, NewActionCommand): #Updates the HUD using the inputted values. self.score.setText('Depth: ' + str(NewScore)) if NewStability >= 100: self.stabilityBar.setImage('../images/100.png') elif NewStability >= 90: self.stabilityBar.setImage('../images/90.png') elif NewStability >= 80: self.stabilityBar.setImage('../images/80.png') elif NewStability >= 70: self.stabilityBar.setImage('../images/70.png') elif NewStability >= 60: self.stabilityBar.setImage('../images/60.png') elif NewStability >= 50: self.stabilityBar.setImage('../images/50.png') elif NewStability >= 40: self.stabilityBar.setImage('../images/40.png') elif NewStability >= 30: self.stabilityBar.setImage('../images/30.png') elif NewStability >= 20: self.stabilityBar.setImage('../images/20.png') elif NewStability >= 10: self.stabilityBar.setImage('../images/10.png') elif NewStability >= 0: self.stabilityBar.setImage('../images/0.png') if NewActionCommand == []: self.actionCommand.setImage('../images/open.png') elif NewActionCommand == ['l','d']: self.actionCommand.setImage('../images/left_down.png') elif NewActionCommand == ['r','d']: self.actionCommand.setImage('../images/right_down.png') elif NewActionCommand == ['l','u']: self.actionCommand.setImage('../images/left_up.png') elif NewActionCommand == ['r','u']: self.actionCommand.setImage('../images/right_up.png') elif NewActionCommand == ['u','d']: self.actionCommand.setImage('../images/up_down.png') elif NewActionCommand == ['l','r']: self.actionCommand.setImage('../images/left_right.png') self.actionCommand.setTransparency(TransparencyAttrib.MAlpha)
class LoadingScreen: def __init__(self, main): self.main = main self.imageObject = OnscreenImage(image = 'IMAGES/loading.jpg', pos = (0, 0, 0)) self.imageObject.reparentTo(render2d) #base.graphicsEngine.renderFrame() base.graphicsEngine.renderFrame() def finish(self): self.imageObject.destroy() self.countDownText = OnscreenText(text=str(countDownStart), style=1, fg=(1,1,1,1), pos=(0.01, 0.1), align = TextNode.ACenter, scale = .2, mayChange = 1) taskMgr.add(self.countDown,"countDownTask") def countDown(self,task): timeLeft = "%01d" % (countDownStart - task.time) if (countDownStart - task.time) > 1: self.countDownText.setText(timeLeft) return task.cont elif 1 > (countDownStart - task.time) > 0: self.countDownText.setText("GO!") return task.cont else: self.canMove = True if not self.main.isActive: print "Activate" self.main.isActive = True taskMgr.add(self.main.update, 'updateWorld') self.main.activateKeys() self.countDownText.destroy() return task.done
class Countdown(GameObject): def __init__(self, sfx_path, font, seconds): GameObject.__init__(self) self.countdown_sfx = loader.loadSfx(sfx_path) self.__countdown_txt = OnscreenText('', pos=(0, 0), scale=.2, fg=(1, 1, 1, 1), font=font) self.__cnt = seconds self.tsk = self.eng.do_later(1.0, self.process_countdown) def process_countdown(self): if self.__cnt >= 0: self.countdown_sfx.play() txt = str(self.__cnt) if self.__cnt else _('GO!') self.__countdown_txt.setText(txt) self.__cnt -= 1 return Task.again self.__countdown_txt.destroy() self.notify('on_start_race') def destroy(self): self.tsk = self.eng.rm_do_later(self.tsk) self.__countdown_txt.destroy() GameObject.destroy(self)
class UI(DirectObject): def __init__(self): self.root = render.attachNewNode("Root") base.setBackgroundColor(0, 0, 0) # This code puts the standard title and instruction text on screen self.title = OnscreenText(text="Ball In Maze", style=1, fg=(1, 1, 0, 1), pos=(0.7, -0.95), scale=.07) self.instructions = OnscreenText(text="Press Esc to exit", pos=(-1.3, .95), fg=(1, 1, 0, 1), align=TextNode.ALeft, scale=.05) self.central_msg = OnscreenText(text="", pos=(0, 0), fg=(1, 1, 0, 1), scale=.1) self.central_msg.hide() self.accept("escape", sys.exit) # Escape quits base.disableMouse() # Disable mouse-based camera control camera.setPosHpr(0, 0, 25, 0, -90, 0) # Place the camera # Load the maze and place it in the scene self.maze = loader.loadModel("models/maze") self.maze.reparentTo(render) # Load the ball and attach it to the scene # It is on a root dummy node so that we can rotate the ball itself without # rotating the ray that will be attached to it self.ballRoot = render.attachNewNode("ballRoot") self.ball = loader.loadModel("models/ball") self.ball.reparentTo(self.ballRoot) # This section deals with lighting for the ball. Only the ball was lit # because the maze has static lighting pregenerated by the modeler ambientLight = AmbientLight("ambientLight") ambientLight.setColor(Vec4(.55, .55, .55, 1)) directionalLight = DirectionalLight("directionalLight") directionalLight.setDirection(Vec3(0, 0, -1)) directionalLight.setColor(Vec4(0.375, 0.375, 0.375, 1)) directionalLight.setSpecularColor(Vec4(1, 1, 1, 1)) self.ballRoot.setLight(render.attachNewNode(ambientLight)) self.ballRoot.setLight(render.attachNewNode(directionalLight)) # This section deals with adding a specular highlight to the ball to make # it look shiny m = Material() m.setSpecular(Vec4(1, 1, 1, 1)) m.setShininess(96) self.ball.setMaterial(m, 1) def show_message(self, message=''): if message: self.central_msg.setText(message) self.central_msg.show() else: self.central_msg.hide()
class Countdown(Subject): def __init__(self, countdown_sfx, font): Subject.__init__(self) self.countdown_sfx = loader.loadSfx(countdown_sfx) self.__countdown_txt = OnscreenText( '', pos=(0, 0), scale=.2, fg=(1, 1, 1, 1), font=font) self.countdown_cnt = 3 meth = self.process_countdown self.tsk = taskMgr.doMethodLater(1.0, meth, 'countdown') # manage repeating do_later def process_countdown(self, task): if self.countdown_cnt >= 0: self.countdown_sfx.play() txt = str(self.countdown_cnt) if self.countdown_cnt else _('GO!') self.__countdown_txt.setText(txt) self.countdown_cnt -= 1 return task.again self.__countdown_txt.destroy() self.notify('on_start_race') def destroy(self): self.tsk = taskMgr.remove(self.tsk) self.__countdown_txt.destroy() Subject.destroy(self)
class RespawnCountdown(DirectObject): def __init__(self): self.node = aspect2d.attachNewNode('RespawnCountdown') self.node.setBin('fixed', GUIOrder.ORDER[GUIOrder.HUD_ITEM]) self.node.hide() self.text = OnscreenText(text = 'Respawn in X...', scale = 0.11, fg = (1, 1, 1, 1), shadow = (0, 0, 0, 1), mayChange = True, font = Globals.FONT_SAF) self.text.reparentTo(self.node) def Start(self): self.node.show() self.text.setText('Respawn in %s...' % (Game.RESPAWN_TIME)) t = taskMgr.doMethodLater(1, self.Update, 'UpdateRespawnCountdown') t.i = Game.RESPAWN_TIME def Update(self, task): task.i -= 1 if(task.i == 0): self.Stop() return task.done self.text.setText('Respawn in %s...' % (task.i)) return task.again def Stop(self): self.node.hide()
class SMGUIMeter(): def __init__(self, maxValue): meterImg = None self.value = 0.0 self.maxValue = maxValue self.text = OnscreenText(text = "0", style = 1, fg = (0,0,0,1), pos = (-1.2, -0.95), align = TextNode.ALeft, scale = .2) def fillBy(self, amt): if(self.value + amt > self.maxValue): self.value = self.maxValue else: self.value += amt def emptyBy(self, amt): if(self.value - amt < 0): self.value = self.maxValue else: self.value = 0 def updateSnow(self, playerObj): self.value = playerObj.getSnow() #------------------------------------------------------------------------------------------------------------------------------------------------------------ # Returns the GUI element type. #------------------------------------------------------------------------------------------------------------------------------------------------------------ def getGUIType(self): return 2 def updateGUI(self): self.text.setText(str(self.value))
class TextOnScreen(ShowBase): def __init__(self): ShowBase.__init__(self) self.bk_text = "Text Demo" self.textObject = OnscreenText(text=self.bk_text, pos=(0.95, -0.95), scale=0.07, fg=(1, 0.5, 0.5, 1), align=TextNode.ACenter, mayChange=1) self.b = DirectButton(text=("OK", "click!", "rolling over", "disabled"), text_scale=0.10, scale=0.9, command=self.set_text) self.bb = DirectButton(text=("Reset?", "Reset", "Yes?", "disabled"), text_scale=0.10, scale=0.9, command=self.reset_text) self.bb.set_pos(0, 5) self.anotherTextObject = OnscreenText(text="This text is permanent", pos=(-0.95, 0.95), scale=0.07, fg=(5.0/255.0, 74.0/255.0, 223.0/255.0, 1), align=TextNode.ACenter) def set_text(self): self.bk_text = "Button Clicked" self.textObject.setText(self.bk_text) def reset_text(self): self.bk_text = "Text Demo" self.textObject.setText(self.bk_text)
class Crono(): def __init__(self, app): self.app = app self.countRunning = False self.count = 0 self.counttime = 0.5 self.countMax = 30 self.windowGui = self.app.loader.loadModel("models/window") self.windowGui.setDepthTest(True) self.windowGui.setDepthWrite(True) def draw(self, x, y): self.windowGui.setScale(0.06, 0.06, 0.06) self.windowGui.setPos(x, 0, y) self.windowGui.reparentTo(self.app.render2d) clockStr = "00:00:%s" % self.countMax self.clockMsg = OnscreenText(text=clockStr, style=1, fg=(1, 1, 1, 1), pos=(x + 0.1, y - 0.01), align=TextNode.ALeft, scale=.05) def task(self, Task): #print strftime("%H:%M:%S", localtime()) horas = int(strftime("%H", localtime())) minutos = int(strftime("%M", localtime())) segundos = int(strftime("%S", localtime())) sec = minutos * 60 minute = horas * 60 segundosTotales = segundos + sec + minute #print segundosTotales countStart = 0 if self.countRunning: if ((segundosTotales - self.count) > self.counttime): self.count = segundosTotales self.countMax -= 1 if self.countMax >= 0: clockStr = "00:00:%s" % self.countMax self.clockMsg.setText(clockStr) else: self.countRunning = False self.countMax = 30 return Task.cont def start(self): self.countRunning = True print("countdown starts")
class Crono(): def __init__(self, app): self.app = app self.countRunning = False self.count = 0 self.counttime = 0.5 self.countMax = 30 self.windowGui = self.app.loader.loadModel("models/window") self.windowGui.setDepthTest(True) self.windowGui.setDepthWrite(True) def draw(self, x, y): self.windowGui.setScale(0.06, 0.06, 0.06) self.windowGui.setPos(x, 0, y) self.windowGui.reparentTo(self.app.render2d) clockStr = "00:00:%s" % self.countMax self.clockMsg = OnscreenText(text=clockStr, style=1, fg=(1,1,1,1), pos=(x+0.1, y-0.01), align=TextNode.ALeft, scale = .05) def task(self, Task): #print strftime("%H:%M:%S", localtime()) horas = int(strftime("%H", localtime())) minutos = int(strftime("%M", localtime())) segundos = int(strftime("%S", localtime())) sec = minutos*60 minute = horas*60 segundosTotales = segundos+sec+minute #print segundosTotales countStart = 0 if self.countRunning: if ( (segundosTotales - self.count) > self.counttime ): self.count = segundosTotales self.countMax -= 1 if self.countMax >= 0: clockStr = "00:00:%s" % self.countMax self.clockMsg.setText(clockStr) else: self.countRunning = False self.countMax = 30 return Task.cont def start(self): self.countRunning = True print "countdown starts"
class Power(NodePath, HUDElement): """Modified from drwr: https://discourse.panda3d.org/t/health-bars-using-directgui/2098/3""" def __init__(self, min_strike=0.05, max_strike=7): self.min_strike = min_strike self.max_strike = max_strike HUDElement.__init__(self) self.text_scale = 0.11 self.text_color = (1, 1, 1, 1) NodePath.__init__(self, 'powerbar') self.reparentTo(self.dummy_right) cmfg = CardMaker('fg') cmfg.setFrame(0, 1, -0.04, 0.04) self.fg = self.attachNewNode(cmfg.generate()) cmbg = CardMaker('bg') cmbg.setFrame(-1, 0, -0.04, 0.04) self.bg = self.attachNewNode(cmbg.generate()) self.bg.setPos(1, 0, 0) self.fg.setColor(1, 0, 0, 1) self.bg.setColor(0.5, 0.5, 0.5, 1) self.setScale(0.3) start_value = 2 self.text = OnscreenText( text=f"{start_value:.2f} m/s", pos=(0, 0), scale=self.text_scale, fg=self.text_color, align=TextNode.ACenter, mayChange=True, parent=self, ) self.text.setPos(0.5, -0.15) self.setPos(0, 0, -0.9) self.set(start_value) def init(self): self.show() def destroy(self): self.hide() del self.text del self def set(self, V0): self.text.setText(f"{V0:.2f} m/s") value = (V0 - self.min_strike) / (self.max_strike - self.min_strike) if value < 0: value = 0 if value > 1: value = 1 self.fg.setScale(value, 1, 1) self.bg.setScale(1.0 - value, 1, 1)
class mineRender(ShowBase): def __init__(self): ShowBase.__init__(self) self.mine = self.loader.loadModel("models/mine") self.mine.reparentTo(self.render) self.mine.setScale(1, 1, 1) self.mine.setPos(0, 0, 0) metalTex = loader.loadTexture('maps/bulkhead.jpg') self.mine.setColor(44, 55, 37, 1) # setTexture(metalTex) self.background = OnscreenImage(parent=render2d, image='maps/pool.jpg') base.cam2d.node().getDisplayRegion(0).setSort(-20) light = Spotlight('slight') light.setColor((1, 1, 1, 1)) self.spot = render.attachNewNode(light) self.spot.setPos(6, 6, 6) self.spot.lookAt(self.mine) render.setLight(self.spot) self.labelText = OnscreenText( text=("runtime: {}".format(0) + "\ncamera_pos: {}".format(self.camera.getPos()) + "\ncamera_Hpr: {}".format(self.camera.getHpr())), pos=(-0.6, -0.8), scale=0.07) self.taskMgr.add(self.spinCameraTask, "SpinCameraTask") self.taskMgr.add(self.spinLightTask, "SpinLightTask") self.taskMgr.add(self.updateText, "updateText") def updateText(self, task): self.labelText.setText( "runtime: {}".format(task.time) + "\ncamera_pos: {}".format(self.camera.getPos()) + "\ncamera_Hpr: {}".format(self.camera.getHpr())) return Task.cont def spinCameraTask(self, task): angleDegrees = task.time * 10.0 angleRadians = angleDegrees * (pi / 180.0) self.camera.setPos(8 * sin(angleRadians), -8 * cos(angleRadians), 4) #self.camera.setHpr(angleDegrees,0,0) self.camera.lookAt(self.mine) return Task.cont def spinLightTask(self, task): angleDegrees = task.time * 10.0 angleRadians = angleDegrees * (pi / 180.0) self.spot.setPos(20 * sin(angleRadians - 2), -20 * cos(angleRadians - 2), 10) #self.spot.setHpr(angleDegrees,0,0) self.spot.lookAt(self.mine) return Task.cont
class UI(DirectObject): def __init__(self): self.root = render.attachNewNode("Root") base.setBackgroundColor(0,0,0) # This code puts the standard title and instruction text on screen self.title = OnscreenText(text="Ball In Maze", style=1, fg=(1,1,0,1), pos=(0.7,-0.95), scale = .07) self.instructions = OnscreenText(text="Press Esc to exit", pos = (-1.3, .95), fg=(1,1,0,1), align = TextNode.ALeft, scale = .05) self.central_msg = OnscreenText(text="", pos = (0, 0), fg=(1, 1, 0, 1), scale = .1 ) self.central_msg.hide() self.accept("escape", sys.exit) # Escape quits base.disableMouse() # Disable mouse-based camera control camera.setPosHpr(0, 0, 25, 0, -90, 0) # Place the camera # Load the maze and place it in the scene self.maze = loader.loadModel("models/maze") self.maze.reparentTo(render) # Load the ball and attach it to the scene # It is on a root dummy node so that we can rotate the ball itself without # rotating the ray that will be attached to it self.ballRoot = render.attachNewNode("ballRoot") self.ball = loader.loadModel("models/ball") self.ball.reparentTo(self.ballRoot) # This section deals with lighting for the ball. Only the ball was lit # because the maze has static lighting pregenerated by the modeler ambientLight = AmbientLight("ambientLight") ambientLight.setColor(Vec4(.55, .55, .55, 1)) directionalLight = DirectionalLight("directionalLight") directionalLight.setDirection(Vec3(0, 0, -1)) directionalLight.setColor(Vec4(0.375, 0.375, 0.375, 1)) directionalLight.setSpecularColor(Vec4(1, 1, 1, 1)) self.ballRoot.setLight(render.attachNewNode(ambientLight)) self.ballRoot.setLight(render.attachNewNode(directionalLight)) # This section deals with adding a specular highlight to the ball to make # it look shiny m = Material() m.setSpecular(Vec4(1,1,1,1)) m.setShininess(96) self.ball.setMaterial(m, 1) def show_message(self, message=''): if message: self.central_msg.setText(message) self.central_msg.show() else: self.central_msg.hide()
class ResourceBar: def __init__(self, x, y, size): self.text = OnscreenText("Gold: " + str(base.ecn_manager.gold) + " +" + str(base.ecn_manager.gold_inc), pos=(x, y), scale=size, fg=base.vis_manager.get_player_col( base.player)) def update(self): self.text.setText("Gold: " + str(int(base.ecn_manager.gold)) + " +" + str(base.ecn_manager.gold_inc))
def makeMsgLeft(x, y, txt="msg", color="white"): fg = textColors[color][0] bg = textColors[color][1] M = OnscreenText(fg=fg, bg=bg, pos=(x, y), align=TextNode.ALeft, mayChange=1, font=FONT, scale=FONT_SCALE) M.setText(txt) return M
class CrowdControlLevelEditorApp(CrowdControlWorldApp): cursorZ = 0.0 def __init__(self): CrowdControlWorldApp.__init__(self) self.modeTextObject = OnscreenText(style=1, fg=(1, 1, 1, 1), pos=(0.8, -0.95), scale=0.07, text="Test") self.modeMenuObject = DirectOptionMenu( text="options", pos=(-1.2, 0.0, 0.91), scale=0.1, items=["Select", "Delete", "Add"], initialitem=2, highlightColor=(0.65, 0.65, 0.65, 1), command=self.onChangeEditorMode, ) self.floorLevelSlider = DirectSlider( range=(-100, 100), pos=(-1.2, 0.0, 0.0), value=self.cursorZ, pageSize=0.5, scale=0.6, command=self.onChangeFloorSliderValue, orientation=DGG.VERTICAL, ) # Callback function to set text def onChangeEditorMode(self, arg): output = "Item Selected is: " + arg self.modeTextObject.setText(output) def onChangeFloorSliderValue(self): pass def createNewLevel(self): self.tilesets.append(TileSet("artwork/floor-tileset.png")) def updateCursorPosition(self): if self.mouseWatcherNode.hasMouse(): x = self.mouseWatcherNode.getMouseX() y = self.mouseWatcherNode.getMouseY() def _createCursor(self): cursorObject = TileSquare(0, 0, self.cursorZ) self.cursorNodePath = self.render.attachNewNode(cursorObject) self.cursorNodePath.hide() texture = self.loader.loadTexture("artwork/cursor.png") ts = TextureStage("ts") self.cursorNodePath.setTexture(ts, texture, 1)
class Popup: '''Meta class for messages that appear on certain actions and disappear into nowhere''' def __init__(self, text=None, pos=(0, 0), align=TextNode.ACenter, scale=1, fg=(1, 1, 1, 1), parent=None, name="Popup", duration=1): if not parent: parent = base.aspect2d self.duration = duration self.name = name #maybe make it possible for popup message to be not just text? idk self.popup_msg = OnscreenText(pos=pos, align=align, scale=scale, fg=fg, parent=parent, mayChange=True) if text: self.set_text(text) self.popup_msg.hide() def set_duration(self, duration): #duration may be both int and float, idk how to do that yet self.duration = duration def set_text(self, text: str): '''Set message's text. Same as setText of panda's native gui items''' self.popup_msg.setText(text) def show(self): '''Show popup for self.duration seconds, then auto-hide it away''' #todo: add ability to use some visual effects self.popup_msg.show() #todo: maybe remake it into lerp, so there wont be need to involve base. #this function is hidden inside, coz we have no use for it outside def hide_popup_task(event): self.popup_msg.hide() return base.task_mgr.do_method_later(self.duration, hide_popup_task, self.name)
def makeMsgCenter(x, y, txt="msg", color="white"): fg = textColors[color][0] bg = textColors[color][1] M = OnscreenText(style=1, fg=fg, bg=bg, pos=(x, y), align=TextNode.ACenter, scale=FONT_SCALE, mayChange=1, font=FONT) M.setText(txt) return M
class DebugText: def __init__(self): self.top_right_text = OnscreenText(text="", scale=0.1, pos=(0.8, 0.9), mayChange=True, align=TextNode.ALeft) def update(self, world): self.top_right_text.setText(f""" Ant Count: {len(world.walking_enemies)} Food Count: {len(world.foods)} """)
def checkGameState(self, task, message = None): goodEndingText = OnscreenText(text="", style=1, fg=(0,0,1,0.01), pos=(0,.4), align=TextNode.ACenter, scale = .25, mayChange = True) BaadEndingText = OnscreenText(text="", style=1, fg=(1,0,0,0.01), pos=(0,.4), align=TextNode.ACenter, scale = .25, mayChange = True) if(self.fadeCounter > 0): if(self.__mainAgent.hasKey(self.room1Key) and self.__mainAgent.hasKey(self.room2Key) and self.__mainAgent.hasKey(self.room3Key)): self.hasAllKeys = True #goodEndingText.setText("You have all 3 keys!") if(self.hasAllKeys): goodEndingText.setText("You have all 3 keys!") if(PathFinder.distance(self.__mainAgent, self.__room1NPC) < 5 and self.__room1NPC.getState() != "returnKey"): if(not self.__mainAgent.hasKey(self.room1Key)): self.playerWasKilledByNPC1 = True if(self.playerWasKilledByNPC1): self.fadeCounter = self.fadeCounter - 1 BaadEndingText.setText("Killed by Eve clone Alpha") if(PathFinder.distance(self.__mainAgent, self.__room2NPC) < 5 and self.__room2NPC.getState() != "returnKey"): if(not self.__mainAgent.hasKey(self.room2Key)): self.playerWasKilledByNPC2 = True if(self.playerWasKilledByNPC2): self.fadeCounter = self.fadeCounter - 1 BaadEndingText.setText("Killed by Eve clone Beta") if(PathFinder.distance(self.__mainAgent, self.__room3NPC) < 5 and self.__room3NPC.getState() != "returnKey"): if(not self.__mainAgent.hasKey(self.room3Key)): self.playerWasKilledByNPC3 = True if(self.playerWasKilledByNPC3): self.fadeCounter = self.fadeCounter - 1 BaadEndingText.setText("Killed by Eve clone Gamma") return Task.cont
class PlayerList(object): """Handles the list of players and the associated UI.""" def __init__(self, game): self.game = game self.display = False props = base.win.getProperties() ratio = float(props.getXSize()) / props.getYSize() self.frame = DirectFrame(frameColor=(0, 0, 0, 0), frameSize=(-1, 0, -1, 0), pos=(ratio, 0, 1)) self.text = OnscreenText( text="", pos=(-0.02, -0.05), scale=0.05, fg=(1, 1, 1, 1), parent=self.frame, align=TextNode.ARight, mayChange=True, ) base.accept("tab", self.toggleDisplay) def toggleDisplay(self): if not self.game.isChatting: self.display = not self.display self.updateDisplay() def updateDisplay(self): if self.display: list = "Current Players:" if self.game.character is not None: list += "\n" + self.describe(self.game.character) for id in self.game.characters: list += "\n" + self.describe(self.game.characters[id]) self.text.setText(list) self.display = True else: self.text.setText("") def describe(self, character): desc = character.name + " (" if character.modelType == Constants.CHAR_RALPH: desc += "Ralph" if character.modelType == Constants.CHAR_PANDA: desc += "Panda" if character.modelType == Constants.CHAR_VEHICLE: desc += "Car" return desc + ")"
class English(HUDElement): def __init__(self): HUDElement.__init__(self) self.dir = ani.model_dir / 'hud' / 'english' self.text_scale = 0.2 self.text_color = (1, 1, 1, 1) self.circle = OnscreenImage(image=panda_path(self.dir / 'circle.png'), parent=self.dummy_right, scale=0.15) self.circle.setTransparency(TransparencyAttrib.MAlpha) autils.alignTo(self.circle, self.dummy_right, autils.CL, autils.C) self.circle.setZ(-0.65) self.crosshairs = OnscreenImage(image=panda_path(self.dir / 'crosshairs.png'), pos=(0, 0, 0), parent=self.circle, scale=0.14) self.crosshairs.setTransparency(TransparencyAttrib.MAlpha) self.text = OnscreenText( text="(0.00, 0.00)", pos=(0, -1.15), scale=self.text_scale, fg=self.text_color, align=TextNode.ACenter, mayChange=True, parent=self.circle, ) def set(self, a, b): self.crosshairs.setPos(-a, 0, b) self.text.setText(f"({a:.2f},{b:.2f})") def init(self): self.show() def show(self): self.circle.show() def hide(self): self.circle.hide() def destroy(self): self.hide() del self.text del self.crosshairs del self.circle
class Log(ServiceScreenBase): def __init__(self, screen_manager): super(Log, self).__init__(screen_manager, "System Log") self.log_view = OnscreenText("", 1, fg=(1, 1, 1, 1), pos=(-1.3, 0.80), align=TextNode.ALeft, scale=.05, mayChange=True, parent=self.node2d) def set_log_text(self, text): self.log_view.setText(text)
class Switches(ServiceScreenBase): def __init__(self, screen_manager): super(Switches, self).__init__(screen_manager, "Switch Test") self.current_switch = OnscreenText( "", 1, fg=(1, 1, 1, 1), pos=(-1.3, 0.60), align=TextNode.ALeft, scale=.10, mayChange=True, # font = base.fontLoader.load('Arial Bold.ttf'), parent=self.node2d) self.switches = OnscreenImage(parent=self.node2d, image="assets/images/switch_matrix.jpg", scale=(1, 1, 0.8)) # Size # (0.15, 0, 0.174) self.switch_active = OnscreenImage( parent=self.node2d, image="assets/images/switch_active.png", scale=(0.075, 0.1, 0.087), pos=(-0.456, 0, 0.52156)) self.switch_active.setTransparency(TransparencyAttrib.MAlpha) def set_active(self, swnum): swnum = swnum - 11 base_pos = (-0.456, 0, 0.52156) pos = (base_pos[0], 0, base_pos[2] - (swnum * 0.174) + 0.005) self.switch_active.setPos(pos) def img_size(self, model): min, max = model.getTightBounds() return max - min def set_switch(self, text): self.current_switch.setText(text) def show(self): super(Switches, self).show() self.switches.show() self.switch_active.show() def hide(self): super(Switches, self).hide() self.switches.hide() self.switch_active.hide()
def makeLabel(self, fontIndex, msg, scale): fg = textColors["white"][0] bg = textColors["white"][1] M = OnscreenText( style=1, fg=fg, bg=bg, pos=(0, 0), align=TextNode.ALeft, scale = scale, mayChange = 1, font = self.fonts[fontIndex], wordwrap=40*self.winX/800.0) M.setText(msg) return M
class UpdateCode(ServiceScreenBase): def __init__(self, screen_manager): super(UpdateCode, self).__init__(screen_manager, "Update Code") self.progress_text = OnscreenText( "Please insert USB update stick...", 1, fg=(1, 1, 1, 1), pos=(-1.3, 0.50), align=TextNode.ALeft, scale=.10, mayChange=True, # font = base.fontLoader.load('Arial Bold.ttf'), parent=self.node2d) def set_progress(self, text): self.progress_text.setText(text)
class Flashers(ServiceScreenBase): def __init__(self, screen_manager): super(Flashers, self).__init__(screen_manager, "Flasher Test") self.current_flasher = OnscreenText( "", 1, fg=(1, 1, 1, 1), pos=(-1.3, 0.60), align=TextNode.ALeft, scale=.10, mayChange=True, # font = base.fontLoader.load('Arial Bold.ttf'), parent=self.node2d) def set_flasher(self, text): self.current_flasher.setText(text)
class TextMsg: """Simple text message. Basically a wrapper on top of OnscreenText with sane argument names. Has limited set of supported functions, in comparison with original. """ # **kwargs is there to accept garbage items passed from childs. Should be # removed when childs will get proper init args instead of these #TODO def __init__( self, text: str, text_pos: tuple = (0, 0), text_align=TextNode.ACenter, text_scale: float = 0.1, text_color: tuple = (1, 1, 1, 1), parent=None, **kwargs ): self.msg = OnscreenText( pos=text_pos, align=text_align, scale=text_scale, fg=text_color, parent=parent or base.aspect2d, mayChange=True, ) self.set_text(text) self.hide() # None of these functions is necessary - I just want to provide unified way # to do these things for all childs. And to avoid camelCase where possible. # I may remove these in future, if it will seem pointless def set_text(self, text: str): """Set message's text""" self.msg.setText(text) def hide(self): """Hide message""" self.msg.hide() def show(self): """Show message""" self.msg.show()
class Hud(DirectObject): def __init__(self): self.lifeBar = DirectWaitBar(value=100, barColor=(0, 1, 0.20, 1), barRelief=DGG.RAISED, relief=DGG.RIDGE, frameColor=(0.8, 0.05, 0.10, 1), frameSize=(-1.2, 0, 0, -0.1), pos=(-0.2, 0, base.a2dTop)) self.lifeBar.setTransparency(1) self.font = loader.loadFont( str(MAINDIR) + '/assets/fonts/allerdisplay.ttf') self.score_text = OnscreenText(text="Score:", pos=(-1.6, 0.93), scale=0.05, fg=(1, 1, 1, 1), align=TextNode.ACenter, font=self.font, mayChange=False) self.score = OnscreenText(text="0", pos=(-1.6, 0.83), scale=0.07, fg=(1, 1, 1, 1), align=TextNode.ACenter, font=self.font, mayChange=True) self.accept("hud_setLifeBarValue", self.setLifeBarValue) self.hide() def show(self): self.lifeBar["value"] = 100 self.lifeBar.show() def hide(self): self.lifeBar.hide() def setScore(self, score): self.score.setText(str(score)) def setLifeBarValue(self, newValue): self.lifeBar["value"] = newValue
class HUDBottomRight(DirectObject): def __init__(self): self.node = base.a2dBottomRight.attachNewNode('hudBottomRight')#GUIOrder.ORDER[GUIOrder.HUD]) self.node.setBin('fixed', GUIOrder.ORDER[GUIOrder.HUD]) self.ammoIcon = OnscreenImage(image = 'Assets/Images/HUD/HUDBottomRight.png', scale = 512.0 / 1024, pos = (-0.5, 0, 0.5)) self.ammoIcon.setTransparency(TransparencyAttrib.MAlpha) self.ammoIcon.reparentTo(self.node) self.ammoTextClip = OnscreenText(text = '30', pos = (-0.35, 0.09), scale = 0.12, fg = (1, 1, 1, 1), shadow = (0, 0, 0, 1), mayChange = True, align=TextNode.ARight, font = Globals.FONT_SAF) self.ammoTextClip.reparentTo(self.node) self.ammoTextClip.setBin('fixed', GUIOrder.ORDER[GUIOrder.HUD]) self.ammoTextLeft = OnscreenText(text = '90', pos = (-0.23, 0.05), scale = 0.07, fg = (1, 1, 1, 1), shadow = (0, 0, 0, 1), mayChange = True, align=TextNode.ARight, font = Globals.FONT_SAF) self.ammoTextLeft.reparentTo(self.node) self.ammoTextLeft.setBin('fixed', GUIOrder.ORDER[GUIOrder.HUD]) self.accept(AmmoChangeEvent.EventName, self.OnAmmoChangeEvent) self.accept(SelectedItemChangeEvent.EventName, self.OnSelectedItemChangeEvent) def OnAmmoChangeEvent(self, event): item = event.GetItem() if(item and item.GetCurrentClipAmmo() == ''): self.ChangeAmmoText('', '') else: self.ChangeAmmoText(str(item.GetCurrentClipAmmo()), str(item.GetTotalRemainingAmmo())) def ChangeAmmoText(self, clip, total): self.ammoTextClip.setText(clip) self.ammoTextLeft.setText(total) def OnSelectedItemChangeEvent(self, event): if(event.GetItemStack() and event.GetItemStack().GetItem()): self.OnAmmoChangeEvent(AmmoChangeEvent(None, event.GetItemStack().GetItem())) else: self.ChangeAmmoText('', '') def Destroy(self): self.ignoreAll() self.ammoIcon.removeNode() self.ammoTextClip.removeNode() self.ammoTextLeft.removeNode() self.node.removeNode()
class SpaceGui: def __init__(self, playerdata): self.playerData = playerdata self.topbar = SpaceTopButtonBar() yellow = (0.65234375, 0.6484375, 0.3359375) blue = (0.25390625, 0.2734375, 0.7421875) red = (0.546875, 0.125, 0.17578125) self.laserHP = SpaceBarre(2,yellow, self.playerData.ship.gunHPMax) self.shieldHP = SpaceBarre(1,blue, self.playerData.ship.shieldHPMax) self.coqueHP = SpaceBarre(0,red, self.playerData.ship.coqueHPMax) x = 0.4 y = -0.92 self.speedMsg = OnscreenText(pos=(x, y-0.015), fg = (1,1,1,1), scale = 0.05, align=TextNode.ACenter, mayChange = 1) self.speedMsg["font"] = FONT self.speedMsg["scale"] = (0.04,0.05,1.0) self.speedImg = makeImg(x, y, "img/gui/speed.png", (0.11,1.0,0.07)) self.label1 = SpaceLabel(-0.8,-0.7,"loot", "item 1") self.label2 = SpaceLabel(-0.8,-0.76,"loot", "Some spaceship") self.items = [self.topbar, self.laserHP, self.shieldHP, self.coqueHP, self.speedMsg, self.speedImg, self.label1, self.label2 ] self.hide() def setSpeed(self, speed): self.speedMsg.setText(str(speed)) def show(self): for item in self.items: item.show() def hide(self): for item in self.items: item.hide() def destroy(self): for item in self.items: item.destroy()
def myTask(task): if (int(tex.getTime()) >=20): print "Stoping" c=0 card.remove() self.sonic.setPos(0,0,-2) self.keyMap["res"]=0 myscore = DirectLabel() myscore.reparentTo(render) #mytimer.setY(0) textObj = OnscreenText(text = "", pos = (0.95,0.95), scale = 0.07,fg=(1,0.5,0.5,1),align=TextNode.ACenter,mayChange=1) c=c+1 myscore['text'] = "Score:"+"2" #print mytimer['text'] textObj.setText(myscore['text']) return task.done #if myMovieTexture.getTime() == myMovieLength: # print "movie puri" return task.cont
class GodCamera(DirectObject): enabled = False def __init__(self): self.godCamNode = render.attachNewNode("godCamNode") self.movement = Movement() self.rotation = Rotation() self.guiposOnscreenText = OnscreenText(text = 'position', fg=(1,1,1,1), pos = (-0.9, 0.9), scale = 0.07, mayChange=True, align=TextNode.ALeft ) def isEnabled(self): return self.enabled def toggleEnabled(self): if self.isEnabled(): self.disable() else: self.enable() def enable(self): taskMgr.doMethodLater(0.1, self.updateGuiposTask, 'updateGuiposTask') self.movement.enable() self.rotation.enable() self.enabled = True base.camera.reparentTo( self.godCamNode ) def disable(self): self.ignoreAll() self.removeAllTasks() self.guiposOnscreenText.setText("") self.movement.disable() self.rotation.disable() self.enabled = False base.camera.reparentTo( render ) def updateGuiposTask( self, task ): text = "%s:%s" % (str(base.camera.getPos( render )), str(base.camera.getHpr( render ))) self.guiposOnscreenText.setText( text ) return Task.cont
class HUD(object): def __init__(self, walls, lights): self.initHUD(walls, lights) def initHUD(self, walls, lights): self.wallsText = OnscreenText(text = 'Walls:', pos = (-1.1, 0.86), scale = 0.08, fg = (1,1,1,1)) self.lightsText = OnscreenText(text = 'Lights:', pos = (-1.1, 0.77), scale = 0.08, fg = (1,1,1,1)) self.wallsLeft = OnscreenText(text = str(walls), pos = (-0.92, 0.86), scale = 0.08, fg = (1,1,1,1), mayChange = True) self.lightsLeft = OnscreenText(text = str(lights), pos = (-0.92, 0.77), scale = 0.08, fg = (1,1,1,1), mayChange = True) self.energyText = OnscreenText(text = 'Energy:', pos = (0.9, -0.86), scale = 0.08, fg = (1,1,1,1)) self.energyLeft = OnscreenText(text = '100', pos = (1.1, -0.86), scale = 0.08, fg = (1,1,1,1), mayChange = True) def updateHUD(self, walls, lights, energy): self.wallsLeft.setText(str(walls)) self.lightsLeft.setText(str(lights)) self.energyLeft.setText(str(int(energy))) def __del__(self): self.wallsText.destroy() self.lightsText.destroy() self.wallsLeft.destroy() self.lightsLeft.destroy() self.energyText.destroy() self.energyLeft.destroy()
class Application(ShowBase): def __init__(self): ShowBase.__init__(self) self.status = OnscreenText("Window Mode") toggle = Sequence( Wait(3), Func(self.status.setText, "Switching to Fullscreen Mode"), Wait(2), Func(self.toggleFullscreen, 1280, 800, 0, 0, 1), Wait(3), Func(self.status.setText, "Switching to Window Mode"), Wait(2), Func(self.toggleFullscreen, 800, 600, 50, 50, 0)) toggle.start() def toggleFullscreen(self, width, height, posX, posY, full): winProps = WindowProperties() winProps.setOrigin(posX, posY) winProps.setSize(width, height) winProps.setFullscreen(full) self.win.requestProperties(winProps) if full: self.status.setText("Fullscreen Mode") else: self.status.setText("Window Mode")
class HUDBottomLeft(DirectObject): def __init__(self): self.node = base.a2dBottomLeft.attachNewNode('hudhealth')#GUIOrder.ORDER[GUIOrder.HUD]) self.node.setBin('fixed', GUIOrder.ORDER[GUIOrder.HUD]) self.health = OnscreenImage(image = 'Assets/Images/HUD/HUDBottomLeft.png', scale = 512.0 / 1024, pos = (0.5, 0, 0.5)) self.health.setTransparency(TransparencyAttrib.MAlpha) self.health.reparentTo(self.node) self.healthText = OnscreenText(text = '100', pos = (0.2, 0.07), scale = 0.12, fg = (1, 1, 1, 1), shadow = (0, 0, 0, 1), mayChange = True, font = Globals.FONT_SAF, align=TextNode.ALeft) self.healthText.reparentTo(self.node) self.healthText.setBin('fixed', GUIOrder.ORDER[GUIOrder.HUD]) self.healthColorSeq = Sequence(LerpColorScaleInterval(self.node, 0.25, Globals.COLOR_RED), LerpColorScaleInterval(self.node, 0.25, Globals.COLOR_WHITE)) self.dieingColorSeq = Sequence(LerpColorScaleInterval(self.node, 1, Globals.COLOR_RED), LerpColorScaleInterval(self.node, 1, Globals.COLOR_WHITE)) self.accept(PlayerHealthEvent.EventName, self.OnPlayerHealthEvent) def OnPlayerHealthEvent(self, event): health = event.GetHealth() self.healthText.setText(str(health)) if(health < 16): #self.node.setColor(Globals.COLOR_RED) self.dieingColorSeq.loop() elif(health == 100): self.dieingColorSeq.finish() else: self.healthColorSeq.start() def Destroy(self): self.ignoreAll() self.health.removeNode() self.healthText.removeNode() self.node.removeNode()
class SMGUIMeter(): def __init__(self, maxValue): meterImg = None self.value = 0.0 self.maxValue = maxValue self.text = OnscreenText(text="0", style=1, fg=(0, 0, 0, 1), pos=(-1.2, -0.95), align=TextNode.ALeft, scale=.2) def fillBy(self, amt): if (self.value + amt > self.maxValue): self.value = self.maxValue else: self.value += amt def emptyBy(self, amt): if (self.value - amt < 0): self.value = self.maxValue else: self.value = 0 def updateSnow(self, playerObj): self.value = playerObj.getSnow() #------------------------------------------------------------------------------------------------------------------------------------------------------------ # Returns the GUI element type. #------------------------------------------------------------------------------------------------------------------------------------------------------------ def getGUIType(self): return 2 def updateGUI(self): self.text.setText(str(self.value))
class HUD(): def __init__(self): self.speedometer = OnscreenImage(image = 'img/speedometerDial.png', pos = (-1, 0, -.7) ) self.speedometer.setScale(.25) self.speedometer.setTransparency(TransparencyAttrib.MAlpha) self.speedPin = OnscreenImage(image = 'img/speedometerNeedle.png', pos = (-1, 0, -.7)) self.speedPin.setScale(.10) self.speedPin.setTransparency(TransparencyAttrib.MAlpha) self.speedPin.setHpr(0, 0, 0) self.minimap = OnscreenImage(image = 'img/minimap.png', pos = (1.05, 0, -.65)) self.minimap.setScale(.19, .19, .3) self.dot = OnscreenImage(image = 'img/dot.png', pos = (1.01, 0, -.55)) self.dot.setScale(.025) font1 = loader.loadFont('img/goodfish.ttf') self.lapText = OnscreenText(text = "0/10", font = font1, pos = (1, -.1, 0), fg = (1, 1, 1, 1) ) self.lapText.setScale(.05) self.placeText = OnscreenText(text = "", font = font1, pos = (1, -.2, 0), fg = (1, 1, 1, 1)) self.placeText.setScale(.05) self.timerText = OnscreenText(text = "Time: ", font = font1, pos = (1, -.3, 0), fg = (1, 1, 1, 1)) def update(self, velocity, x, y, laps, place, time): if velocity < 0: velocity = -velocity self.dot.setPos(1.01+(x/4250), 0, -.55+(y/4250)) self.lapText.setText("Laps: " + str(laps)+"/3") self.speedPin.setHpr(0, 0, 4*velocity) self.placeText.setText("Position: "+str(place)) self.timerText.setText("Time: "+ str(round(time))) """def getDist(self, x, y, checkpoint): cx = checkpoint[0] cy = checkpoint[1] dist = math.sqrt((cx-x)**2 + (cy-y)**2) rotAngle = math.atan2(-y,x) newX = x*math.cos(rotAngle) - y*math.sin(rotAngle) dToCheckpoint = dist - newX return dToCheckpoint""" """def updateMiniMap(self, x, y): self.dot.setPos(1+(x/1000), 0, -.7+(y/1000))"""
def checkGameState(self, task, message=None): goodEndingText = OnscreenText(text="", style=1, fg=(0, 0, 1, 0.01), pos=(0, .4), align=TextNode.ACenter, scale=.25, mayChange=True) BaadEndingText = OnscreenText(text="", style=1, fg=(1, 0, 0, 0.01), pos=(0, .4), align=TextNode.ACenter, scale=.25, mayChange=True) if (self.fadeCounter > 0): if (self.__mainAgent.hasKey(self.room1Key) and self.__mainAgent.hasKey(self.room2Key) and self.__mainAgent.hasKey(self.room3Key)): self.hasAllKeys = True #goodEndingText.setText("You have all 3 keys!") if (self.hasAllKeys): goodEndingText.setText("You have all 3 keys!") if (PathFinder.distance(self.__mainAgent, self.__room1NPC) < 5 and self.__room1NPC.getState() != "returnKey"): if (not self.__mainAgent.hasKey(self.room1Key)): self.playerWasKilledByNPC1 = True if (self.playerWasKilledByNPC1): self.fadeCounter = self.fadeCounter - 1 BaadEndingText.setText("Killed by Eve clone Alpha") if (PathFinder.distance(self.__mainAgent, self.__room2NPC) < 5 and self.__room2NPC.getState() != "returnKey"): if (not self.__mainAgent.hasKey(self.room2Key)): self.playerWasKilledByNPC2 = True if (self.playerWasKilledByNPC2): self.fadeCounter = self.fadeCounter - 1 BaadEndingText.setText("Killed by Eve clone Beta") if (PathFinder.distance(self.__mainAgent, self.__room3NPC) < 5 and self.__room3NPC.getState() != "returnKey"): if (not self.__mainAgent.hasKey(self.room3Key)): self.playerWasKilledByNPC3 = True if (self.playerWasKilledByNPC3): self.fadeCounter = self.fadeCounter - 1 BaadEndingText.setText("Killed by Eve clone Gamma") return Task.cont
class cApplication( DirectObject ): def __init__( self ): # create world self.world = cWorld( ) # setup controls self.setupControls( ) # display title information self.title = OnscreenText( text = 'BOIDS.PY - SEEK & ARRIVE', fg = ( 1.0, 1.0, 1.0, 1.0), pos = ( -.98, .9 ), scale = 0.06 ) # display copright information self.copyRight = OnscreenText( text = 'Copyright (C) 2016 David Lettier.', fg = ( 1.0, 1.0, 1.0, 1.0), pos = ( .98, -.98 ), scale = 0.05 ) # display panda version text self.pandaVersion = OnscreenText( text = 'Panda Version 1.9.2', fg = ( 1.0, 1.0, 1.0, 1.0), pos = ( -1.18, -.98 ), scale = 0.04 ) # display print debug button # this button calls the prntDebug function self.prntDebugButton = DirectButton( text = "Print Debug", relief = DGG.RAISED, scale = .1, pad = ( .5, .5 ), pos = Vec3( -1.0, 0.0, -.8 ), command = self.prntDebug ) def setupControls( self ): # accept the esc key to exit application self.accept( 'escape', sys.exit ) def prntDebug( self ): # destory debug button self.prntDebugButton.destroy( ) # create new clear debug button # this button calls the clearDebug function self.clearDebugButton = DirectButton( text = "Clear Debug", relief = DGG.RAISED, scale = .1, pad = ( .5, .5 ), pos = Vec3( -1.0, 0.0, -.8 ), command = self.clearDebug ) # create green target position text self.greenPos = OnscreenText( text = 'Green Target Pos: ' + str( int( self.world.target.getX( ) ) ) + ", " + str( int( self.world.target.getY( ) ) ) + ", " + str( int( self.world.target.getZ( ) ) ), fg = ( 1.0, 1.0, 1.0, 1.0), pos = ( -.8, .8 ), scale = 0.05, mayChange = True ) # create blue boid position text self.bluePos = OnscreenText( text = 'Blue Boid (Arrive) Pos: ' + str( int( self.world.blueBoid.boidModel.getX( ) ) ) + ", " + str( int( self.world.blueBoid.boidModel.getY( ) ) ) + ", " + str( int( self.world.blueBoid.boidModel.getZ( ) ) ), fg = ( 1.0, 1.0, 1.0, 1.0), pos = ( -.8, .7 ), scale = 0.05, mayChange = True ) # create green boid position text self.redPos = OnscreenText( text = 'Red Boid (Seek) Pos: ' + str( int( self.world.redBoid.boidModel.getX( ) ) ) + ", " + str( int( self.world.redBoid.boidModel.getY( ) ) ) + ", " + str( int( self.world.redBoid.boidModel.getZ( ) ) ), fg = ( 1.0, 1.0, 1.0, 1.0), pos = ( -.8, .6 ), scale = 0.05, mayChange = True ) # add the update on screen text task taskMgr.add( self.updateOSTxt, 'updateOSTxt' ) def updateOSTxt( self, Task ): # update green target position text self.greenPos.setText( 'Green Target Pos: ' + str( int( self.world.target.getX( ) ) ) + ", " + str( int( self.world.target.getY( ) ) ) + ", " + str( int( self.world.target.getZ( ) ) ) ) # update blue boid position text self.bluePos.setText( 'Blue Boid (Arrive) Pos: ' + str( int( self.world.blueBoid.boidModel.getX( ) ) ) + ", " + str( int( self.world.blueBoid.boidModel.getY( ) ) ) + ", " + str( int( self.world.blueBoid.boidModel.getZ( ) ) ) ) # update red boid position text self.redPos.setText( 'Red Boid (Seek) Pos: ' + str( int( self.world.redBoid.boidModel.getX( ) ) ) + ", " + str( int( self.world.redBoid.boidModel.getY( ) ) ) + ", " + str( int( self.world.redBoid.boidModel.getZ( ) ) ) ) # call task next frame return Task.cont def clearDebug( self ): # destory button self.clearDebugButton.destroy( ) # destory all debug on screen text self.greenPos.destroy( ) self.bluePos.destroy( ) self.redPos.destroy( ) # remove task taskMgr.remove( 'updateOSTxt' ) # create again the print debug button to start the cycle all over again self.prntDebugButton = DirectButton( text = "Print Debug", relief = DGG.RAISED, scale = .1, pad = ( .5, .5 ), pos = Vec3( -1.0, 0.0, -.8 ), command = self.prntDebug )
class FPSCounter(DirectObject): def __init__(self): self.node = base.a2dTopLeft.attachNewNode('Debug Info') self.node.setPos(0.03, 0, -0.15) self.fpsText = OnscreenText(text = '', pos = (0, 0), scale = 0.06, fg = (1, 1, 1, 1), align = TextNode.ALeft, mayChange = True) self.fpsText.reparentTo(self.node) self.fps = 60 self.lastTextUpdateTime = 0 self.chunkText = OnscreenText(text = '', pos = (0, -0.07), scale = 0.05, fg = (1, 1, 1, 1), align = TextNode.ALeft, mayChange = True) self.chunkText.reparentTo(self.node) self.bandwidthText = OnscreenText(text = '', pos = (0, -0.14), scale = 0.05, fg = (1, 1, 1, 1), align = TextNode.ALeft, mayChange = True) self.bandwidthText.reparentTo(self.node) self.accept(ChunkTimeEvent.EventName, self.UpdateChunkTime) self.accept(BandwidthInfoEvent.EventName, self.UpdateBandwidth) def Update(self): if(GameTime.deltaTime == 0): return self.fps += 0.1 * ((1.0 / GameTime.deltaTime) - self.fps) if(GameTime.time - self.lastTextUpdateTime > 0.5): self.fpsText.setText('FPS: %s' % (str(int(self.fps)))) self.lastTextUpdateTime = GameTime.time def UpdateChunkTime(self, event): self.chunkText.setText('Chunk: %s' % (str(event.GetTime()))) def UpdateBandwidth(self, event): self.bandwidthText.setText('In: %s\nOut: %s' % (event.GetIncoming(), event.GetOutgoing())) def Destroy(self): self.fpsText.removeNode() del self.fpsText self.chunkText.removeNode() del self.chunkText self.bandwidthText.removeNode() del self.bandwidthText self.ignoreAll()
class DistributedPartyTrampolineActivity(DistributedPartyActivity): notify = DirectNotifyGlobal.directNotify.newCategory('DistributedPartyTrampolineActivity') def __init__(self, cr, doJellyBeans = True, doTricks = False, texture = None): DistributedPartyTrampolineActivity.notify.debug('__init__') DistributedPartyActivity.__init__(self, cr, PartyGlobals.ActivityIds.PartyTrampoline, PartyGlobals.ActivityTypes.GuestInitiated, wantLever=False, wantRewardGui=True) self.doJellyBeans = doJellyBeans self.doTricks = doTricks self.texture = texture self.toon = None self.trampHeight = 3.6 self.trampK = 400.0 self.normalTrampB = 2.5 self.leavingTrampB = 8.0 self.trampB = self.normalTrampB self.g = -32.0 self.jumpBoost = 330.0 self.beginningBoost = 500.0 self.beginningBoostThreshold = self.trampHeight + 1.5 self.earlyJumpThreshold = 75.0 self.boingThreshold = 300.0 self.turnFactor = 120.0 self.stepDT = 0.001 self.targetCameraPos = Point3(0.0, 40.0, 10.0) self.cameraSpeed = 2.0 self.hopOffPos = Point3(16.0, 0.0, 0.0) self.indicatorFactor = 0.0095 self.dropShadowCutoff = 15.0 self.minHeightForText = 15.0 self.heightTextOffset = -0.065 self.beanOffset = 0.5 self.guiBeanOffset = -0.02 self.jumpTextShown = False self.toonJumped = False self.turnLeft = False self.turnRight = False self.leavingTrampoline = False self.toonVelocity = 0.0 self.topHeight = 0.0 self.lastPeak = 0.0 self.beginRoundInterval = None self.hopOnAnim = None self.hopOffAnim = None self.flashTextInterval = None self.numJellyBeans = PartyGlobals.TrampolineNumJellyBeans self.jellyBeanBonus = PartyGlobals.TrampolineJellyBeanBonus self.jellyBeanStartHeight = 20.0 self.jellyBeanStopHeight = 90.0 self.jellyBeanColors = [VBase4(1.0, 0.5, 0.5, 1.0), VBase4(0.5, 1.0, 0.5, 1.0), VBase4(0.5, 1.0, 1.0, 1.0), VBase4(1.0, 1.0, 0.4, 1.0), VBase4(0.4, 0.4, 1.0, 1.0), VBase4(1.0, 0.5, 1.0, 1.0)] delta = (self.jellyBeanStopHeight - self.jellyBeanStartHeight) / (self.numJellyBeans - 1) self.jellyBeanPositions = [ self.jellyBeanStartHeight + n * delta for n in xrange(self.numJellyBeans) ] self.doSimulateStep = False return def load(self): DistributedPartyTrampolineActivity.notify.debug('load') DistributedPartyActivity.load(self) self.loadModels() self.loadCollision() self.loadGUI() self.loadSounds() self.loadIntervals() self.activityFSM = TrampolineActivityFSM(self) self.activityFSM.request('Idle') self.animFSM = TrampolineAnimFSM(self) self.setBestHeightInfo('', 0) def loadModels(self): self.tramp = self.root.attachNewNode(self.uniqueName('tramp')) self.trampActor = Actor('phase_13/models/parties/trampoline_model', {'emptyAnim': 'phase_13/models/parties/trampoline_anim'}) self.trampActor.reparentTo(self.tramp) if self.texture: reskinNode = self.tramp.find('**/trampoline/__Actor_modelRoot/-GeomNode') reskinNode.setTexture(loader.loadTexture(self.texture), 100) self.surface = NodePath(self.uniqueName('trampSurface')) self.surface.reparentTo(self.tramp) self.surface.setZ(self.trampHeight) self.trampActor.controlJoint(self.surface, 'modelRoot', 'trampoline_joint1') self.sign.setPos(PartyGlobals.TrampolineSignOffset) self.beans = [ loader.loadModelCopy('phase_4/models/props/jellybean4') for i in xrange(self.numJellyBeans) ] for bean in self.beans: bean.find('**/jellybean').setP(-35.0) bean.setScale(3.0) bean.setTransparency(True) bean.reparentTo(self.tramp) bean.stash() self.beans[-1].setScale(8.0) def loadCollision(self): collTube = CollisionTube(0.0, 0.0, 0.0, 0.0, 0.0, 6.0, 5.4) collTube.setTangible(True) self.trampolineCollision = CollisionNode(self.uniqueName('TrampolineCollision')) self.trampolineCollision.addSolid(collTube) self.trampolineCollision.setCollideMask(OTPGlobals.CameraBitmask | OTPGlobals.WallBitmask) self.trampolineCollisionNP = self.tramp.attachNewNode(self.trampolineCollision) collSphere = CollisionSphere(0.0, 0.0, 0.0, 7.0) collSphere.setTangible(False) self.trampolineTrigger = CollisionNode(self.uniqueName('TrampolineTrigger')) self.trampolineTrigger.addSolid(collSphere) self.trampolineTrigger.setIntoCollideMask(OTPGlobals.WallBitmask) self.trampolineTriggerNP = self.tramp.attachNewNode(self.trampolineTrigger) self.accept('enter%s' % self.uniqueName('TrampolineTrigger'), self.onTrampolineTrigger) def loadGUI(self): self.gui = loader.loadModel('phase_13/models/parties/trampolineGUI') self.gui.reparentTo(base.a2dTopLeft) self.gui.setPos(0.115, 0, -1) self.gui.hide() self.toonIndicator = self.gui.find('**/trampolineGUI_MovingBar') jumpLineLocator = self.gui.find('**/jumpLine_locator') guiBean = self.gui.find('**/trampolineGUI_GreenJellyBean') self.gui.find('**/trampolineGUI_GreenJellyBean').stash() self.guiBeans = [ guiBean.instanceUnderNode(jumpLineLocator, self.uniqueName('guiBean%d' % i)) for i in xrange(self.numJellyBeans) ] self.guiBeans[-1].setScale(1.5) heightTextNode = TextNode(self.uniqueName('TrampolineActivity.heightTextNode')) heightTextNode.setFont(ToontownGlobals.getSignFont()) heightTextNode.setAlign(TextNode.ALeft) heightTextNode.setText('0.0') heightTextNode.setShadow(0.05, 0.05) heightTextNode.setShadowColor(0.0, 0.0, 0.0, 1.0) heightTextNode.setTextColor(1.0, 1.0, 1.0, 1.0) self.heightText = jumpLineLocator.attachNewNode(heightTextNode) self.heightText.setX(0.15) self.heightText.setScale(0.1) self.heightText.setAlphaScale(0.0) self.quitEarlyButtonModels = loader.loadModel('phase_3.5/models/gui/inventory_gui') quitEarlyUp = self.quitEarlyButtonModels.find('**//InventoryButtonUp') quitEarlyDown = self.quitEarlyButtonModels.find('**/InventoryButtonDown') quitEarlyRollover = self.quitEarlyButtonModels.find('**/InventoryButtonRollover') self.quitEarlyButton = DirectButton(parent=base.a2dTopRight, relief=None, text=TTLocalizer.PartyTrampolineQuitEarlyButton, text_fg=(1, 1, 0.65, 1), text_pos=(0, -0.23), text_scale=0.7, image=(quitEarlyUp, quitEarlyDown, quitEarlyRollover), image_color=(1, 0, 0, 1), image_scale=(20, 1, 11), pos=(-0.183, 0, -0.4), scale=0.09, command=self.leaveTrampoline) self.quitEarlyButton.stash() self.flashText = OnscreenText(text='', pos=(0.0, -0.45), scale=0.2, fg=(1.0, 1.0, 0.65, 1.0), align=TextNode.ACenter, font=ToontownGlobals.getSignFont(), mayChange=True) self.timer = PartyUtils.getNewToontownTimer() self.timer.posInTopRightCorner() return def loadSounds(self): self.jellyBeanSound = base.loader.loadSfx('phase_4/audio/sfx/sparkly.ogg') self.boingSound = base.loader.loadSfx('phase_4/audio/sfx/target_trampoline_2.ogg') self.whistleSound = base.loader.loadSfx('phase_4/audio/sfx/AA_sound_whistle.ogg') def loadIntervals(self): def prepareHeightText(): self.heightText.node().setText(TTLocalizer.PartyTrampolineGetHeight % int(self.toon.getZ())) self.heightText.setZ(self.indicatorFactor * self.toon.getZ() + self.heightTextOffset) self.heightTextInterval = Sequence(Func(prepareHeightText), LerpFunc(self.heightText.setAlphaScale, fromData=1.0, toData=0.0, duration=1.0)) def unload(self): DistributedPartyTrampolineActivity.notify.debug('unload') if self.hopOnAnim and self.hopOnAnim.isPlaying(): self.hopOnAnim.finish() if self.hopOffAnim and self.hopOffAnim.isPlaying(): self.hopOffAnim.finish() if self.beginRoundInterval and self.beginRoundInterval.isPlaying(): self.beginRoundInterval.finish() if self.flashTextInterval and self.flashTextInterval.isPlaying(): self.flashTextInterval.finish() if self.heightTextInterval and self.heightTextInterval.isPlaying(): self.heightTextInterval.finish() self.timer.stop() DistributedPartyActivity.unload(self) taskMgr.remove(self.uniqueName('TrampolineActivity.updateTask')) taskMgr.remove(self.uniqueName('TrampolineActivity.remoteUpdateTask')) self.ignoreAll() del self.heightTextInterval del self.beginRoundInterval del self.hopOnAnim del self.hopOffAnim del self.flashTextInterval if hasattr(self, 'beanAnims'): self.cleanupJellyBeans() self.quitEarlyButton.destroy() del self.quitEarlyButton del self.gui del self.activityFSM del self.animFSM return def setBestHeightInfo(self, toonName, height): self.bestHeightInfo = (toonName, height) DistributedPartyTrampolineActivity.notify.debug('%s has the best height of %d' % (toonName, height)) if height > 0: self.setSignNote(TTLocalizer.PartyTrampolineBestHeight % self.bestHeightInfo) else: self.setSignNote(TTLocalizer.PartyTrampolineNoHeightYet) def leaveTrampoline(self): if self.toon != None and self.toon.doId == base.localAvatar.doId: self._showFlashMessage(TTLocalizer.PartyTrampolineTimesUp) self.leavingTrampoline = True self.timer.reset() self.trampB = self.leavingTrampB self.ignore('control') self.quitEarlyButton.stash() self.gui.hide() return def requestAnim(self, request): self.animFSM.request(request) def b_requestAnim(self, request): self.requestAnim(request) self.sendUpdate('requestAnim', [request]) def requestAnimEcho(self, request): if self.toon != None and self.toon.doId != base.localAvatar.doId: self.requestAnim(request) return def removeBeans(self, beansToRemove): for i in beansToRemove: height, bean, guiBean, beanAnim = self.beanDetails[i] guiBean.stash() if i in self.beansToCollect: self.beansToCollect.remove(i) else: self.notify.warning('removeBeans avoided a crash, %d not in self.beansToCollect' % i) self.poofBean(bean, beanAnim) def b_removeBeans(self, beansToRemove): self.removeBeans(beansToRemove) self.sendUpdate('removeBeans', [beansToRemove]) def removeBeansEcho(self, beansToRemove): if self.toon != None and self.toon.doId != base.localAvatar.doId: self.removeBeans(beansToRemove) return def joinRequestDenied(self, reason): DistributedPartyActivity.joinRequestDenied(self, reason) self.showMessage(TTLocalizer.PartyActivityDefaultJoinDeny) base.cr.playGame.getPlace().fsm.request('walk') def exitRequestDenied(self, reason): DistributedPartyActivity.exitRequestDenied(self, reason) self.showMessage(TTLocalizer.PartyActivityDefaultExitDeny) def setState(self, newState, timestamp): DistributedPartyTrampolineActivity.notify.debug('setState( newState=%s, ... )' % newState) DistributedPartyActivity.setState(self, newState, timestamp) self.activityFSM.request(newState) def startIdle(self): DistributedPartyTrampolineActivity.notify.debug('startIdle') def finishIdle(self): DistributedPartyTrampolineActivity.notify.debug('finishIdle') def startRules(self): DistributedPartyTrampolineActivity.notify.debug('startRules') if self.doJellyBeans: self.setupJellyBeans() if self.toon != None and self.toon.doId == base.localAvatar.doId: self.acquireToon() return def startActive(self): DistributedPartyTrampolineActivity.notify.debug('startActive') if self.toon != None and self.toon.doId == base.localAvatar.doId: base.setCellsActive(base.bottomCells, True) self.accept('arrow_left', self.onLeft) self.accept('arrow_left-up', self.onLeftUp) self.accept('arrow_right', self.onRight) self.accept('arrow_right-up', self.onRightUp) self.beginRoundInterval = Sequence(Func(self._showFlashMessage, TTLocalizer.PartyTrampolineReady), Wait(1.2), Func(self.flashMessage, TTLocalizer.PartyTrampolineGo), Func(self.beginRound)) self.beginRoundInterval.start() return def finishActive(self): DistributedPartyTrampolineActivity.notify.debug('finishActive') if self.doJellyBeans: self.cleanupJellyBeans() def setupJellyBeans(self): self.beanAnims = [] self.beansToCollect = [] self.beanDetails = [] self.numBeansCollected = 0 for i in xrange(self.numJellyBeans): bean = self.beans[i] guiBean = self.guiBeans[i] height = self.jellyBeanPositions[i] color = random.choice(self.jellyBeanColors) bean.find('**/jellybean').setColor(color) if self.toon.doId == base.localAvatar.doId: bean.setAlphaScale(1.0) else: bean.setAlphaScale(0.5) guiBean.setColor(color) bean.setZ(height + self.toon.getHeight() + self.beanOffset) guiBean.setZ(height * self.indicatorFactor + self.guiBeanOffset) bean.setH(0.0) bean.unstash() guiBean.unstash() beanAnim = bean.hprInterval(1.5, VBase3((i % 2 * 2 - 1) * 360.0, 0.0, 0.0)) beanAnim.loop() self.beanAnims.append(beanAnim) self.beanDetails.append((height, bean, guiBean, beanAnim)) self.beansToCollect = range(self.numJellyBeans) def cleanupJellyBeans(self): for bean in self.beans: bean.stash() for guiBean in self.guiBeans: guiBean.stash() if hasattr(self, 'beanAnims'): for beanAnim in self.beanAnims: beanAnim.finish() del self.beanAnims del self.beansToCollect def beginRound(self): base.playSfx(self.whistleSound) self.timer.setTime(PartyGlobals.TrampolineDuration) self.timer.countdown(PartyGlobals.TrampolineDuration) self.timer.show() self.gui.show() self.quitEarlyButton.unstash() self.notify.debug('Accepting contorl') self.accept('control', self.onJump) self.notify.debug('setting simulate step to true') self.doSimulateStep = True def acquireToon(self): self.toon.disableSmartCameraViews() self.toon.stopUpdateSmartCamera() camera.wrtReparentTo(render) self.toon.dropShadow.reparentTo(hidden) self.toon.startPosHprBroadcast(period=0.2) self.toonAcceleration = 0.0 self.toonVelocity = 0.0 self.topHeight = 0.0 self.trampB = self.normalTrampB self.leavingTrampoline = False self.hopOnAnim = Sequence(Func(self.toon.b_setAnimState, 'jump', 1.0), Wait(0.4), PartyUtils.arcPosInterval(0.75, self.toon, Point3(0.0, 0.0, self.trampHeight), 5.0, self.tramp), Func(self.postHopOn)) self.hopOnAnim.start() def postHopOn(self): self.toon.setH(self.toon.getH() + 90.0) self.toon.dropShadow.reparentTo(self.surface) self.timeLeftToSimulate = 0.0 self.doSimulateStep = False taskMgr.add(self.updateTask, self.uniqueName('TrampolineActivity.updateTask')) base.setCellsActive(base.leftCells, False) base.setCellsActive(base.bottomCells, False) DistributedPartyActivity.startRules(self) def releaseToon(self): self._hideFlashMessage() self.ignore('arrow_left') self.ignore('arrow_left-up') self.ignore('arrow_right') self.ignore('arrow_right-up') taskMgr.remove(self.uniqueName('TrampolineActivity.updateTask')) self.hopOffAnim = Sequence(self.toon.hprInterval(0.5, VBase3(-90.0, 0.0, 0.0), other=self.tramp), Func(self.toon.b_setAnimState, 'jump', 1.0), Func(self.toon.dropShadow.reparentTo, hidden), Wait(0.4), PartyUtils.arcPosInterval(0.75, self.toon, self.hopOffPos, 5.0, self.tramp), Func(self.postHopOff)) self.hopOffAnim.start() def postHopOff(self): base.setCellsActive(base.leftCells, True) self.timer.stop() self.timer.hide() self.toon.dropShadow.reparentTo(self.toon.getShadowJoint()) self.toon.dropShadow.setAlphaScale(1.0) self.toon.dropShadow.setScale(1.0) self.b_requestAnim('Off') camera.reparentTo(base.localAvatar) base.localAvatar.startUpdateSmartCamera() base.localAvatar.enableSmartCameraViews() base.localAvatar.setCameraPositionByIndex(base.localAvatar.cameraIndex) place = base.cr.playGame.getPlace() if self.doJellyBeans: self.sendUpdate('awardBeans', [self.numBeansCollected, int(self.topHeight)]) if int(self.topHeight) > self.bestHeightInfo[1]: self.sendUpdate('reportHeightInformation', [int(self.topHeight)]) self.d_toonExitDemand() def onTrampolineTrigger(self, collEntry): if self.activityFSM.state == 'Idle' and self.toon == None and base.cr.playGame.getPlace().fsm.getCurrentState().getName() == 'walk': base.cr.playGame.getPlace().fsm.request('activity') self.d_toonJoinRequest() else: self.flashMessage(TTLocalizer.PartyTrampolineActivityOccupied, duration=2.0) return def onJump(self): self.notify.debug('got onJump') if self.toon != None and self.toon.getZ() < self.trampHeight: self.toonJumped = True self.b_requestAnim('Jump') else: self.notify.debug('z is less than tramp height') return def onLeft(self): self.turnLeft = True def onLeftUp(self): self.turnLeft = False def onRight(self): self.turnRight = True def onRightUp(self): self.turnRight = False def handleToonJoined(self, toonId): DistributedPartyTrampolineActivity.notify.debug('handleToonJoined') self.toon = self.getAvatar(toonId) if self.toon != None and not self.toon.isEmpty(): self.oldJumpSquatPlayRate = self.toon.getPlayRate('jump-squat') self.oldJumpLandPlayRate = self.toon.getPlayRate('jump-land') self.toon.setPlayRate(2.5, 'jump-squat') self.toon.setPlayRate(2.0, 'jump-land') self.turnLeft = False self.turnRight = False self.activityFSM.request('Rules') if self.toon.doId != base.localAvatar.doId: taskMgr.add(self.remoteUpdateTask, self.uniqueName('TrampolineActivity.remoteUpdateTask')) else: self.notify.warning('handleToonJoined could not get toon %d' % toonId) return def handleToonExited(self, toonId): DistributedPartyTrampolineActivity.notify.debug('handleToonExited') if self.toon != None: if self.toon.doId != base.localAvatar.doId: taskMgr.remove(self.uniqueName('TrampolineActivity.remoteUpdateTask')) self.surface.setZ(self.trampHeight) self.toon.setPlayRate(self.oldJumpSquatPlayRate, 'jump-squat') self.toon.setPlayRate(self.oldJumpLandPlayRate, 'jump-land') self.toon = None return def handleToonDisabled(self, toonId): DistributedPartyTrampolineActivity.notify.debug('handleToonDisabled') DistributedPartyTrampolineActivity.notify.debug('avatar ' + str(toonId) + ' disabled') if base.localAvatar.doId == toonId: self.releaseToon() def handleRulesDone(self): self.sendUpdate('toonReady') self.finishRules() def getTitle(self): if self.doJellyBeans: return TTLocalizer.PartyTrampolineJellyBeanTitle elif self.doTricks: return TTLocalizer.PartyTrampolineTricksTitle else: return DistributedPartyActivity.getTitle(self) def getInstructions(self): return TTLocalizer.PartyTrampolineActivityInstructions def updateTask(self, task): z = self.toon.getZ() dt = globalClock.getDt() if self.doSimulateStep: self.timeLeftToSimulate += dt while self.timeLeftToSimulate >= self.stepDT: z, a = self.simulateStep(z) self.timeLeftToSimulate -= self.stepDT self.toon.setZ(z) if z <= self.trampHeight: self.surface.setZ(z) else: self.surface.setZ(self.trampHeight) self.toonIndicator.setZ((z - self.trampHeight) * self.indicatorFactor) if self.turnLeft: self.toon.setH(self.toon.getH() + self.turnFactor * dt) if self.turnRight: self.toon.setH(self.toon.getH() - self.turnFactor * dt) currentPos = base.camera.getPos(self.toon) vec = self.targetCameraPos - currentPos newPos = currentPos + vec * (dt * self.cameraSpeed) base.camera.setPos(self.toon, newPos) base.camera.lookAt(self.toon) #if z > self.trampHeight: # heightFactor = 1.0 - min(1.0, (z - self.trampHeight) / self.dropShadowCutoff) # self.toon.dropShadow.setAlphaScale(heightFactor) # self.toon.dropShadow.setScale(max(0.1, heightFactor)) #else: # self.toon.dropShadow.setAlphaScale(1.0) # self.toon.dropShadow.setScale(1.0) if self.leavingTrampoline and z < self.trampHeight and abs(a) < 0.1: self.releaseToon() return Task.cont def simulateStep(self, z): if z >= self.trampHeight: a = self.g self.toonJumped = False else: a = self.g + self.trampK * (self.trampHeight - z) - self.trampB * self.toonVelocity if self.toonJumped: if self.lastPeak > self.earlyJumpThreshold or self.toonVelocity >= -300000.0: a += self.jumpBoost if self.lastPeak < self.beginningBoostThreshold: a += self.beginningBoost lastVelocity = self.toonVelocity self.toonVelocity += a * self.stepDT if lastVelocity > 0.0 and self.toonVelocity <= 0.0: topOfJump = True bottomOfJump = False elif lastVelocity < 0.0 and self.toonVelocity >= 0.0: topOfJump = False bottomOfJump = True else: topOfJump = False bottomOfJump = False newZ = z + self.toonVelocity * self.stepDT if newZ > self.topHeight: self.topHeight = newZ if self.doJellyBeans: self.collectJellyBeans(newZ) if topOfJump: self.lastPeak = newZ if newZ >= self.minHeightForText: self.heightTextInterval.start() if topOfJump: if newZ > self.trampHeight + 20.0: self.b_requestAnim('Falling') elif self.animFSM.state == 'Jump': self.b_requestAnim('Falling') if newZ <= self.trampHeight and z > self.trampHeight: if self.animFSM.state == 'Falling': self.b_requestAnim('Land') elif self.animFSM.state != 'Neutral': self.b_requestAnim('Neutral') if bottomOfJump and a > self.boingThreshold: base.playSfx(self.boingSound) return (newZ, a) def collectJellyBeans(self, z): beansToRemove = [] for i in self.beansToCollect: height = self.beanDetails[i][0] if height <= z: beansToRemove.append(i) if len(beansToRemove) > 0: base.playSfx(self.jellyBeanSound) self.numBeansCollected += len(beansToRemove) self.b_removeBeans(beansToRemove) def remoteUpdateTask(self, task): if self.toon != None and not self.toon.isEmpty(): z = self.toon.getZ() if z <= self.trampHeight: self.surface.setZ(z) else: self.surface.setZ(self.trampHeight) return Task.cont def poofBean(self, bean, beanAnim): if bean == None: self.notify.warning('poofBean, returning immediately as bean is None') return if bean.isEmpty(): self.notify.warning('poofBean, returning immediately as bean is empty') return currentAlpha = bean.getColorScale()[3] currentScale = bean.getScale() poofAnim = Sequence(Parallel(LerpFunc(bean.setAlphaScale, fromData=currentAlpha, toData=0.0, duration=0.25), LerpFunc(bean.setScale, fromData=currentScale, toData=currentScale * 5.0, duration=0.25)), Func(bean.stash), Func(beanAnim.finish), Func(bean.setAlphaScale, currentAlpha), Func(bean.setScale, currentScale)) poofAnim.start() return def _showFlashMessage(self, message): if self.isDisabled(): return if self.flashTextInterval is not None and self.flashTextInterval.isPlaying(): self.flashTextInterval.finish() self.flashText.setText(message) self.flashText.setAlphaScale(1.0) self.flashText.unstash() return def _hideFlashMessage(self, duration = 0.0): if self.isDisabled(): pass self.flashTextInterval = Sequence(Wait(duration), LerpFunc(self.flashText.setAlphaScale, fromData=1.0, toData=0.0, duration=1.0), Func(self.flashText.stash)) self.flashTextInterval.start() def flashMessage(self, message, duration = 0.5): self._showFlashMessage(message) self._hideFlashMessage(duration)
class SocketServer(): def __init__(self, port, virtual_world, camera_mgr, sync_session): self.port = port self.virtual_world = virtual_world self.cam_mgr = camera_mgr self.task_mgr = virtual_world.taskMgr self.cManager = QueuedConnectionManager() self.cListener = QueuedConnectionListener(self.cManager, 0) self.cReader = QueuedConnectionReader(self.cManager, 0) self.cReader.setRawMode(True) self.cWriter = ConnectionWriter(self.cManager, 1) self.cWriter.setRawMode(True) self.tcpSocket = self.cManager.openTCPServerRendezvous(port, BACKLOG) self.cListener.addConnection(self.tcpSocket) self.activeSessions = {} self.connection_map = {} self.set_handlers() hostname = socket.gethostname() a, b, address_list = socket.gethostbyname_ex(hostname) self.ip = address_list[0] logging.info("Addresses %s" % address_list) logging.info("Server is running on ip: %s, port: %s" % (self.ip, self.port)) self.client_counter = 0 self.read_buffer = '' self.read_state = 0 self.read_body_length = 0 self.packet = SocketPacket() controller = virtual_world.getController() self.sync = Sync(self.task_mgr, controller, camera_mgr, sync_session) self.vv_id = None if sync_session: logging.info("Waiting for Sync Client!") self.showing_info = False virtual_world.accept("i", self.toggleInfo) self.sync_session = sync_session self.createInfoLabel() atexit.register(self.exit) def createInfoLabel(self): string = self.generateInfoString() self.info_label = OST(string, pos=(-1.3, -0.5), fg=(1, 1, 1, 1), bg=(0, 0, 0, 0.7), scale=0.05, align=TextNode.ALeft) self.info_label.hide() def generateInfoString(self, ): string = " IP:\t%s \n" % self.ip string += " PORT:\t%s \n" % self.port if self.sync_session: string += " MODE:\tSync Client\n" string += " VV ID:\t%s\n" % self.vv_id else: string += " MODE:\tAutomatic\n" cameras = self.cam_mgr.getCameras() num_cameras = len(cameras) for camera in cameras: id = camera.getId() type = camera.getTypeString() string += " Cam%s:\t%s\n" % (id, type) string += "\n" return string def set_handlers(self): self.task_mgr.add(self.connection_polling, "Poll new connections", -39) self.task_mgr.add(self.reader_polling, "Poll reader", -40) self.task_mgr.add(self.disconnection_polling, "PollDisconnections", -41) def connection_polling(self, taskdata): if self.cListener.newConnectionAvailable(): rendezvous = PointerToConnection() netAddress = NetAddress() newConn = PointerToConnection() if self.cListener.getNewConnection(rendezvous, netAddress, newConn): conn = newConn.p() self.cReader.addConnection(conn) # Begin reading connection conn_id = self.client_counter logging.info("New Connection from ip:%s, conn:%s" % (conn.getAddress(), conn_id)) self.connection_map[conn_id] = conn self.client_counter += 1 message = eVV_ACK_OK(self.ip, self.port, conn_id) self.sendMessage(message, conn) return Task.cont def reader_polling(self, taskdata): if self.cReader.dataAvailable(): datagram = NetDatagram( ) # catch the incoming data in this instance # Check the return value; if we were threaded, someone else could have # snagged this data before we did if self.cReader.getData(datagram): self.read_buffer = self.read_buffer + datagram.getMessage() while (True): if self.read_state == 0: if len(self.read_buffer) >= self.packet.header_length: bytes_consumed = self.packet.header_length self.packet.header = self.read_buffer[:bytes_consumed] self.read_body_length = self.packet.decode_header() self.read_buffer = self.read_buffer[bytes_consumed:] self.read_state = 1 else: break if self.read_state == 1: if len(self.read_buffer) >= self.read_body_length: bytes_consumed = self.read_body_length self.packet.data = self.read_buffer[:bytes_consumed] self.packet.offset = 0 self.read_body_length = 0 self.read_buffer = self.read_buffer[bytes_consumed:] self.read_state = 0 self.new_data_callback(self.packet) else: break return Task.cont def new_data_callback(self, packet): packet = copy.deepcopy(packet) message_type = packet.get_int() conn_id = packet.get_int() if message_type == VP_SESSION: conn = self.connection_map[conn_id] type = packet.get_char() pipeline = packet.get_char() logging.debug("Received VP_SESSION message from conn:%s, " \ "type=%s, pipeline=%s" %(conn_id, VP_TYPE[type], PIPELINE[pipeline])) self.newVPSession(conn, type, pipeline, conn_id) elif message_type == SYNC_SESSION: vv_id = packet.get_int() self.vv_id = vv_id string = self.generateInfoString() self.info_label.setText(string) conn = self.connection_map[conn_id] logging.debug("Received SYNC_SESSION message from conn:%s" % conn_id) self.newSyncSession(conn, conn_id, vv_id) logging.info("Sync client connected") elif message_type == VP_REQ_CAM_LIST: logging.debug("Received VP_REQ_CAM_LIST message from conn:%s" % conn_id) cameras = self.cam_mgr.getCameras() pipeline = self.activeSessions[conn_id].getPipeline() camera_type = None if pipeline == STATIC_PIPELINE: camera_type = VP_STATIC_CAMERA elif pipeline == PTZ_PIPELINE: camera_type = VP_ACTIVE_CAMERA cam_list = [] for camera in cameras: if camera_type == camera.getType() and not camera.hasSession(): cam_list.append(camera.getId()) message = eVV_CAM_LIST(self.ip, self.port, cam_list) conn = self.connection_map[conn_id] logging.debug("Sent VV_CAM_LIST message to conn:%s" % conn_id) self.sendMessage(message, conn) elif message_type == VP_REQ_IMG: cam_id = packet.get_int() frequency = packet.get_char() width = packet.get_int() height = packet.get_int() jpeg = packet.get_bool() data = (frequency, width, height, jpeg) camera = self.cam_mgr.getCameraById(cam_id) logging.debug("Received VV_REQ_IMG message from conn:%s" % conn_id) if camera and not camera.hasSession(): session = self.activeSessions[conn_id] session.addCamera(cam_id) camera.setSession(session, VP_BASIC, self.ip, self.port, data) else: if conn_id in self.activeSessions: self.activeSessions[conn_id].newMessage(message_type, packet) def newVPSession(self, conn, type, pipeline, conn_id): if type == VP_ADVANCED: camera_type = -1 if pipeline == STATIC_PIPELINE: camera_type = STATIC_CAMERA ## Change this to use a different static camera class elif pipeline == PTZ_PIPELINE: camera_type = ACTIVE_CAMERA if camera_type != -1: cam = self.cam_mgr.getAvailableCamera(camera_type) if cam: session = VPSession(conn_id, conn, self, VP, pipeline) session.addCamera(cam.getId()) self.activeSessions[conn_id] = session message = eVV_VP_ACK_OK(self.ip, self.port, cam.getId()) logging.debug("Sent VV_VP_ACK_OK message to conn:%s" % conn_id) self.sendMessage(message, conn) cam.setSession(session, type, self.ip, self.port) else: message = eVV_VP_ACK_FAILED(self.ip, self.port) logging.debug("Sent VV_VP_ACK_FAILED message to conn:%s" % conn_id) self.sendMessage(message, conn) else: message = eVV_VP_ACK_FAILED(self.ip, self.port) logging.debug("Sent VV_VP_ACK_FAILED message to conn:%s" % conn_id) self.sendMessage(message, conn) def newSyncSession(self, conn, conn_id, vv_id): session = SyncSession(conn_id, conn, self, SYNC) self.sync.setSession(session, vv_id, self.ip, self.port) self.activeSessions[conn_id] = session message = eVV_SYNC_ACK(self.ip, self.port, vv_id) logging.debug("Sent VV_SYNC_ACK message to conn:%s" % conn_id) self.sendMessage(message, conn) def sendMessage(self, message, conn): self.cWriter.send(message, conn) def disconnection_polling(self, taskdata): if (self.cManager.resetConnectionAvailable()): connectionPointer = PointerToConnection() self.cManager.getResetConnection(connectionPointer) lostConnection = connectionPointer.p() for session in self.activeSessions.values(): if session.conn == lostConnection: logging.info("Lost Connection from ip:%s, conn:%s" % (session.client_address, session.conn_id)) conn_id = session.conn_id if session.getSessionType() == VP: cameras = session.getCameras() for cam_id in cameras: camera = self.cam_mgr.getCameraById(cam_id) camera.clearSession() del self.activeSessions[conn_id] del self.connection_map[conn_id] break self.cManager.closeConnection(lostConnection) return Task.cont def toggleInfo(self): if self.showing_info: self.info_label.hide() self.showing_info = False else: self.info_label.show() self.showing_info = True def exit(self): for connection in self.connection_map.values(): self.cReader.removeConnection(connection) self.cManager.closeConnection(self.tcpSocket) self.tcpSocket.getSocket().Close()
class Menu: def __init__(self): self.count = 0 self.x = {} self.y = {} self.z = {} self.Gstart = 0 self.slist = False self.nlist = False self.connected = False self.music = loader.loadSfx("sounds/music/menu.wav") self.engine = loader.loadSfx("sounds/sfx/engine5.wav") self.engine.setLoop(True) self.engine.setVolume(.7) self.music.setLoop(True) self.music.setVolume(.7) self.music.play() self.name = "" self.font = loader.loadFont("cmr12.egg") self.myImage = OnscreenImage(image='bg.jpg', pos=(0, 0, 0), scale=(2, 2, 1)) self.myImage.setTransparency(TransparencyAttrib.MAlpha) self.welcome = OnscreenText( text="Welcome to 3d multiplayer Racing Game", fg=Vec4(1, 1, 1, 1), shadow=Vec4(0, 0, 0, 1), scale=0.10, pos=(0, .8, 0)) self.bk_text = " " self.textObject = OnscreenText(text=self.bk_text, pos=(0.95, -0.95), scale=0.07, fg=(1, 0.5, 0.5, 0), align=TextNode.ACenter, mayChange=1, font=self.font, shadow=Vec4(0, 0, 0, 1), bg=(1, 1, 1, .2)) self.b = DirectEntry(scale=.05, command=self.setText, initialText="Enter your name", numLines=1, focus=0, focusInCommand=self.clearText, entryFont=self.font, width=20, pos=(-0.5, 0, 0), borderWidth=(0.5, 0.5), color=(1, 1, 1, 0.5), autoCapitalize=1) self.b.setTransparency(TransparencyAttrib.MDual) def setText(self, textEntered): self.name = textEntered cl.SetName(self.name) self.textObject.setText("Welcome " + textEntered) self.client() def createDirectlist(self): numItemsVisible = 4 itemHeight = 0.11 myScrolledList = DirectScrolledList( decButton_pos=(0.35, 0, 0.53), decButton_text="Dec", decButton_text_scale=0.04, decButton_borderWidth=(0.005, 0.005), incButton_pos=(0.35, 0, -0.02), incButton_text="Inc", incButton_text_scale=0.04, incButton_borderWidth=(0.005, 0.005), frameSize=(0.0, 0.7, -0.05, 0.59), frameColor=(1, 0, 0, 0.5), pos=(-1, 0, 0), numItemsVisible=numItemsVisible, forceHeight=itemHeight, itemFrame_frameSize=(-0.2, 0.2, -0.37, 0.11), itemFrame_pos=(0.35, 0, 0.4), ) return myScrolledList def clearText(self): self.b['color'] = Vec4(1, 1, 1, 1) self.b.enterText('') def client(self): self.b.destroy() self.textObject['fg'] = Vec4(1, 1, 1, 1) self.refresh = DirectButton(text=("", "", "", "disabled"), scale=.05, command=self.refresh, pos=(0.95, -0.95, 0), image="refresh.png", image_scale=2) self.refresh.setTransparency(TransparencyAttrib.MAlpha) def refresh(self): if self.slist: self.slist.destroy() if self.nlist: self.nlist.destroy() if self.connected: self.getMembers() else: for k, v in cl.servers.iteritems(): self.addserver(k, v) def addserver(self, k, v): print "inside addserver()" self.slist = self.createDirectlist() self.x[self.count] = k self.y[self.count] = v self.z[self.count] = DirectButton(text=v, scale=.05, command=self.connectServer, extraArgs=str(self.count)) self.slist.addItem(self.z[self.count]) self.count = self.count + 1 def clearServers(self): for i in range(0, self.count): self.z[i].destroy() self.slist.destroy() self.count = 0 def connectServer(self, count): #print count #print self.x[int(count)] self.slist.destroy() self.connected = True self.clearServers() cl.connectServer(str(self.x[int(count)])) self.getMembers() def getMembers(self): self.nlist = self.createDirectlist() cl.RequestServer() x = int(cl.getTotalUsers()) cl.RequestServer() cl.getUsers() for i in range(0, x): l = cl.getInput(1) k = cl.getInput(int(l)) l = DirectLabel(text=str(k), text_scale=0.05) self.nlist.addItem(l) if x > 1: self.start = DirectButton(text=("", "", "", "disabled"), scale=.05, command=self.destroy, pos=(0.2, -0.95, 0), image="start.jpg", image_scale=2) self.start.setTransparency(TransparencyAttrib.MAlpha) cl.ExitReqServer() #self.c.RequestServer() #self.c.getTotalUsers() #self.c.getTotalUsers(s) def sendY(self, Y): cl.sendY(Y) def sendH(self, H): cl.sendH(H) def destroy(self): self.Gstart = 1 self.nlist.destroy() self.myImage.destroy() self.welcome.destroy() self.b.destroy() self.textObject.destroy() self.start.destroy() self.start.destroy() self.refresh.destroy() self.self = None return
class DebugOptions(DirectObject): def __init__(self, parent): self.parent = parent self.textPlayerPos = OnscreenText(text = '', parent=base.a2dTopLeft, pos = (0, -0.1), scale = 0.04,fg=(1, 1, 1, 1),align=TextNode.ALeft) self.showFps = True base.setFrameRateMeter(True) self.ambientLight = True self.parent.alight.setColor(VBase4(0.43, 0.43, 0.43, 1.0)) self.flashlightFrustum = False self.autoShader = True render.setShaderAuto() self.playerPos = True taskMgr.add(self.refreshPlayerPos, 'RefreshPlayerPosTask') self.textPlayerPos.reparentTo(base.a2dTopLeft) self.bloom = False self.blur = False self.ao = False self.walls = True #spotlightpanel self.spot_light_panel = SpotlightPanel(self, self.parent.player.slight) base.accept('f1', self.toggleFps) base.accept('f2', self.toggleAmbientLight) base.accept('f3', self.toggleFlashlightFrustum) base.accept('f4', self.parent.player.getDamage) base.accept('f5', self.toggleAutoShader) base.accept('f6', self.togglePlayerPos) base.accept('f7', self.toggleBloom) base.accept('f8', self.toggleBlur) base.accept('f9', self.toggleAO) base.accept('f10', self.toggleWalls) base.accept('f11', render.analyze) base.accept('f12', self.debugPrint) def toggleFps(self): if self.showFps == False: self.showFps = True base.setFrameRateMeter(True) else: self.showFps = False base.setFrameRateMeter(False) def toggleAmbientLight(self): if self.ambientLight == False: self.ambientLight = True self.parent.alight.setColor(VBase4(0.43, 0.43, 0.43, 1.0)) else: self.ambientLight = False self.parent.alight.setColor(VBase4(0.03, 0.03, 0.03, 1.0)) def toggleFlashlightFrustum(self): if self.flashlightFrustum == False: self.flashlightFrustum = True self.parent.slight.showFrustum() else: self.flashlightFrustum = False self.parent.slight.hideFrustum() def toggleAutoShader(self): if self.autoShader == False: self.autoShader = True render.setShaderAuto() else: self.autoShader = False render.setShaderOff() def toggleWalls(self): if self.walls == False: self.walls = True self.parent.level.wall_node.reparentTo(self.parent.level.node) else: self.walls = False self.parent.level.wall_node.detachNode() def togglePlayerPos(self): if self.playerPos == False: self.playerPos = True taskMgr.add(self.refreshPlayerPos, 'RefreshPlayerPosTask') self.textPlayerPos.reparentTo(base.a2dTopLeft) else: self.playerPos = False taskMgr.remove('RefreshPlayerPosTask') self.textPlayerPos.detachNode() def toggleBloom(self): if self.bloom == False: self.bloom = True self.parent.filters.setBloom() else: self.bloom = False self.parent.filters.delBloom() def toggleBlur(self): if self.blur == False: self.blur = True self.parent.filters.setBlurSharpen() else: self.blur = False self.parent.filters.delBlurSharpen() def toggleAO(self): if self.ao == False: self.ao = True self.parent.filters.setAmbientOcclusion() else: self.ao = False self.parent.filters.delAmbientOcclusion() def refreshPlayerPos(self, task): px, py, pz = self.parent.player.node.getPos() self.textPlayerPos.setText('Player pos: (%0.3f, %0.3f, %0.3f)' % (px, py, pz)) return task.cont def debugPrint(self): print taskMgr
class Connect4: def __init__(self, p_base): self.base = p_base self.render = p_base.render # Keyboard inputs map self.keyMap = {"left": False, "right": False, "down": False, "drop": False} # Global parameters self.player = 1 self.speed = 15 self.movement_V = False self.movement_H = False self.axes_H = [-3.6, -2.4, -1.2, 0, 1.2, 2.4, 3.6] self.axes_V = [0.25, -1.0, -2.25, -3.5, -4.75, -6] self.column = 3 self.line = 5 self.quit_game_bool = False self.round = 0 # Initialization of audio coin self.audio_coin = self.base.loader.loadMusic("connect4/audio/coin.ogg") # Initialization of the table self.table = self.base.loader.loadModel("connect4/models/table") self.table.reparentTo(self.render) self.table.setScale(2, 2, 2) self.table.setHpr(90, 0, 0) self.table_anim_start = self.table.posInterval(3, Point3(0, 30, -8), startPos=Point3(0, 0, -8)) self.table_anim_end = self.table.posInterval(3, Point3(0, 0, -8), startPos=Point3(0, 30, -8)) # Initialization of the grid self.grid = self.base.loader.loadModel("connect4/models/grid") self.grid.reparentTo(self.render) self.grid.setColor(0.1, 0.2, 0.8, 1.0) self.grid.setHpr(90, 0, 0) self.grid.setScale(0.6, 0.6, 0.625) self.grid_anim_start = self.grid.posInterval(3, Point3(3.6, 30, -6), startPos=Point3(3.6, 30, 0)) self.grid_anim_end = self.grid.posInterval(3, Point3(3.6, 30, 0), startPos=Point3(3.6, 30, -6)) self.gridContent = np.zeros(6 * 7) # Initialization of the discs self.discs = [] self.nb_discs = 44 for i in range(0, self.nb_discs): disc = self.base.loader.loadModel("connect4/models/disc") disc.reparentTo(self.render) if i % 2 == 0: color_disc = Disc(i, disc, 1.0, 0.0, 0.0) else: color_disc = Disc(i, disc, 1.0, 1.0, 0.0) self.discs.append(color_disc) self.first_disc_anim = self.discs[self.round].disc.posInterval(3, Point3(0, 30, 1.5), startPos=Point3(0, 0, 8)) # Initialization of start sequences self.init_sequence = Parallel(self.table_anim_start, self.grid_anim_start, self.first_disc_anim, name="p_start") self.init_sequence.start() # Initialization of keys self.base.accept("arrow_left", self.updateKeyMap, ["left", True]) self.base.accept("arrow_left-up", self.updateKeyMap, ["left", False]) self.base.accept("arrow_right", self.updateKeyMap, ["right", True]) self.base.accept("arrow_right-up", self.updateKeyMap, ["right", False]) self.base.accept("arrow_down", self.updateKeyMap, ["down", True]) self.base.accept("arrow_down-up", self.updateKeyMap, ["down", False]) self.base.accept("space", self.updateKeyMap, ["drop", True]) self.base.accept("space-up", self.updateKeyMap, ["drop", False]) # Initialization of winning cases self.results = [] with open("connect4/csv/cases.csv") as csvfile: reader = csv.reader(csvfile, quoting=csv.QUOTE_NONNUMERIC) for row in reader: self.results.append(row) # Initialization of fonts self.font = self.base.loader.loadFont("connect4/font/Roboto-Medium.ttf") self.font.setPixelsPerUnit(60) # Initialization of the victory text self.text_victory = OnscreenText(text='', pos=(1.4, -0.8), scale=0.1) self.text_victory.setFg((0, 0, 0, 1)) self.text_victory.setBg((1, 1, 1, 0)) self.text_victory.setShadow((0.5, 0.5, 0.5, 1)) # Initialization of buttons self.load_game_button = DirectButton(text="Load", pos=(-1.5, 0, 0.75), frameSize=(-3, 3, -0.5, 1), scale=.1, text_scale=0.9, command=self.load_game) self.new_game_button = DirectButton(text="New game", pos=(-1.5, 0, 0.9), frameSize=(-3, 3, -0.5, 1), scale=.1, text_scale=0.9, command=self.new_game) self.button_changed = False self.save_game_button = DirectButton(text="Save", pos=(-1.5, 0, 0.6), frameSize=(-3, 3, -0.5, 1), scale=.1, text_scale=0.9, command=self.save_game) self.quit_game_button = DirectButton(text="Quit", pos=(-1.5, 0, -0.95), frameSize=(-3, 3, -0.5, 1), scale=.1, text_scale=0.9, command=self.quit_game) self.hand_control_button = DirectButton(text="Activer le contrôle \n visuel", pos=(1.5, 0, -0.9), frameSize=(-3, 3, -1, 0.8), scale=.1, text_scale=0.5, command=self.activate_hand_control) # Mode # (mode 0 : default mode) # (mode 1 : hand control mode) self.mode = 0 self.disc_caught = -1 self.disc_dropped = -1 # Initialization of the right hand self.right_hand = self.base.loader.loadModel("connect4/models/hand") self.right_hand.reparentTo(self.render) self.right_hand.setPos(3.6, -20, 0) self.right_hand.setColor(0.88, 0.67, 0.41, 1.0) self.right_hand.setHpr(90, -90, 0) self.right_hand.setScale(0.2, 0.2, 0.2) # self.left_hand = self.base.loader.loadModel("connect4/models/hand") # self.left_hand.reparentTo(self.render) # self.left_hand.setPos(-3.6, -20, 0) # self.left_hand.setColor(0.88, 0.67, 0.41, 1.0) # self.left_hand.setHpr(90, -90, 180) # self.left_hand.setScale(0.2, 0.2, 0.2) def activate_hand_control(self): if self.mode == 0: self.mode = 1 self.hand_control_button.setText("Désactiver le contrôle \n visuel") self.right_hand.setPos(3.6, 30, 0) self.new_game() # self.left_hand.setPos(-3.6, 20, 0) else: self.mode = 0 self.hand_control_button.setText("Activer le contrôle \n visuel") self.right_hand.setPos(3.6, -20, 0) self.new_game() # self.left_hand.setPos(-3.6, -20, 0) def updateKeyMap(self, key, state): """ Function that updates the input map """ self.keyMap[key] = state def load_game(self): """ Load game functions used for load game button """ print("Connect 4 > Load a game") f1 = open("connect4/safeguard/safeguard.txt", "r") last_line = f1.readlines()[-1] f1.close() last_line_list = last_line.split(',') k = 0 p = 1 round = 0 for i in range(0, 42): col = i % 7 line = i // 7 if last_line_list[i] == '1': self.discs[k].disc.setPos(self.axes_H[col], 30, self.axes_V[line]) k += 2 round += 1 elif last_line_list[i] == '2': self.discs[p].disc.setPos(self.axes_H[col], 30, self.axes_V[line]) p += 2 round += 1 self.round = round self.discs[self.round].disc.setPos(0, 30, 1.5) self.gridContent = [int(j) for j in last_line_list] def new_game(self): """ New game functions used for new game button """ print("Connect 4 > New game") self.gridContent = np.zeros(6 * 7) self.round = 0 self.text_victory.setText('') if self.mode == 0: for i in range(0, 42): self.discs[i].disc.setPos(100, 100, 100) self.discs[self.round].disc.setPos(0, 30, 1.5) elif self.mode == 1: pos_xr = [-8.4, -7.2, -6.0, -12, -10.8, -9.6, -8.4, -7.2, -6.0, -12, -10.8, -9.6, -8.4, -7.2, -6.0, -12, -10.8, -9.6, -8.4, -7.2, -6.0] pos_xy = [8.4, 7.2, 6.0, 12, 10.8, 9.6, 8.4, 7.2, 6.0, 12, 10.8, 9.6, 8.4, 7.2, 6.0, 12, 10.8, 9.6, 8.4, 7.2, 6.0] pos_z = [-6.4, -6.4, -6.4, -5.2, -5.2, -5.2, -5.2, -5.2, -5.2, -4.0, -4.0, -4.0, -4.0, -4.0, -4.0, -2.8, -2.8, -2.8, -2.8, -2.8, -2.8] n = 0 p = 0 for i in range(0, 42): if i % 2 == 0: self.discs[i].disc.setPos(pos_xr[n], 30, pos_z[n]) n += 1 else: self.discs[i].disc.setPos(pos_xy[p], 30, pos_z[p]) p += 1 def save_game(self): """ Save game functions used for save game button """ print("Connect 4 > Save the game") grid = [int(j) for j in self.gridContent] grid_content_str = ','.join([str(elem) for elem in grid]) f = open("connect4/safeguard/safeguard.txt", "a") f.write(grid_content_str + "\n") f.close() def quit_game(self): """ Quit game functions used for quit game button """ print("Connect 4 > Quit the game") for i in range(0, self.nb_discs): self.discs[i].disc.removeNode() self.grid.removeNode() self.table.removeNode() self.new_game_button.destroy() self.save_game_button.destroy() self.load_game_button.destroy() self.quit_game_button.destroy() self.quit_game_bool = True def check_victory(self): """ Function that check if there is a victory case @return 1 if red wins and 2 if yellow wins """ if self.mode == 0: num_disc = self.round elif self.mode == 1: num_disc = self.disc_dropped if num_disc % 2 == 0: disc_type = 1 else: disc_type = 2 self.gridContent[7 * self.line + self.column] = disc_type for i in range(69): for j in range(4): if self.results[i][j] == 7 * self.line + self.column: if (self.gridContent[int(self.results[i][0])] == disc_type) and ( self.gridContent[int(self.results[i][1])] == disc_type) and ( self.gridContent[int(self.results[i][2])] == disc_type) and ( self.gridContent[int(self.results[i][3])] == disc_type): return disc_type return 0 def mainloop(self): """ Main loop of the connect 4 game """ # If quit_button is clicked if self.quit_game_bool: return 0 # Get the clock dt = globalClock.getDt() # Change the button "New game" to "Restart" for the first round if self.round == 1 and self.button_changed == False: self.new_game_button["text"] = "Restart" self.button_changed = True print("Connect 4 > Main loop") # Default mode if self.mode == 0: # Get the position of the current disc pos = self.discs[self.round].disc.getPos() # Left click if self.keyMap["left"] and self.column != 0 and not self.movement_V: self.keyMap["left"] = False self.column -= 1 self.movement_H = True # Right click if self.keyMap["right"] and self.column != 6 and not self.movement_V: self.keyMap["right"] = False self.column += 1 self.movement_H = True # down clic if self.keyMap["down"] and self.gridContent[self.column] == 0 and not self.movement_V: # To have only one click self.keyMap["down"] = False # Find the final disc line line_fixed = 0 self.line = 5 while line_fixed == 0 and self.line >= 0: if self.gridContent[7 * self.line + self.column] != 0: self.line -= 1 else: line_fixed = 1 self.movement_V = True # check if there is a victory or not victory = self.check_victory() if victory == 1: self.text_victory.setText('Red wins') if victory == 2: self.text_victory.setText('Yellow wins') # Progressive vertical movement if self.movement_V and pos.z >= self.axes_V[self.line]: pos.z -= self.speed * dt self.discs[self.round].disc.setPos(pos) # Set the disc position / Prepare next disc if self.movement_V and pos.z <= self.axes_V[self.line]: pos.z = self.axes_V[self.line] self.discs[self.round].disc.setPos(pos) self.audio_coin.play() self.movement_V = False self.line = 0 self.column = 3 self.round += 1 if self.round < 42 and self.mode == 0: self.discs[self.round].disc.setPos(0, 30, 1.5) # Horizontal movement if self.mode == 0 and self.movement_H: pos.x = self.axes_H[self.column] self.discs[self.round].disc.setPos(pos) self.movement_H = False # Handplay mode if self.mode == 1: # Detect hand position if cap.isOpened(): success, image = cap.read() image = cv2.cvtColor(cv2.flip(image, 1), cv2.COLOR_BGR2RGB) image.flags.writeable = False results = hands.process(image) # Draw the hand annotations on the image. image.flags.writeable = True image = cv2.cvtColor(image, cv2.COLOR_RGB2BGR) # If a hand is detected if results.multi_hand_landmarks: for hand_landmarks in results.multi_hand_landmarks: for idx, landmark in enumerate(hand_landmarks.landmark): if idx == 9: x = 24 * landmark.x - 12 z = - 14 * landmark.y + 7 self.right_hand.setPos(x, 30, z) # If a is caught if self.disc_caught != -1: self.discs[self.disc_caught].disc.setPos(self.right_hand.getPos().x - 0.5, 30, self.right_hand.getPos().z + 0.5) else: for i in range(0, 42): if (abs(self.right_hand.getPos().x - 0.5 - self.discs[i].disc.getPos().x) < 0.5) \ and abs(self.right_hand.getPos().z - self.discs[i].disc.getPos().z) < 0.5: self.disc_caught = self.discs[i].id print("Connect 4 > Disc n°", self.disc_caught, " is caught") self.discs[self.disc_caught].disc.setPos(x - 0.5, 30, z + 0.5) # If space touch is pressed if self.keyMap["drop"]: print("Connect 4 > Disc n°", self.disc_caught, " is dropped") self.keyMap["drop"] = False pos_x = self.discs[self.disc_caught].disc.getPos().x min = 10 for i in range(len(self.axes_H)): if abs(self.axes_H[i] - pos_x) < min: self.column = i min = abs(self.axes_H[i] - pos_x) # Find the final disc line line_fixed = 0 self.line = 5 while line_fixed == 0 and self.line >= 0: if self.gridContent[7 * self.line + self.column] != 0: self.line -= 1 else: line_fixed = 1 self.movement_V = True self.discs[self.disc_caught].disc.setPos(self.axes_H[self.column], 30, self.axes_V[0]) self.disc_dropped = self.disc_caught self.disc_caught = -1 # check if there is a victory or not victory = self.check_victory() if victory == 1: self.text_victory.setText('Red wins') if victory == 2: self.text_victory.setText('Yellow wins') # Progressive vertical movement pos = self.discs[self.disc_dropped].disc.getPos() if self.movement_V and pos.z >= self.axes_V[self.line]: pos.z -= self.speed * dt self.discs[self.disc_dropped].disc.setPos(pos) # Set the disc position if self.movement_V and pos.z <= self.axes_V[self.line]: pos.z = self.axes_V[self.line] self.discs[self.disc_dropped].disc.setPos(pos) self.audio_coin.play() self.movement_V = False self.line = 0 self.column = 3 self.round += 1 return 1
class Round(): # Initialisation Function def __init__(self,showbase): # Initialise Window self.showbase=showbase # total time since start of game, to keep ticks updating on time (rather, not before) self.total_time = 0 # packets queue self.incoming=deque() # this is unnecessary lol but meh ill comment it anyway self.hp = OnscreenText(text = "HP: "+str(100.0), pos = (0.95,-0.95), scale = 0.07,fg=(1,1,1,1),align=TextNode.ACenter,mayChange=1) # Keys array (down if 1, up if 0) self.keys={"left":0,"right":0,"up":0,"down":0,"c":0,"x":0} self.skybox=Skybox(self.showbase) self.ch=CameraHandler() # maybe this shit too, or this can stay here and just pass in an array of spells self.showbase.spell_man=SpellManager(self.showbase.num_warlocks) # until the Game() class is created in here which i think it should for i in self.showbase.spells: self.showbase.spell_man.add_spell(i) self.game=Game(self.showbase,game_tick) self.warlock=self.game.warlock[self.showbase.which] self.warlock.attach_ring(self.showbase) self.tick=0 self.temp_tick=0 # Set event handlers for keys self.showbase.accept("escape",sys.exit) # holding c will focus the camera on clients warlock self.showbase.accept("c",set_value,[self.keys,"c",1]) self.showbase.accept("c-up",set_value,[self.keys,"c",0]) # variable to track which spell has been requested self.current_spell=-1 # keys to change spell self.showbase.accept("q",self.set_spell,[0]) self.showbase.accept("w",self.set_spell,[1]) self.showbase.accept("e",self.set_spell,[2]) self.showbase.accept("r",self.set_spell,[3]) # mouse 1 is for casting the spell set by the keys self.showbase.accept("mouse1",self.cast_spell) # mouse 3 is for movement, or canceling keys for casting spell self.showbase.accept("mouse3",self.update_destination) # sets the camera up behind clients warlock looking down on it from angle follow=self.warlock.model self.ch.setTarget(follow.getPos().getX(),follow.getPos().getY(),follow.getPos().getZ()) self.ch.turnCameraAroundPoint(follow.getH(),0) # Add the game loop procedure to the task manager. self.showbase.taskMgr.add(self.game_loop,"Game Loop") def set_spell(self,spell): self.current_spell=spell # sends spell request to server if one is selected def cast_spell(self): if not self.current_spell==-1: target=self.ch.get_mouse_3d() if not target.getZ()==-1: data = {} data[0] = "spell" data[1] = {} data[1][0] = self.current_spell data[1][1] = {} data[1][1][0] = target.getX() data[1][1][1] = target.getY() self.showbase.client.sendData(data) self.current_spell=-1 # sends destination request to server, or cancels spell if selected def update_destination(self): if self.current_spell==-1: destination=self.ch.get_mouse_3d() if not destination.getZ()==-1: data = {} data[0] = "destination" data[1] = {} data[1][0] = destination.getX() data[1][1] = destination.getY() self.showbase.client.sendData(data) else: self.current_spell=-1 def update_camera(self,dt): # sets the camMoveTask to be run every frame self.ch.camMoveTask(dt) # if c is down update camera to always be following on the warlock if self.keys["c"]: follow=self.warlock.model self.ch.setTarget(follow.getPos().getX(),follow.getPos().getY(),follow.getPos().getZ()) self.ch.turnCameraAroundPoint(0,0) # Game Loop Procedure def game_loop(self,task): # update total time self.total_time+=globalClock.getDt() # process any incoming network packets temp=self.showbase.client.getData() if temp!=[]: for i in range(len(temp)): # this part puts the next packets onto the end of the queue self.incoming.append(temp[i]) # while there is packets to process while list(self.incoming): valid_packet=False package=self.incoming.popleft() # if username is sent, assign to client if package[0]=='tick': # not sure if this is the best way to do this but yea something to look into for syncing them all preround i guess if package[1]==0: self.total_time=0 # check what tick it should be self.temp_tick=package[1] # if this tick needs to be run (if frames are up to the server tick) if self.temp_tick*game_tick<=self.total_time: # run tick if not self.game.run_tick(): print 'Game Over' self.update_camera(game_tick) # maybe this should be put outside of this loop and just updated from the globalClock.getDt() self.hp.setText("HP: "+str(self.warlock.hp)) # i think there should be a HUD class which will show all the info needed for the player (like hps,spells cds, etc) valid_packet=True else: # otherwise put packet back on front of list and end frame processing self.incoming.appendleft(package) break # i think it should check for 'tick' and if not tick then pass the rest of the packets to a packet handler (kind of makes it more modable i guess for changing the game to another like pudgewars or centipede or w/e) # so i guess these will be put into a packet manager (i think this idea you had before anyway :P) silly me! :D # well, just leave here for now i guess :P elif package[0]=='update_dest': # if its an update packet then update destination of required warlock print "Update Destination: "+str(package[1])+" "+str(package[2]) self.game.warlock[package[1]].set_destination(Vec3(package[2][0],package[2][1],0)) valid_packet=True elif package[0]=='update_spell': # if its an update packet then update destination of required warlock print "Update Spell: "+str(package[1])+" "+str(package[2])+" "+str(package[3]) self.game.warlock[package[1]].set_spell(package[2],package[3]) valid_packet=True # Return cont to run task again next frame return task.cont
class MyApp(ShowBase): def __init__(self): ShowBase.__init__(self) plane_scale = 0.07 self.xPos = 0.0 self.yPos = 0.0 self.tilt = 0.0 self.lift = 0.0 self.camera_state = "FOLLOW" self.adsb = None self.adsb_states = None self.plane_state = None #camera.setPosHpr(0, 0.5, 20, 0, -100, 0) #Vary this # Disable the camera trackball controls. self.disableMouse() ''' # Load the environment model. self.scene = self.loader.loadModel("models/environment") # Reparent the model to render. self.scene.reparentTo(self.render) # Apply scale and position transforms on the model. self.scene.setScale(0.25, 0.25, 0.25) self.scene.setPos(-8, 42, 0) ''' ''' # Add the spinCameraTask procedure to the task manager. self.taskMgr.add(self.spinCameraTask, "SpinCameraTask") ''' self.plane = loader.loadModel('./models/plane/boeing707') self.plane.setPos(0, 0, 5) self.plane.reparentTo(render) self.plane.setScale(plane_scale, plane_scale, plane_scale) #self.plane.setPosHpr(self.xPos, self.yPos, 0, DEFAULT_HEADING, self.lift, self.tilt) self.plane.setPosHpr(self.xPos, self.yPos, 0, DEFAULT_HEADING, self.lift, self.tilt) # Create a floater object, which lfoats 2 units above the plane self.floater = NodePath(PandaNode("floater")) self.floater.reparentTo(self.plane) self.floater.setZ(2.0) # Add keymappings # Key mappings ''' self.accept('escape', sys.exit) self.accept(']', self.scaleUp) self.accept('[', self.scaleDown) self.accept('w', self.liftUp) self.accept('s', self.liftDown) self.accept('q', self.stabilizeLift) self.accept('a', self.moveLeft) self.accept('d', self.moveRight) self.accept('e', self.stabilizeTilt) ''' # This is used to store which keys are currently pressed. self.keyMap = { "left": 0, "right": 0, "forward": 0, "backward": 0, "cam-left": 0, "cam-right": 0, } self.accept("escape", sys.exit) self.accept("arrow_left", self.setKey, ["left", True]) self.accept("arrow_right", self.setKey, ["right", True]) self.accept("arrow_up", self.setKey, ["forward", True]) self.accept("arrow_down", self.setKey, ["backward", True]) self.accept("a", self.setKey, ["cam-left", True]) self.accept("s", self.setKey, ["cam-right", True]) self.accept("arrow_left-up", self.setKey, ["left", False]) self.accept("arrow_right-up", self.setKey, ["right", False]) self.accept("arrow_up-up", self.setKey, ["forward", False]) self.accept("arrow_down-up", self.setKey, ["backward", False]) self.accept("a-up", self.setKey, ["cam-left", False]) self.accept("s-up", self.setKey, ["cam-right", False]) taskMgr.add(self.move, "moveTask") taskMgr.add(self.adsb_task, "adsbTask") self.title = addTitle("Danger Plane") self.inst1 = addInstructions(0.06, "[ESC]: Quit") self.inst2 = addInstructions(0.12, "[Left Arrow]: Rotate Plane Left") self.inst3 = addInstructions(0.18, "[Right Arrow]: Rotate Plane Right") self.inst4 = addInstructions(0.24, "[Up Arrow]: Moves Plane Down") self.inst5 = addInstructions(0.30, "[Down Arrow]: Moves Plane Up") self.inst6 = addInstructions(0.36, "[A]: Rotate Camera Left") self.inst7 = addInstructions(0.42, "[S]: Rotate Camera Right") self.camera.setPos(self.plane.getX(), self.plane.getY() + 10, 2) self.text_status = OnscreenText(text="Starting...", style=1, fg=(1, 1, 1, 1), scale=.04, parent=base.a2dBottomLeft, align=TextNode.ALeft, pos=(0.08, 0.09), shadow=(0, 0, 0, 1)) ''' self.text_status = TextNode('textStatus') self.text_status.setText("Starting...") self.text_np = aspect2d.attachNewNode(self.text_status) self.text_np.setScale(0.1) self.text_np.setX(-0.9) self.text_np.setY(-0.9) #self.text_np.reparentTo(render) #self.text_np.setZ(0.00) #self.text_np.setPos(self.floater.getX(), self.floater.getY(), 2) print ("Text Position: %f, %f, %f" % (self.text_np.getX(), self.text_np.getY(), self.text_np.getZ())) print ("Plane Position: %f, %f, %f" % (self.plane.getX(), self.plane.getY(), self.plane.getZ())) print ("Floater Position: %f, %f, %f" % (self.floater.getX(), self.floater.getY(), self.floater.getZ())) ''' def setKey(self, key, value): self.keyMap[key] = value def adsb_task(self, task): if self.adsb == None: self.adsb = ADSBFactory().open(ADSB_SOURCE) if DEFAULT_BOUNDING_BOX is not None: self.adsb.set_bounding_box( DEFAULT_BOUNDING_BOX[0], DEFAULT_BOUNDING_BOX[1], DEFAULT_BOUNDING_BOX[2], DEFAULT_BOUNDING_BOX[3], ) self.adsb.enable_bounding_box(True) self.adsb_states = self.adsb.get_states() if self.adsb_states is not None: # Update States #XXX: Just get the first plane for now self.plane_state = self.adsb_states.states[0] self.text_status.setText( "%s: La: %f, Lo: %f, A: %f, V: %f, H: %f" % (self.plane_state.callsign, self.plane_state.latitude, self.plane_state.longitude, self.plane_state.geo_altitude, self.plane_state.velocity, self.plane_state.heading)) self.plane.setPosHpr(self.plane_state.longitude, self.plane_state.latitude, self.plane_state.geo_altitude, self.plane_state.heading, self.lift, self.tilt) pass return task.cont # Accepts arrow keys to move either the player or the menu cursor, # Also deals with grid checking and collision detection def move(self, task): # Get the time that elapsed since last frame. We multiply this with # the desired speed in order to find out with which distance to move # in order to achieve that desired speed. dt = globalClock.getDt() # If the camera-left key is pressed, move camera left. # If the camera-right key is pressed, move camera right. #if self.keyMap["cam-left"]: # self.camera.setX(self.camera, -20 * dt) #if self.keyMap["cam-right"]: # self.camera.setX(self.camera, +20 * dt) # If a move-key is pressed, move ralph in the specified direction. if self.keyMap["left"]: self.moveLeft() #self.ralph.setH(self.ralph.getH() + 300 * dt) if self.keyMap["right"]: #self.ralph.setH(self.ralph.getH() - 300 * dt) self.moveRight() if self.keyMap["forward"]: #self.ralph.setY(self.ralph, -20 * dt) self.liftDown() if self.keyMap["backward"]: #self.ralph.setY(self.ralph, +10 * dt) self.liftUp() if self.camera_state == "USER": pass else: #Follow the plane camvec = self.plane.getPos() - self.camera.getPos() camvec.setZ(0) camdist = camvec.length() camvec.normalize() if camdist > 10.0: self.camera.setPos(self.camera.getPos() + camvec * (camdist - 10)) camdist = 10.0 if camdist < 5.0: self.camera.setPos(self.camera.getPos() - camvec * (5 - camdist)) camdist = 5.0 self.camera.setZ(self.plane.getZ() + 2.0) self.camera.lookAt(self.floater) return task.cont # Make the Boeing stable on the tilt def stabilizeTilt(self): if (self.tilt > 0): if (self.tilt != 0.0): self.tilt = self.tilt - 0.25 else: if (self.tilt != 0.0): self.tilt = self.tilt + 0.25 self.plane.setPosHpr(self.xPos, self.yPos, 0, DEFAULT_HEADING, self.lift, self.tilt) # Make the Boeing stable on the lift def stabilizeLift(self): if (self.lift > 0): if (self.lift != 0.0): self.lift = self.lift - 0.25 else: if (self.lift != 0.0): self.lift = self.lift + 0.25 self.plane.setPosHpr(self.xPos, self.yPos, 0, DEFAULT_HEADING, self.lift, self.tilt) # Zoom into the plane def scaleUp(self): self.scale = self.scale + 0.005 self.plane.setScale(self.scale, self.scale, self.scale) # Zoom out of the plane def scaleDown(self): self.scale = self.scale - 0.005 self.plane.setScale(self.scale, self.scale, self.scale) # Move the plane right def moveRight(self): if (self.tilt >= MAX_TILT): self.tilt = MAX_TILT self.xPos = self.xPos + 0.01 self.tilt = self.tilt + 0.25 self.plane.setPosHpr(self.xPos, self.yPos, 0, DEFAULT_HEADING, self.lift, self.tilt) # Move the plane left def moveLeft(self): if (self.tilt <= -MAX_TILT): self.tilt = -MAX_TILT self.tilt = self.tilt - 0.25 self.xPos = self.xPos - 0.01 self.plane.setPosHpr(self.xPos, self.yPos, 0, DEFAULT_HEADING, self.lift, self.tilt) # Lift the plane up def liftUp(self): if (self.lift >= MAX_LIFT): self.lift = MAX_LIFT self.lift = self.lift + 0.25 self.yPos = self.yPos + 0.01 self.plane.setPosHpr(self.xPos, self.yPos, 0, DEFAULT_HEADING, self.lift, self.tilt) # Lift the plane down def liftDown(self): if (self.lift <= -MAX_LIFT): self.lift = -MAX_LIFT self.lift = self.lift - 0.25 self.yPos = self.yPos - 0.01 self.plane.setPosHpr(self.xPos, self.yPos, 0, DEFAULT_HEADING, self.lift, self.tilt) # Define a procedure to move the camera. def spinCameraTask(self, task): angleDegrees = task.time * 6.0 angleRadians = angleDegrees * (pi / 180.0) self.camera.setPos(20 * sin(angleRadians), -20.0 * cos(angleRadians), 3) self.camera.setHpr(angleDegrees, 0, 0) return Task.cont
class DistributedPartyTrampolineActivity(DistributedPartyActivity): notify = DirectNotifyGlobal.directNotify.newCategory('DistributedPartyTrampolineActivity') def __init__(self, cr, doJellyBeans = True, doTricks = False, texture = None): DistributedPartyTrampolineActivity.notify.debug('__init__') DistributedPartyActivity.__init__(self, cr, PartyGlobals.ActivityIds.PartyTrampoline, PartyGlobals.ActivityTypes.GuestInitiated, wantLever=False, wantRewardGui=True) self.doJellyBeans = doJellyBeans self.doTricks = doTricks self.texture = texture self.toon = None self.trampHeight = 3.6 self.trampK = 400.0 self.normalTrampB = 2.5 self.leavingTrampB = 8.0 self.trampB = self.normalTrampB self.g = -32.0 self.jumpBoost = 330.0 self.beginningBoost = 500.0 self.beginningBoostThreshold = self.trampHeight + 1.5 self.earlyJumpThreshold = 75.0 self.boingThreshold = 300.0 self.turnFactor = 120.0 self.stepDT = 0.001 self.targetCameraPos = Point3(0.0, 40.0, 10.0) self.cameraSpeed = 2.0 self.hopOffPos = Point3(16.0, 0.0, 0.0) self.indicatorFactor = 0.0095 self.dropShadowCutoff = 15.0 self.minHeightForText = 15.0 self.heightTextOffset = -0.065 self.beanOffset = 0.5 self.guiBeanOffset = -0.02 self.jumpTextShown = False self.toonJumped = False self.turnLeft = False self.turnRight = False self.leavingTrampoline = False self.toonVelocity = 0.0 self.topHeight = 0.0 self.lastPeak = 0.0 self.beginRoundInterval = None self.hopOnAnim = None self.hopOffAnim = None self.flashTextInterval = None self.numJellyBeans = PartyGlobals.TrampolineNumJellyBeans self.jellyBeanBonus = PartyGlobals.TrampolineJellyBeanBonus self.jellyBeanStartHeight = 20.0 self.jellyBeanStopHeight = 90.0 self.jellyBeanColors = [VBase4(1.0, 0.5, 0.5, 1.0), VBase4(0.5, 1.0, 0.5, 1.0), VBase4(0.5, 1.0, 1.0, 1.0), VBase4(1.0, 1.0, 0.4, 1.0), VBase4(0.4, 0.4, 1.0, 1.0), VBase4(1.0, 0.5, 1.0, 1.0)] delta = (self.jellyBeanStopHeight - self.jellyBeanStartHeight) / (self.numJellyBeans - 1) self.jellyBeanPositions = [ self.jellyBeanStartHeight + n * delta for n in xrange(self.numJellyBeans) ] self.doSimulateStep = False return def load(self): DistributedPartyTrampolineActivity.notify.debug('load') DistributedPartyActivity.load(self) self.loadModels() self.loadCollision() self.loadGUI() self.loadSounds() self.loadIntervals() self.activityFSM = TrampolineActivityFSM(self) self.activityFSM.request('Idle') self.animFSM = TrampolineAnimFSM(self) self.setBestHeightInfo('', 0) def loadModels(self): self.tramp = self.root.attachNewNode(self.uniqueName('tramp')) self.trampActor = Actor('phase_13/models/parties/trampoline_model', {'emptyAnim': 'phase_13/models/parties/trampoline_anim'}) self.trampActor.reparentTo(self.tramp) if self.texture: reskinNode = self.tramp.find('**/trampoline/__Actor_modelRoot/-GeomNode') reskinNode.setTexture(loader.loadTexture(self.texture), 100) self.surface = NodePath(self.uniqueName('trampSurface')) self.surface.reparentTo(self.tramp) self.surface.setZ(self.trampHeight) self.trampActor.controlJoint(self.surface, 'modelRoot', 'trampoline_joint1') self.sign.setPos(PartyGlobals.TrampolineSignOffset) self.beans = [ loader.loadModelCopy('phase_4/models/props/jellybean4') for i in xrange(self.numJellyBeans) ] for bean in self.beans: bean.find('**/jellybean').setP(-35.0) bean.setScale(3.0) bean.setTransparency(True) bean.reparentTo(self.tramp) bean.stash() self.beans[-1].setScale(8.0) def loadCollision(self): collTube = CollisionTube(0.0, 0.0, 0.0, 0.0, 0.0, 6.0, 5.4) collTube.setTangible(True) self.trampolineCollision = CollisionNode(self.uniqueName('TrampolineCollision')) self.trampolineCollision.addSolid(collTube) self.trampolineCollision.setCollideMask(OTPGlobals.CameraBitmask | OTPGlobals.WallBitmask) self.trampolineCollisionNP = self.tramp.attachNewNode(self.trampolineCollision) collSphere = CollisionSphere(0.0, 0.0, 0.0, 7.0) collSphere.setTangible(False) self.trampolineTrigger = CollisionNode(self.uniqueName('TrampolineTrigger')) self.trampolineTrigger.addSolid(collSphere) self.trampolineTrigger.setIntoCollideMask(OTPGlobals.WallBitmask) self.trampolineTriggerNP = self.tramp.attachNewNode(self.trampolineTrigger) self.accept('enter%s' % self.uniqueName('TrampolineTrigger'), self.onTrampolineTrigger) def loadGUI(self): self.gui = loader.loadModel('phase_13/models/parties/trampolineGUI') self.gui.reparentTo(base.a2dTopLeft) self.gui.setPos(0.115, 0, -1) self.gui.hide() self.toonIndicator = self.gui.find('**/trampolineGUI_MovingBar') jumpLineLocator = self.gui.find('**/jumpLine_locator') guiBean = self.gui.find('**/trampolineGUI_GreenJellyBean') self.gui.find('**/trampolineGUI_GreenJellyBean').stash() self.guiBeans = [ guiBean.instanceUnderNode(jumpLineLocator, self.uniqueName('guiBean%d' % i)) for i in xrange(self.numJellyBeans) ] self.guiBeans[-1].setScale(1.5) heightTextNode = TextNode(self.uniqueName('TrampolineActivity.heightTextNode')) heightTextNode.setFont(ToontownGlobals.getSignFont()) heightTextNode.setAlign(TextNode.ALeft) heightTextNode.setText('0.0') heightTextNode.setShadow(0.05, 0.05) heightTextNode.setShadowColor(0.0, 0.0, 0.0, 1.0) heightTextNode.setTextColor(1.0, 1.0, 1.0, 1.0) self.heightText = jumpLineLocator.attachNewNode(heightTextNode) self.heightText.setX(0.15) self.heightText.setScale(0.1) self.heightText.setAlphaScale(0.0) self.quitEarlyButtonModels = loader.loadModel('phase_3.5/models/gui/inventory_gui') quitEarlyUp = self.quitEarlyButtonModels.find('**//InventoryButtonUp') quitEarlyDown = self.quitEarlyButtonModels.find('**/InventoryButtonDown') quitEarlyRollover = self.quitEarlyButtonModels.find('**/InventoryButtonRollover') self.quitEarlyButton = DirectButton(parent=base.a2dTopRight, relief=None, text=TTLocalizer.PartyTrampolineQuitEarlyButton, text_fg=(1, 1, 0.65, 1), text_pos=(0, -0.23), text_scale=0.7, image=(quitEarlyUp, quitEarlyDown, quitEarlyRollover), image_color=(1, 0, 0, 1), image_scale=(20, 1, 11), pos=(-0.183, 0, -0.4), scale=0.09, command=self.leaveTrampoline) self.quitEarlyButton.stash() self.flashText = OnscreenText(text='', pos=(0.0, -0.45), scale=0.2, fg=(1.0, 1.0, 0.65, 1.0), align=TextNode.ACenter, font=ToontownGlobals.getSignFont(), mayChange=True) self.timer = PartyUtils.getNewToontownTimer() self.timer.posInTopRightCorner() return def loadSounds(self): self.jellyBeanSound = base.loadSfx('phase_4/audio/sfx/sparkly.ogg') self.boingSound = base.loadSfx('phase_4/audio/sfx/target_trampoline_2.ogg') self.whistleSound = base.loadSfx('phase_4/audio/sfx/AA_sound_whistle.ogg') def loadIntervals(self): def prepareHeightText(): self.heightText.node().setText(TTLocalizer.PartyTrampolineGetHeight % int(self.toon.getZ())) self.heightText.setZ(self.indicatorFactor * self.toon.getZ() + self.heightTextOffset) self.heightTextInterval = Sequence(Func(prepareHeightText), LerpFunc(self.heightText.setAlphaScale, fromData=1.0, toData=0.0, duration=1.0)) def unload(self): DistributedPartyTrampolineActivity.notify.debug('unload') if self.hopOnAnim and self.hopOnAnim.isPlaying(): self.hopOnAnim.finish() if self.hopOffAnim and self.hopOffAnim.isPlaying(): self.hopOffAnim.finish() if self.beginRoundInterval and self.beginRoundInterval.isPlaying(): self.beginRoundInterval.finish() if self.flashTextInterval and self.flashTextInterval.isPlaying(): self.flashTextInterval.finish() if self.heightTextInterval and self.heightTextInterval.isPlaying(): self.heightTextInterval.finish() self.timer.stop() DistributedPartyActivity.unload(self) taskMgr.remove(self.uniqueName('TrampolineActivity.updateTask')) taskMgr.remove(self.uniqueName('TrampolineActivity.remoteUpdateTask')) self.ignoreAll() del self.heightTextInterval del self.beginRoundInterval del self.hopOnAnim del self.hopOffAnim del self.flashTextInterval if hasattr(self, 'beanAnims'): self.cleanupJellyBeans() self.quitEarlyButton.destroy() del self.quitEarlyButton del self.gui del self.activityFSM del self.animFSM return def setBestHeightInfo(self, toonName, height): self.bestHeightInfo = (toonName, height) DistributedPartyTrampolineActivity.notify.debug('%s has the best height of %d' % (toonName, height)) if height > 0: self.setSignNote(TTLocalizer.PartyTrampolineBestHeight % self.bestHeightInfo) else: self.setSignNote(TTLocalizer.PartyTrampolineNoHeightYet) def leaveTrampoline(self): if self.toon != None and self.toon.doId == base.localAvatar.doId: self._showFlashMessage(TTLocalizer.PartyTrampolineTimesUp) self.leavingTrampoline = True self.timer.reset() self.trampB = self.leavingTrampB self.ignore('control') self.quitEarlyButton.stash() self.gui.hide() return def requestAnim(self, request): self.animFSM.request(request) def b_requestAnim(self, request): self.requestAnim(request) self.sendUpdate('requestAnim', [request]) def requestAnimEcho(self, request): if self.toon != None and self.toon.doId != base.localAvatar.doId: self.requestAnim(request) return def removeBeans(self, beansToRemove): for i in beansToRemove: height, bean, guiBean, beanAnim = self.beanDetails[i] guiBean.stash() if i in self.beansToCollect: self.beansToCollect.remove(i) else: self.notify.warning('removeBeans avoided a crash, %d not in self.beansToCollect' % i) self.poofBean(bean, beanAnim) def b_removeBeans(self, beansToRemove): self.removeBeans(beansToRemove) self.sendUpdate('removeBeans', [beansToRemove]) def removeBeansEcho(self, beansToRemove): if self.toon != None and self.toon.doId != base.localAvatar.doId: self.removeBeans(beansToRemove) return def joinRequestDenied(self, reason): DistributedPartyActivity.joinRequestDenied(self, reason) self.showMessage(TTLocalizer.PartyActivityDefaultJoinDeny) base.cr.playGame.getPlace().fsm.request('walk') def exitRequestDenied(self, reason): DistributedPartyActivity.exitRequestDenied(self, reason) self.showMessage(TTLocalizer.PartyActivityDefaultExitDeny) def setState(self, newState, timestamp): DistributedPartyTrampolineActivity.notify.debug('setState( newState=%s, ... )' % newState) DistributedPartyActivity.setState(self, newState, timestamp) self.activityFSM.request(newState) def startIdle(self): DistributedPartyTrampolineActivity.notify.debug('startIdle') def finishIdle(self): DistributedPartyTrampolineActivity.notify.debug('finishIdle') def startRules(self): DistributedPartyTrampolineActivity.notify.debug('startRules') if self.doJellyBeans: self.setupJellyBeans() if self.toon != None and self.toon.doId == base.localAvatar.doId: self.acquireToon() return def startActive(self): DistributedPartyTrampolineActivity.notify.debug('startActive') if self.toon != None and self.toon.doId == base.localAvatar.doId: base.setCellsActive(base.bottomCells, True) self.accept('arrow_left', self.onLeft) self.accept('arrow_left-up', self.onLeftUp) self.accept('arrow_right', self.onRight) self.accept('arrow_right-up', self.onRightUp) self.beginRoundInterval = Sequence(Func(self._showFlashMessage, TTLocalizer.PartyTrampolineReady), Wait(1.2), Func(self.flashMessage, TTLocalizer.PartyTrampolineGo), Func(self.beginRound)) self.beginRoundInterval.start() return def finishActive(self): DistributedPartyTrampolineActivity.notify.debug('finishActive') if self.doJellyBeans: self.cleanupJellyBeans() def setupJellyBeans(self): self.beanAnims = [] self.beansToCollect = [] self.beanDetails = [] self.numBeansCollected = 0 for i in xrange(self.numJellyBeans): bean = self.beans[i] guiBean = self.guiBeans[i] height = self.jellyBeanPositions[i] color = random.choice(self.jellyBeanColors) bean.find('**/jellybean').setColor(color) if self.toon.doId == base.localAvatar.doId: bean.setAlphaScale(1.0) else: bean.setAlphaScale(0.5) guiBean.setColor(color) bean.setZ(height + self.toon.getHeight() + self.beanOffset) guiBean.setZ(height * self.indicatorFactor + self.guiBeanOffset) bean.setH(0.0) bean.unstash() guiBean.unstash() beanAnim = bean.hprInterval(1.5, VBase3((i % 2 * 2 - 1) * 360.0, 0.0, 0.0)) beanAnim.loop() self.beanAnims.append(beanAnim) self.beanDetails.append((height, bean, guiBean, beanAnim)) self.beansToCollect = range(self.numJellyBeans) def cleanupJellyBeans(self): for bean in self.beans: bean.stash() for guiBean in self.guiBeans: guiBean.stash() if hasattr(self, 'beanAnims'): for beanAnim in self.beanAnims: beanAnim.finish() del self.beanAnims del self.beansToCollect def beginRound(self): base.playSfx(self.whistleSound) self.timer.setTime(PartyGlobals.TrampolineDuration) self.timer.countdown(PartyGlobals.TrampolineDuration) self.timer.show() self.gui.show() self.quitEarlyButton.unstash() self.notify.debug('Accepting contorl') self.accept('control', self.onJump) self.notify.debug('setting simulate step to true') self.doSimulateStep = True def acquireToon(self): self.toon.disableSmartCameraViews() self.toon.stopUpdateSmartCamera() camera.wrtReparentTo(render) self.toon.dropShadow.reparentTo(hidden) self.toon.startPosHprBroadcast(period=0.2) self.toonAcceleration = 0.0 self.toonVelocity = 0.0 self.topHeight = 0.0 self.trampB = self.normalTrampB self.leavingTrampoline = False self.hopOnAnim = Sequence(Func(self.toon.b_setAnimState, 'jump', 1.0), Wait(0.4), PartyUtils.arcPosInterval(0.75, self.toon, Point3(0.0, 0.0, self.trampHeight), 5.0, self.tramp), Func(self.postHopOn)) self.hopOnAnim.start() def postHopOn(self): self.toon.setH(self.toon.getH() + 90.0) self.toon.dropShadow.reparentTo(self.surface) self.timeLeftToSimulate = 0.0 self.doSimulateStep = False taskMgr.add(self.updateTask, self.uniqueName('TrampolineActivity.updateTask')) base.setCellsActive(base.leftCells, False) base.setCellsActive(base.bottomCells, False) DistributedPartyActivity.startRules(self) def releaseToon(self): self._hideFlashMessage() self.ignore('arrow_left') self.ignore('arrow_left-up') self.ignore('arrow_right') self.ignore('arrow_right-up') taskMgr.remove(self.uniqueName('TrampolineActivity.updateTask')) self.hopOffAnim = Sequence(self.toon.hprInterval(0.5, VBase3(-90.0, 0.0, 0.0), other=self.tramp), Func(self.toon.b_setAnimState, 'jump', 1.0), Func(self.toon.dropShadow.reparentTo, hidden), Wait(0.4), PartyUtils.arcPosInterval(0.75, self.toon, self.hopOffPos, 5.0, self.tramp), Func(self.postHopOff)) self.hopOffAnim.start() def postHopOff(self): base.setCellsActive(base.leftCells, True) self.timer.stop() self.timer.hide() self.toon.dropShadow.reparentTo(self.toon.getShadowJoint()) self.toon.dropShadow.setAlphaScale(1.0) self.toon.dropShadow.setScale(1.0) self.b_requestAnim('Off') camera.reparentTo(base.localAvatar) base.localAvatar.startUpdateSmartCamera() base.localAvatar.enableSmartCameraViews() base.localAvatar.setCameraPositionByIndex(base.localAvatar.cameraIndex) place = base.cr.playGame.getPlace() if self.doJellyBeans: self.sendUpdate('awardBeans', [self.numBeansCollected, int(self.topHeight)]) if int(self.topHeight) > self.bestHeightInfo[1]: self.sendUpdate('reportHeightInformation', [int(self.topHeight)]) self.d_toonExitDemand() def onTrampolineTrigger(self, collEntry): if self.activityFSM.state == 'Idle' and self.toon == None and base.cr.playGame.getPlace().fsm.getCurrentState().getName() == 'walk': base.cr.playGame.getPlace().fsm.request('activity') self.d_toonJoinRequest() else: self.flashMessage(TTLocalizer.PartyTrampolineActivityOccupied, duration=2.0) return def onJump(self): self.notify.debug('got onJump') if self.toon != None and self.toon.getZ() < self.trampHeight: self.toonJumped = True self.b_requestAnim('Jump') else: self.notify.debug('z is less than tramp height') return def onLeft(self): self.turnLeft = True def onLeftUp(self): self.turnLeft = False def onRight(self): self.turnRight = True def onRightUp(self): self.turnRight = False def handleToonJoined(self, toonId): DistributedPartyTrampolineActivity.notify.debug('handleToonJoined') self.toon = self.getAvatar(toonId) if self.toon != None and not self.toon.isEmpty(): self.oldJumpSquatPlayRate = self.toon.getPlayRate('jump-squat') self.oldJumpLandPlayRate = self.toon.getPlayRate('jump-land') self.toon.setPlayRate(2.5, 'jump-squat') self.toon.setPlayRate(2.0, 'jump-land') self.turnLeft = False self.turnRight = False self.activityFSM.request('Rules') if self.toon.doId != base.localAvatar.doId: taskMgr.add(self.remoteUpdateTask, self.uniqueName('TrampolineActivity.remoteUpdateTask')) else: self.notify.warning('handleToonJoined could not get toon %d' % toonId) return def handleToonExited(self, toonId): DistributedPartyTrampolineActivity.notify.debug('handleToonExited') if self.toon != None: if self.toon.doId != base.localAvatar.doId: taskMgr.remove(self.uniqueName('TrampolineActivity.remoteUpdateTask')) self.surface.setZ(self.trampHeight) self.toon.setPlayRate(self.oldJumpSquatPlayRate, 'jump-squat') self.toon.setPlayRate(self.oldJumpLandPlayRate, 'jump-land') self.toon = None return def handleToonDisabled(self, toonId): DistributedPartyTrampolineActivity.notify.debug('handleToonDisabled') DistributedPartyTrampolineActivity.notify.debug('avatar ' + str(toonId) + ' disabled') if base.localAvatar.doId == toonId: self.releaseToon() def handleRulesDone(self): self.sendUpdate('toonReady') self.finishRules() def getTitle(self): if self.doJellyBeans: return TTLocalizer.PartyTrampolineJellyBeanTitle elif self.doTricks: return TTLocalizer.PartyTrampolineTricksTitle else: return DistributedPartyActivity.getTitle(self) def getInstructions(self): return TTLocalizer.PartyTrampolineActivityInstructions def updateTask(self, task): z = self.toon.getZ() dt = globalClock.getDt() if self.doSimulateStep: self.timeLeftToSimulate += dt while self.timeLeftToSimulate >= self.stepDT: z, a = self.simulateStep(z) self.timeLeftToSimulate -= self.stepDT self.toon.setZ(z) if z <= self.trampHeight: self.surface.setZ(z) else: self.surface.setZ(self.trampHeight) self.toonIndicator.setZ((z - self.trampHeight) * self.indicatorFactor) if self.turnLeft: self.toon.setH(self.toon.getH() + self.turnFactor * dt) if self.turnRight: self.toon.setH(self.toon.getH() - self.turnFactor * dt) currentPos = base.camera.getPos(self.toon) vec = self.targetCameraPos - currentPos newPos = currentPos + vec * (dt * self.cameraSpeed) base.camera.setPos(self.toon, newPos) base.camera.lookAt(self.toon) #if z > self.trampHeight: # heightFactor = 1.0 - min(1.0, (z - self.trampHeight) / self.dropShadowCutoff) # self.toon.dropShadow.setAlphaScale(heightFactor) # self.toon.dropShadow.setScale(max(0.1, heightFactor)) #else: # self.toon.dropShadow.setAlphaScale(1.0) # self.toon.dropShadow.setScale(1.0) if self.leavingTrampoline and z < self.trampHeight and abs(a) < 0.1: self.releaseToon() return Task.cont def simulateStep(self, z): if z >= self.trampHeight: a = self.g self.toonJumped = False else: a = self.g + self.trampK * (self.trampHeight - z) - self.trampB * self.toonVelocity if self.toonJumped: if self.lastPeak > self.earlyJumpThreshold or self.toonVelocity >= -300000.0: a += self.jumpBoost if self.lastPeak < self.beginningBoostThreshold: a += self.beginningBoost lastVelocity = self.toonVelocity self.toonVelocity += a * self.stepDT if lastVelocity > 0.0 and self.toonVelocity <= 0.0: topOfJump = True bottomOfJump = False elif lastVelocity < 0.0 and self.toonVelocity >= 0.0: topOfJump = False bottomOfJump = True else: topOfJump = False bottomOfJump = False newZ = z + self.toonVelocity * self.stepDT if newZ > self.topHeight: self.topHeight = newZ if self.doJellyBeans: self.collectJellyBeans(newZ) if topOfJump: self.lastPeak = newZ if newZ >= self.minHeightForText: self.heightTextInterval.start() if topOfJump: if newZ > self.trampHeight + 20.0: self.b_requestAnim('Falling') elif self.animFSM.state == 'Jump': self.b_requestAnim('Falling') if newZ <= self.trampHeight and z > self.trampHeight: if self.animFSM.state == 'Falling': self.b_requestAnim('Land') elif self.animFSM.state != 'Neutral': self.b_requestAnim('Neutral') if bottomOfJump and a > self.boingThreshold: base.playSfx(self.boingSound) return (newZ, a) def collectJellyBeans(self, z): beansToRemove = [] for i in self.beansToCollect: height = self.beanDetails[i][0] if height <= z: beansToRemove.append(i) if len(beansToRemove) > 0: base.playSfx(self.jellyBeanSound) self.numBeansCollected += len(beansToRemove) self.b_removeBeans(beansToRemove) def remoteUpdateTask(self, task): if self.toon != None and not self.toon.isEmpty(): z = self.toon.getZ() if z <= self.trampHeight: self.surface.setZ(z) else: self.surface.setZ(self.trampHeight) return Task.cont def poofBean(self, bean, beanAnim): if bean == None: self.notify.warning('poofBean, returning immediately as bean is None') return if bean.isEmpty(): self.notify.warning('poofBean, returning immediately as bean is empty') return currentAlpha = bean.getColorScale()[3] currentScale = bean.getScale() poofAnim = Sequence(Parallel(LerpFunc(bean.setAlphaScale, fromData=currentAlpha, toData=0.0, duration=0.25), LerpFunc(bean.setScale, fromData=currentScale, toData=currentScale * 5.0, duration=0.25)), Func(bean.stash), Func(beanAnim.finish), Func(bean.setAlphaScale, currentAlpha), Func(bean.setScale, currentScale)) poofAnim.start() return def _showFlashMessage(self, message): if self.isDisabled(): return if self.flashTextInterval is not None and self.flashTextInterval.isPlaying(): self.flashTextInterval.finish() self.flashText.setText(message) self.flashText.setAlphaScale(1.0) self.flashText.unstash() return def _hideFlashMessage(self, duration = 0.0): if self.isDisabled(): pass self.flashTextInterval = Sequence(Wait(duration), LerpFunc(self.flashText.setAlphaScale, fromData=1.0, toData=0.0, duration=1.0), Func(self.flashText.stash)) self.flashTextInterval.start() def flashMessage(self, message, duration = 0.5): self._showFlashMessage(message) self._hideFlashMessage(duration)
class Water(ShowBase): def __init__(self): ShowBase.__init__(self) self.disableMouse() # sun=DirectionalLight("sun") sun.setColor((0.5, 0.5, 0.5, 1.0)) sunN=self.render.attachNewNode(sun) sunN.setHpr(-45, -45, 0) self.render.setLight(sunN) # self.terreno=self.loader.loadModel("terreno-flattened") self.terreno.reparentTo(self.render) #self.terreno.setClipPlane(plane_nodeN) # point=PointLight("foco") point.setColor((0.7, 0.7, 0.7, 1.0)) pointN=self.render.attachNewNode(point) pointN.setPos(0.0, 0.0, 0.2) self.render.setLight(pointN) # self.horrendo=self.loader.loadModel("horrendo") self.horrendo.reparentTo(self.render) self.horrendo.setPos(0.0, 0.0, 3.0) # self.hombre=self.loader.loadModel("actor.egg") self.hombre.reparentTo(self.render) self.hombre.setPos(0.0, 3.0, -0.5) # self.nivel_agua=-0.7#-0.05 self.agua=self.loader.loadModel("plano-flattened") self.agua.reparentTo(self.render) self.agua.setScale(0.75) self.agua.setTransparency(TransparencyAttrib.MAlpha) self.agua.setZ(self.nivel_agua) # self.rotador=self.render.attachNewNode("rotador") #self.rotador.setZ(self.nivel_agua) self.camera2=None self.camera3=None # self.configurar_reflejo() self.configurar_refraccion() self.configurar_dudv() self.configurar_normal() self.move_factor=0.0 # self.vel_cam=Vec2(0.0, 0.0) # self.camera.reparentTo(self.rotador) self.camera.setPos(self.agua, 10.0, -24.0, 10.0) self.camera.lookAt(self.agua) if self.camera2!=None: self.camera2.reparentTo(self.rotador) self.camera2.setPos(self.agua, 10.0, -24.0, -10.0) self.camera2.lookAt(self.agua) if self.camera3!=None: self.camera3.reparentTo(self.rotador) self.camera3.setPos(self.agua, 10.0, -24.0, 10.0) self.camera3.lookAt(self.agua) # debug info text self.texto1=OnscreenText(text="info?", pos=(0.5, 0.5), scale=0.05, mayChange=True) # shader=Shader.load(Shader.SL_GLSL, vertex="water.v.glsl", fragment="water.f.glsl") self.agua.setShader(shader) self.agua.setShaderInput("light_pos", sunN.getPos()) self.agua.setShaderInput("light_color", sun.getColor()) # self.accept("arrow_left", self.input, ["arrow_left"]) self.accept("arrow_right", self.input, ["arrow_right"]) self.accept("arrow_up", self.input, ["arrow_up"]) self.accept("arrow_down", self.input, ["arrow_down"]) self.accept("arrow_left-up", self.input, ["deactivate"]) self.accept("arrow_right-up", self.input, ["deactivate"]) self.accept("arrow_up-up", self.input, ["deactivate"]) self.accept("arrow_down-up", self.input, ["deactivate"]) # self.taskMgr.add(self.update,"update") def input(self, tecla): dmove=1.0 if tecla=="arrow_left": self.vel_cam.setX(-dmove) elif tecla=="arrow_right": self.vel_cam.setX(dmove) elif tecla=="arrow_up": self.vel_cam.setY(dmove) elif tecla=="arrow_down": self.vel_cam.setY(-dmove) elif tecla=="deactivate": self.vel_cam=Vec2(0.0, 0.0) def configurar_reflejo(self): # reflejo reflection_plane=Plane(Vec3(0.0, 0.0, 1.0), Vec3(0.0, 0.0, self.nivel_agua-0.15)) reflection_plane_node=PlaneNode("reflection_plane_node") reflection_plane_node.setPlane(reflection_plane) reflection_plane_nodeN=self.render.attachNewNode(reflection_plane_node) # reflection_buffer=self.win.makeTextureBuffer('reflection_buffer', 512, 512) reflection_buffer.setClearColor(Vec4(0, 0, 0, 1)) self.camera2=self.makeCamera(reflection_buffer) self.camera2.node().getLens().setFov(self.cam.node().getLens().getFov()) dummy_reflection=NodePath("dummy_reflection") dummy_reflection.setTwoSided(False) dummy_reflection.setClipPlane(reflection_plane_nodeN) self.camera2.node().setInitialState(dummy_reflection.getState()) # ts0=TextureStage("tsBuffer_reflection") tex0=reflection_buffer.getTexture() tex0.setWrapU(Texture.WMClamp) tex0.setWrapV(Texture.WMClamp) self.agua.setTexture(ts0, tex0) def configurar_refraccion(self): # refraccion refraction_plane=Plane(Vec3(0.0, 0.0, -1.0), Vec3(0.0, 0.0, self.nivel_agua+0.109)) refraction_plane_node=PlaneNode("refraction_plane_node") refraction_plane_node.setPlane(refraction_plane) refraction_plane_nodeN=self.render.attachNewNode(refraction_plane_node) # refraction_buffer=self.win.makeTextureBuffer('refraction_buffer', 512, 512) refraction_buffer.setClearColor(Vec4(0, 0, 0, 1)) self.camera3=self.makeCamera(refraction_buffer) self.camera3.node().getLens().setFov(self.cam.node().getLens().getFov()) dummy_refraction=NodePath("dummy_refraction") dummy_refraction.setTwoSided(False) dummy_refraction.setClipPlane(refraction_plane_nodeN) self.camera3.node().setInitialState(dummy_refraction.getState()) # ts1=TextureStage("tsBuffer_refraction") tex1=refraction_buffer.getTexture() tex1.setWrapU(Texture.WMClamp) tex1.setWrapV(Texture.WMClamp) self.agua.setTexture(ts1, tex1) def configurar_dudv(self): ts2=TextureStage("tsBuffer_dudv") tex2=self.loader.loadTexture("agua_dudv.png") tex2.setWrapU(Texture.WMRepeat) tex2.setWrapV(Texture.WMRepeat) self.agua.setTexture(ts2, tex2) def configurar_normal(self): ts3=TextureStage("tsBuffer_normal") tex3=self.loader.loadTexture("agua_normal.png") tex3.setWrapU(Texture.WMRepeat) tex3.setWrapV(Texture.WMRepeat) self.agua.setTexture(ts3, tex3) def update(self, task): if self.camera2!=None: self.camera2.setPos(self.camera.getPos()) self.camera2.setZ(-self.camera.getZ()) self.camera2.setP(-self.camera.getP()) if self.camera3!=None: self.camera3.setPos(self.camera.getPos()) self.camera3.setHpr(self.camera.getHpr()) if self.camera2!=None and self.camera3!=None: self.texto1.setText("cam %s %s\ncam2 %s %s\ncam3 %s %s"%(str(self.camera.getPos(self.render)), str(self.camera.getHpr(self.render)), str(self.camera2.getPos(self.render)), str(self.camera2.getHpr(self.render)), str(self.camera3.getPos(self.render)), str(self.camera3.getHpr(self.render)))) # dt=self.taskMgr.globalClock.getDt() self.move_factor+=0.03*dt self.move_factor%=1 self.agua.setShaderInput("move_factor", self.move_factor) self.agua.setShaderInput("cam_pos", self.camera.getPos(self.render)) #self.rotador.setH(3.0*dt) if self.vel_cam!=Vec2.zero(): self.rotador.setPos(self.rotador, Vec3(self.vel_cam, 0.0)*dt) # return task.cont
class World(DirectObject): #subclassing here is necessary to accept events def __init__(self): # Marc's stuff #turn off mouse control, otherwise camera is not repositionable base.disableMouse() #camera.setPosHpr(0, -15, 7, 0, -15, 0) #self.update() self.setupLights() render.setShaderAuto() #you probably want to use this ##self.cfont = loader.loadFont('Coalition_v2.ttf') self.wave_size = 3 self.max_enemies = 6 self.score = 0 self.wave = 0 self.background_music = loader.loadSfx("sounds/bgm.wav") self.shotgun_fire = loader.loadSfx("sounds/shotgun_fire.wav") self.smg_fire = loader.loadSfx("sounds/smg_fire.wav") self.mortar_fire = loader.loadSfx("sounds/mortar_fire.wav") self.explosion_1 = loader.loadSfx("sounds/explosion_1.wav") self.explosion_2 = loader.loadSfx("sounds/explosion_2.wav") self.hit = loader.loadSfx("sounds/bullet_hit.wav") self.shotgun_load = loader.loadSfx("sounds/shotgun_load.wav") self.smg_load = loader.loadSfx("sounds/smg_load.wav") self.mortar_load = loader.loadSfx("sounds/mortar_load.wav") self.background_music.setLoop(True) # Mapping some keys self.keyMap = {"left":0, "right":0, "forward":0, "back":0, "shoot":0, "rot_left":0, "rot_right":0} self.accept("escape", self.pause) self.accept("space", self.setKey, ["shoot", 1]) self.accept("space-up",self.setKey, ["shoot", 0]) self.accept("e", self.create_explosion) self.accept("r", self.reload) self.accept("l", self.toggle_light) self.accept("1", self.setSMG) self.accept("2", self.setShotgun) self.accept("3", self.setMortar) self.accept("w", self.setKey, ["forward", 1]) self.accept("d", self.setKey, ["right", 1]) self.accept("a", self.setKey, ["left", 1]) self.accept("s", self.setKey, ["back",1]) self.accept("arrow_left", self.setKey, ["rot_left",1]) self.accept("arrow_left-up", self.setKey, ["rot_left",0]) self.accept("arrow_right", self.setKey, ["rot_right",1]) self.accept("arrow_right-up", self.setKey, ["rot_right", 0]) self.accept("mouse1", self.setKey, ["fire", True]) self.accept("w-up", self.setKey, ["forward", 0]) self.accept("d-up", self.setKey, ["right", 0]) self.accept("a-up", self.setKey, ["left", 0]) self.accept("s-up", self.setKey, ["back", 0]) self.accept("mouse1-up", self.setKey, ["fire", False]) # Empty lists to track stuff self.enemies = [] self.bullets = [] self.mortars = [] # Find the start position self.player_start = (0,0,20) # Make a player object self.player = player.Player(self) self.count = 0 #Load Environment self.environ = loader.loadModel("models/terrain") self.environ.reparentTo(render) self.environ.setScale(0.66) self.environ.setPos(0,0,0) # Setup the collision detection rays self.cTrav = CollisionTraverser() # Player Rays self.player_cgray = CollisionRay() self.player_cgray.setOrigin(0,0,100) self.player_cgray.setDirection(0,0,-1) self.player_cgcol = CollisionNode("player_gray") self.player_cgcol.addSolid(self.player_cgray) self.player_cgcol.setFromCollideMask(BitMask32.bit(0)) self.player_cgcol.setIntoCollideMask(BitMask32.allOff()) self.player_cgcolnp = self.player.actor.attachNewNode(self.player_cgcol) self.player_cghandler = CollisionHandlerQueue() self.cTrav.addCollider(self.player_cgcolnp, self.player_cghandler) # Ground Rays self.cgray=CollisionRay() self.cgray.setOrigin(0,0,100) self.cgray.setDirection(0,0,-1) self.cgcol = CollisionNode("cgray") self.cgcol.addSolid(self.cgray) self.cgcol.setFromCollideMask(BitMask32.bit(0)) self.cgcol.setIntoCollideMask(BitMask32.allOff()) self.cgcolnp = camera.attachNewNode(self.cgcol) self.cghandler = CollisionHandlerQueue() self.cTrav.addCollider(self.cgcolnp, self.cghandler) self.paused = False self.setAI() self.hud_weapon = OnscreenText(text = "WEAPON: "+ str(self.player.selected_weapon), pos = (0.75, -0.8), scale = 0.07, fg=(180,180,180,1), shadow = (0,0,0,1)) self.hud_health = OnscreenText(text = "HEALTH: "+ str(self.player.health), pos= (-0.9, -0.8), scale = 0.07, fg=(180,180,180,1), shadow=(0,0,0,1)) self.hud_ammo = OnscreenText(text = "AMMO: ", pos=(0.75, -0.9), scale=0.07, fg=(180,180,180,1), shadow=(0,0,0,1)) self.hud_wave = OnscreenText(text = "WAVE: "+str(self.wave), pos= (-0.9, -0.9), scale = 0.07, fg=(180,180,180,1), shadow=(0,0,0,1)) self.hud_score = OnscreenText(text = "SCORE: "+str(self.score),pos= (0, -0.9), scale = 0.07, fg=(180,180,180,1), shadow=(0,0,0,1)) # Set the enemy spawn points and frequenct of spawns self.wavetimer = 30 self.spawnlocs = [(-1,-30,0),(3,30,0),(-13,2,0),(13,0,0)]# self.spawnTask = taskMgr.doMethodLater(2,self.spawnEnemies,'spawnTask') #self.explosions_handler = explosions.Explosions_Manager() self.explosions_handler = explosions.Explosions_Manager() taskMgr.add(self.update, "update") taskMgr.add(self.player_shoot, "Shoot") self.background_music.setVolume(0.4) self.background_music.play() def create_explosion(self): self.explosions_handler.Small_Explosion(VBase3(0,0,3)) def setKey(self, key, value): self.keyMap[key] = value def setSMG(self): self.player.set_weapon("SMG") def setShotgun(self): self.player.set_weapon("SHOTGUN") def setMortar(self): self.player.set_weapon("MORTAR") def reload(self): self.player.reload(self) def toggle_light(self): self.player.toggle_light() def player_shoot(self, task): if not self.paused: if self.keyMap["shoot"]: self.player.fire(self) return Task.cont def setupLights(self): #ambient light self.ambientLight = AmbientLight("ambientLight") #four values, RGBA (alpha is largely irrelevent), value range is 0:1 self.ambientLight.setColor((.5, .5, .4, 1)) self.ambientLightNP = render.attachNewNode(self.ambientLight) #the nodepath that calls setLight is what gets illuminated by the light render.setLight(self.ambientLightNP) #call clearLight() to turn it off self.keyLight = DirectionalLight("keyLight") self.keyLight.setColor((.6,.6,.6, 1)) self.keyLightNP = render.attachNewNode(self.keyLight) self.keyLightNP.setHpr(0, -26, 0) render.setLight(self.keyLightNP) """ self.fillLight = DirectionalLight("fillLight") self.fillLight.setColor((.4,.4,.4, 1)) self.fillLightNP = render.attachNewNode(self.fillLight) self.fillLightNP.setHpr(30, 0, 0) render.setLight(self.fillLightNP) """ def pause(self): if not self.paused: self.paused = True self.pause_text = OnscreenText(text = "PAUSED", pos = (0, 0.5), scale = 0.1, fg=(180,180,180,1), shadow = (0,0,0,1)) self.resume_button = DirectButton(text = ("RESUME"), scale = 0.2, command = self.resume_game, pos=(0, 0, 0.0)) self.exit_button = DirectButton(text = ("EXIT"), scale = 0.2, command = self.exit_game, pos=(0, 0,-0.4)) def setAI(self): """ Set up The AI world""" # Create the world self.AIworld = AIWorld(render) # Add the AIworld updater taskMgr.add(self.AIUpdate, "AIUpdate") def spawnEnemies(self,task): print "Spawning Wave!" task.delayTime = self.wavetimer if not self.paused: if len(self.enemies) + self.wave_size <= self.max_enemies: self.wave += 1 random.seed() for i in range(self.wave_size): x = math.floor(random.uniform(0,6)) if x < 1: self.newEnemy = enemies.Enemy2(self,random.choice(self.spawnlocs),"Enemy-%d-%d"%(self.wave,i)) elif x < 4: self.newEnemy = enemies.Enemy1(self,random.choice(self.spawnlocs),"Enemy-%d-%d"%(self.wave,i)) else: self.newEnemy = enemies.Enemy3(self,random.choice(self.spawnlocs),"Enemy-%d-%d"%(self.wave,i)) self.enemies.append(self.newEnemy) self.AIworld.addAiChar(self.newEnemy.setupAI(self.player.actor)) return task.again def AIUpdate(self,task): """ Update the AIWorld """ if not self.paused: self.AIworld.update() for e in self.enemies: if e.health <= 0: e.die(self) self.enemies.remove(e) else: e.updateHeight(self) return Task.cont def resume_game(self): self.remove_pause_menu() self.paused = False def exit_game(self): self.remove_pause_menu() sys.exit() def remove_pause_menu(self): if self.pause_text: self.pause_text.removeNode() if self.resume_button: self.resume_button.removeNode() if self.exit_button: self.exit_button.removeNode() def update(self, task): self.hud_health.setText("HEALTH: " + str(self.player.health)) if str(self.player.selected_weapon) == "SMG": self.hud_weapon.setText("WEAPON: MAIN GUN") else: self.hud_weapon.setText("WEAPON: " + str(self.player.selected_weapon)) self.hud_wave.setText("WAVE: " + str(self.wave)) self.hud_score.setText("SCORE: " + str(self.score)) if self.player.health <= 25: self.hud_health.setFg((180,0,0,1)) else: self.hud_health.setFg((180,180,180,1)) if self.player.selected_weapon == "SMG": self.hud_ammo.setText("AMMO: " + str(self.player.smg_mag)) if self.player.smg_mag == 0 or self.player.smg_reloading: self.hud_ammo.setFg((180,0,0,1)) else: self.hud_ammo.setFg((180,180,180,1)) elif self.player.selected_weapon == "SHOTGUN": self.hud_weapon.setText("WEAPON: " + self.player.selected_weapon) if self.player.shotgun_mag == 0 or self.player.shotgun_reloading: self.hud_ammo.setFg((180,0,0,1)) else: self.hud_ammo.setFg((180,180,180,1)) self.hud_ammo.setText("AMMO: " + str(self.player.shotgun_mag)) else: self.hud_ammo.setText("LOADED") if self.player.mortar_loaded == False: self.hud_ammo.setFg((180,0,0,1)) else: self.hud_ammo.setFg((180,180,180,1)) if self.pause == True: print "PAUSED" if self.player.health <=0: self.game_end = True return task.cont
class MyTapper(DirectObject): def __init__(self): formatArray = GeomVertexArrayFormat() formatArray.addColumn(InternalName.make("drawFlag"), 1, Geom.NTUint8, Geom.COther) format = GeomVertexFormat(GeomVertexFormat.getV3n3cpt2()) format.addArray(formatArray) self.format = GeomVertexFormat.registerFormat(format) bodydata = GeomVertexData("body vertices", format, Geom.UHStatic) self.barkTexture = loader.loadTexture("barkTexture.jpg") treeNodePath = NodePath("Tree Holder") makeFractalTree(bodydata, treeNodePath, LVector3(4, 4, 7)) treeNodePath.setTexture(self.barkTexture, 1) treeNodePath.reparentTo(render) self.accept("q", self.regenTree) self.accept("w", self.addTree) self.accept("arrow_up", self.upIterations) self.accept("arrow_down", self.downIterations) self.accept("arrow_right", self.upCopies) self.accept("arrow_left", self.downCopies) self.numIterations = 11 self.numCopies = 4 self.upDownEvent = OnscreenText( text="Up/Down: Increase/Decrease the number of iterations (" + str(self.numIterations) + ")", parent=base.a2dTopLeft, align=TextNode.ALeft, style=1, fg=(1, 1, 1, 1), pos=(0.06, -0.22), scale=.05, mayChange=True) self.leftRightEvent = OnscreenText( text="Left/Right: Increase/Decrease branching (" + str(self.numCopies) + ")", parent=base.a2dTopLeft, align=TextNode.ALeft, style=1, fg=(1, 1, 1, 1), pos=(0.06, -0.28), scale=.05, mayChange=True) def upIterations(self): self.numIterations += 1 self.upDownEvent.setText( "Up/Down: Increase/Decrease the number of iterations (" + str(self.numIterations) + ")") def downIterations(self): self.numIterations -= 1 self.upDownEvent.setText( "Up/Down: Increase/Decrease the number of iterations (" + str(self.numIterations) + ")") def upCopies(self): self.numCopies += 1 self.leftRightEvent.setText( "Left/Right: Increase/Decrease branching (" + str(self.numCopies) + ")") def downCopies(self): self.numCopies -= 1 self.leftRightEvent.setText( "Left/Right: Increase/Decrease branching (" + str(self.numCopies) + ")") def regenTree(self): forest = render.findAllMatches("Tree Holder") forest.detach() bodydata = GeomVertexData("body vertices", self.format, Geom.UHStatic) treeNodePath = NodePath("Tree Holder") makeFractalTree(bodydata, treeNodePath, LVector3(4, 4, 7), LVector3(0, 0, 0), self.numIterations, self.numCopies) treeNodePath.setTexture(self.barkTexture, 1) treeNodePath.reparentTo(render) def addTree(self): bodydata = GeomVertexData("body vertices", self.format, Geom.UHStatic) randomPlace = LVector3(200 * random.random() - 100, 200 * random.random() - 100, 0) # randomPlace.normalize() treeNodePath = NodePath("Tree Holder") makeFractalTree(bodydata, treeNodePath, LVector3(4, 4, 7), randomPlace, self.numIterations, self.numCopies) treeNodePath.setTexture(self.barkTexture, 1) treeNodePath.reparentTo(render)
class WartsApp(ShowBase): """ The application running all the graphics. """ def __init__(self, graphicsInterface): ShowBase.__init__(self) # This is available as a global, but pylint gives an undefined-variable # warning if we use it that way. Looking at # https://www.panda3d.org/manual/index.php/ShowBase # I would have thought we could reference it as either # self.globalClock, direct.showbase.ShowBase.globalClock, or possibly # direct.showbase.globalClock, but none of those seems to work. To # avoid the pylint warnings, create self.globalClock manually. self.globalClock = ClockObject.getGlobalClock() self.graphicsInterface = graphicsInterface # Mapping from gids to entities. self.entities = {} # Set up event handling. self.mouseState = {} self.keys = {} self.setupEventHandlers() # Set up camera control. self.cameraHolder = self.render.attachNewNode('CameraHolder') self.cameraHolder.setPos(0, 0, 100) self.prevCameraHpr = (0, -80, 0) self.usingCustomCamera = True self.setCameraCustom() self.prevMousePos = None self.selectionBox = None self.selectionBoxNode = None self.selectionBoxOrigin = None # TODO[#3]: Magic numbers bad. self.resourceDisplay = OnscreenText(pos=(-0.98,.9), align=TextNode.ALeft, mayChange=True) # Define the ground plane by a normal (+z) and a point (the origin). self.groundPlane = core.Plane(core.Vec3(0, 0, 1), core.Point3(0, 0, 0)) self.graphicsInterface.graphicsReady(self) def cleanup(self): pass def interfaceMessage(self, data): # Messages from GraphicsInterface to Graphics are always internal # client messages, so no need to catch InvalidMessageError. message = deserializeMessage(data) if isinstance(message, messages.Tick): pass elif isinstance(message, cmessages.AddEntity): self.addEntity(message.gid, message.pos, message.modelPath, message.isExample, message.isUnit, message.goalSize) elif isinstance(message, cmessages.RemoveEntity): self.removeEntity(message.gid) elif isinstance(message, cmessages.MoveEntity): self.moveEntity(message.gid, message.pos) elif isinstance(message, cmessages.MarkEntitySelected): self.markSelected(message.gid, message.isSelected) elif isinstance(message, cmessages.DisplayResources): self.displayResources(message.resourceAmt) else: badIMessageCommand(message, log) def addEntity(self, gid, pos, modelPath, isExample, isUnit, goalSize): """ pos is given in graphics coordinates. goalSize, if specified, is a pair (width, height) -- the model will be scaled in the xy plane so that it's as large as possible while still fitting within that width and height. Don't pass 0 as the width or the height, because that's just not nice. """ if gid in self.entities: raise RuntimeError("Already have entity with gid {gid}." .format(gid=gid)) log.debug("Adding graphical entity %s at %s", gid, pos) x, y = pos if isExample: # The example panda from the Panda3D "Hello world" tutorial. # TODO[#9]: Figure out a more general way of specifying animations. model = Actor(modelPath, {"walk": "models/panda-walk4"}) else: model = self.loader.loadModel(getModelPath(modelPath)) # Put the model in the scene, but don't position it yet. rootNode = self.render.attachNewNode("") model.reparentTo(rootNode) # Rescale the model about its origin. The x and y coordinates of the # model's origin should be chosen as wherever it looks like the model's # center of mass is, so that rotation about the origin (in the xy # plane) feels natural. goalWidthX, goalWidthY = goalSize bound1, bound2 = model.getTightBounds() modelWidthX = abs(bound2[0] - bound1[0]) modelWidthY = abs(bound2[1] - bound1[1]) # Scale it to the largest it can be while still fitting within the goal # rect. If the aspect ratio of the goal rect is different from that of # the model, then it'll only fill that rect in one dimension. # altScaleFactor is used for sanity checks below. scaleFactor, altScaleFactor = minmax(goalWidthX / modelWidthX, goalWidthY / modelWidthY) # Sanity check the scale factor. if scaleFactor <= 0.0: if scaleFactor == 0.0: log.warn("Graphical entity %s will be scaled negatively!", gid) else: log.warn("Graphical entity %s will be scaled to zero size.", gid) else: # TODO[#9]: Currently the example panda triggers this warning. # TODO[#3]: Magic numbers bad. if altScaleFactor / scaleFactor > 1.001: log.warn("Graphical entity %s has different aspect ratio than " "its model: model of size %.3g x %.3g being scaled " "into %.3g x %.3g.", gid, modelWidthX, modelWidthY, goalWidthX, goalWidthY) model.setScale(scaleFactor) # Place the model at z=0. The model's origin should be placed so that # this looks natural -- for most units this means it should be right at # the bottom of the model, but if we add any units that are intended to # float above the ground, then this can be accomplished by just # positioning the model above its origin. rootNode.setPos(x, y, 0.0) entity = Entity(gid, model, rootNode, isExample) self.entities[gid] = entity if isUnit: # TODO[#52]: Sigh. This is a terrible hack. I guess we could pipe # through yet another bool for "is this my unit", but I don't want # to have a growing collection of bools that need to be passed into # the graphics for each unit. For now, "is this an example model?" # and "is this my unit" are equivalent, so I guess we'll just # piggyback off of isExample.... if isExample: entity.setIndicator(self.loader.loadModel( getModelPath("unit-indicator-mine.egg") )) else: entity.setIndicator(self.loader.loadModel( getModelPath("unit-indicator-notmine.egg") )) def removeEntity(self, gid): log.debug("Removing graphical entity %s", gid) entity = self.entities.pop(gid) entity.cleanup() def moveEntity(self, gid, newPos): log.debug("Moving graphical entity %s to %s", gid, newPos) entity = self.entities[gid] x, y = newPos oldX, oldY, oldZ = entity.rootNode.getPos() z = oldZ # Ensure the entity is facing the right direction. heading = math.atan2(y - oldY, x - oldX) heading *= 180.0 / math.pi # Magic angle adjustment needed to stop the panda always facing # sideways. # TODO[#9]: Establish a convention about which way _our_ models face; # figure out whether we need something like this. (Hopefully not?) heading += 90.0 entity.rootNode.setHpr(heading, 0, 0) moveInterval = entity.rootNode.posInterval(config.TICK_LENGTH, (x, y, z)) moveInterval.start() if entity.isActor and "walk" in entity.model.getAnimNames(): currFrame = entity.model.getCurrentFrame("walk") if currFrame is None: currFrame = 0 # Supposedly, it's possible to pass a startFrame and a duration to # actorInterval, instead of calculating the endFrame ourself. But # for some reason, that doesn't seem to work; if I do that, then # the animation just keeps jumping around the early frames and # never gets past frame 5 or so. I'm not sure why. For now at # least, just calculate the endFrame ourselves to work around this. log.debug("Animating entity %s from frame %s/%s", gid, currFrame, entity.model.getNumFrames("walk")) frameRate = entity.model.getAnimControl("walk").getFrameRate() endFrame = currFrame + int(math.ceil(frameRate * config.TICK_LENGTH)) animInterval = entity.model.actorInterval( "walk", loop=1, startFrame=currFrame, endFrame=endFrame ) animInterval.start() def markSelected(self, gid, isSelected): log.debug("Marking graphical entity %s as %sselected", gid, "" if isSelected else "not ") entity = self.entities[gid] if isSelected: entity.setIndicator(self.loader.loadModel( getModelPath("unit-indicator-selected.egg") )) else: # You can't currently select others' units, so if a unit is being # deselected it must be mine. entity.setIndicator(self.loader.loadModel( getModelPath("unit-indicator-mine.egg") )) def displayResources(self, resourceAmt): self.resourceDisplay.setText("Resource: {}".format(resourceAmt)) def createSelectionBox(self, corner1, corner2): """ Create a selection "box" given the coordinates of two opposite corners. The corners are given in world coordinates (well, 3d graphics coordinates). """ assert self.selectionBox is None p1, p2, p3, p4 = self.convert3dBoxToScreen(corner1, corner2) x1, y1 = p1 x2, y2 = p2 x3, y3 = p3 x4, y4 = p4 # TODO[#3]: Magic numbers bad. self.selectionBox = LineSegs("SelectionBox") self.selectionBox.setThickness(3.0) self.selectionBox.setColor(0.0, 1.0, 0.25, 1.0) self.selectionBox.move_to(x1, 0, y1) self.selectionBox.draw_to(x2, 0, y2) self.selectionBox.draw_to(x3, 0, y3) self.selectionBox.draw_to(x4, 0, y4) self.selectionBox.draw_to(x1, 0, y1) self.selectionBoxNode = self.render2d.attachNewNode( self.selectionBox.create()) def moveSelectionBox(self, corner1, corner2): assert self.selectionBox is not None p1, p2, p3, p4 = self.convert3dBoxToScreen(corner1, corner2) x1, y1 = p1 x2, y2 = p2 x3, y3 = p3 x4, y4 = p4 self.selectionBox.setVertex(0, x1, 0, y1) self.selectionBox.setVertex(1, x2, 0, y2) self.selectionBox.setVertex(2, x3, 0, y3) self.selectionBox.setVertex(3, x4, 0, y4) self.selectionBox.setVertex(4, x1, 0, y1) def removeSelectionBox(self): self.selectionBoxNode.removeNode() self.selectionBox = None self.selectionBoxNode = None def convert3dBoxToScreen(self, corner1, corner3): """ Return screen coordinates of the 4 corners of a box, given in 3d coordinates. The box is specified using 2 opposite corners. """ wx1, wy1, wz1 = corner1 wx3, wy3, wz3 = corner3 wx2, wy2 = (wx1, wy3) wx4, wy4 = (wx3, wy1) # Note: corner1 and corner2 could have nonzero z because floating-point # calculations, but they should at least be close. We'll just average # their z and not worry about it. wz2 = wz4 = 0.5 * (wz1 + wz3) p1 = self.coord3dToScreen((wx1, wy1, wz1)) p2 = self.coord3dToScreen((wx2, wy2, wz2)) p3 = self.coord3dToScreen((wx3, wy3, wz3)) p4 = self.coord3dToScreen((wx4, wy4, wz4)) return (p1, p2, p3, p4) def setCameraCustom(self): """ Change to using our custom task to control the camera. """ # Disable the default mouse-based camera control task, so we don't have # to fight with it for control of the camera. self.disableMouse() # Face the camera in the appropriate angle. self.camera.setHpr(self.prevCameraHpr) # Put it in the same location as the cameraHolder, and make it stay # put relative to the cameraHolder (so we can move the camera around by # changing the cameraHolder's position). self.camera.reparentTo(self.cameraHolder) self.camera.setPos(0, 0, 0) # Substitute our own camera control task. self.taskMgr.add(self.updateCameraTask, "UpdateCameraTask") self.usingCustomCamera = True # Need a task to handle mouse-dragging because there doesn't seem to be # a built-in mouseMove event. self.taskMgr.add(self.mouseMoveTask, "MouseMoveTask") def setCameraDefault(self): """ Change to using the default mouse-based camera controls. """ self.taskMgr.remove("UpdateCameraTask") # Save current location for when this control style is restored. self.prevCameraHpr = self.camera.getHpr() # Use the existing camera location, rather than jumping back to the one # from last time the default camera controller was active. # Copied from https://www.panda3d.org/manual/index.php/Mouse_Support mat = Mat4(self.camera.getMat()) mat.invertInPlace() self.mouseInterfaceNode.setMat(mat) self.enableMouse() self.usingCustomCamera = False def toggleCameraStyle(self): """ Switch to whichever style of camera control isn't currently active. """ if self.usingCustomCamera: self.setCameraDefault() else: self.setCameraCustom() # We don't use task, but we can't remove it because the function signature # is from Panda3D. def updateCameraTask(self, task): # pylint: disable=unused-argument """ Move the camera sensibly. """ dt = self.globalClock.getDt() translateSpeed = 30 * dt rotateSpeed = 50 * dt # Separately track whether the camera should translate in each of the 4 # directions. These 4 are initialized based on the various inputs that # might tell us to scroll, and different inputs saying the same thing # don't stack. That way if we get inputs saying both "left" and # "right", they can cancel and the camera just won't move along that # axis -- even if, say, there are two inputs saying "left" and only one # saying "right'. moveLeft = self.keys["arrow_left"] moveRight = self.keys["arrow_right"] moveUp = self.keys["arrow_up"] moveDown = self.keys["arrow_down"] # Check if the mouse is over the window. if self.mouseWatcherNode.hasMouse(): # Get the position. # Each coordinate is normalized to the interval [-1, 1]. mousePos = self.mouseWatcherNode.getMouse() xPos, yPos = mousePos.getX(), mousePos.getY() # Only move if the mouse is close to the edge, and actually within # the window. if (1.0 - EDGE_SCROLL_WIDTH) < xPos <= 1.0: moveRight = 1 if -(1.0 - EDGE_SCROLL_WIDTH) > xPos >= -1.0: moveLeft = 1 if (1.0 - EDGE_SCROLL_WIDTH) < yPos <= 1.0: moveUp = 1 if -(1.0 - EDGE_SCROLL_WIDTH) > yPos >= -1.0: moveDown = 1 forward = translateSpeed * (moveUp - moveDown) sideways = translateSpeed * (moveRight - moveLeft) self.cameraHolder.setPos(self.cameraHolder, sideways, forward, 0) if sideways != 0 or forward != 0: self.updateSelectionBox() rotate = rotateSpeed * (self.keys["a"] - self.keys["d"]) self.cameraHolder.setHpr(self.cameraHolder, rotate, 0, 0) return Task.cont def zoomCamera(self, inward): """ Zoom in or out. """ dt = self.globalClock.getDt() zoomSpeed = 100 * dt zoom = -zoomSpeed if inward else zoomSpeed self.cameraHolder.setPos(self.cameraHolder, 0, 0, zoom) def centerView(self): """ Center the view sensibly. """ message = cmessages.RequestCenter() self.graphicsInterface.graphicsMessage(message.serialize()) # We don't use task, but we can't remove it because the function signature # is from Panda3D. def mouseMoveTask(self, task): # pylint: disable=unused-argument """ Handle mouse movement. """ mousePos = self.getMousePos() # NOTE: We don't handle clicking and dragging at the same time. if mousePos is not None and mousePos != self.prevMousePos: for (buttonId, state) in self.mouseState.iteritems(): state.lastPos = mousePos if state.hasMoved: self.handleMouseDragMove(buttonId, state.modifiers, state.startPos, mousePos) else: startX, startY = state.startPos mouseX, mouseY = mousePos distance = math.hypot(mouseX - startX, mouseY - startY) # TODO[#3]: Magic numbers bad. # Check if the mouse has moved outside the dead zone. if distance > 0.0314: self.handleMouseDragStart(buttonId, state.modifiers, state.startPos, mousePos) state.hasMoved = True if mousePos != self.prevMousePos: self.prevMousePos = mousePos return Task.cont def pandaEventMouseDown(self, buttonId, modifiers): if buttonId in self.mouseState: # Call pandaEventMouseUp just to clear any state related to the # button being down, so we can handle this buttonDown event as if # it were a fresh press of the button. log.warn("Mouse button %s is already down.", buttonId) self.pandaEventMouseUp(buttonId) assert buttonId not in self.mouseState state = MouseButtonState(modifiers[:], self.getMousePos()) self.mouseState[buttonId] = state def pandaEventMouseUp(self, buttonId): if buttonId not in self.mouseState: # Drop the event, since there's nothing to do. log.warn("Mouse button %s is already up.", buttonId) return state = self.mouseState[buttonId] if state.hasMoved: endPos = self.getMousePos() if endPos is None: endPos = state.lastPos self.handleMouseDragEnd(buttonId, state.modifiers, state.startPos, endPos) else: self.handleMouseClick(buttonId, state.modifiers, state.startPos) del self.mouseState[buttonId] def handleMouseClick(self, button, modifiers, pos): # Make sure the mouse is inside the screen # TODO: Move this check to pandaEventMouseUp? if self.mouseWatcherNode.hasMouse() and self.usingCustomCamera: x, y, _z = self.coordScreenTo3d(pos) if modifiers == []: # TODO: This component should take care of decoding the # click as far as "left" or "right"; we shouldn't send a # numerical button id to the graphicsInterface. message = cmessages.Click(button, (x, y)) elif button == 1 and modifiers == ["shift"]: message = cmessages.ShiftLClick((x, y)) elif button == 1 and modifiers == ["control"]: message = cmessages.ControlLClick((x, y)) elif button == 3 and modifiers == ["shift"]: message = cmessages.ShiftRClick((x, y)) elif button == 3 and modifiers == ["control"]: message = cmessages.ControlRClick((x, y)) else: thisShouldNeverHappen( "Unhandled modifiers for click: {}".format(modifiers)) self.graphicsInterface.graphicsMessage(message.serialize()) def handleMouseDragStart(self, buttonId, modifiers, startPos, endPos): log.debug("Start dragging from %s to %s", startPos, endPos) if buttonId == 1 and modifiers == []: assert self.selectionBoxOrigin is None self.selectionBoxOrigin = self.coordScreenTo3d(startPos) endPos = self.coordScreenTo3d(endPos) self.createSelectionBox(self.selectionBoxOrigin, endPos) def handleMouseDragMove(self, buttonId, modifiers, startPos, endPos): log.debug("Continue dragging from %s to %s", startPos, endPos) if buttonId == 1 and modifiers == []: assert self.selectionBoxOrigin is not None endPos = self.coordScreenTo3d(endPos) self.moveSelectionBox(self.selectionBoxOrigin, endPos) def handleMouseDragEnd(self, buttonId, modifiers, startPos, endPos): log.debug("End dragging from %s to %s", startPos, endPos) if buttonId == 1 and modifiers == []: # Actually select the units. endPos = self.coordScreenTo3d(endPos) # TODO[#55]: Use 3d graphics coords in messages so we don't have to # remove the z coordinates everywhere. message = cmessages.DragBox(self.selectionBoxOrigin[:2], endPos[:2]) self.graphicsInterface.graphicsMessage(message.serialize()) # Clear the selection box; we're done dragging. self.selectionBoxOrigin = None self.removeSelectionBox() def updateSelectionBox(self): if self.selectionBoxOrigin is not None: mousePos = self.getMousePos() if mousePos is not None: endPos = self.coordScreenTo3d(mousePos) self.moveSelectionBox(self.selectionBoxOrigin, endPos) def getMousePos(self): # Check if the mouse is over the window. if self.mouseWatcherNode.hasMouse(): # Get the position. # Each coordinate is normalized to the interval [-1, 1]. mousePoint = self.mouseWatcherNode.getMouse() # Create a copy of mousePoint rather than returning a reference to # it, because mousePoint will be modified in place by Panda. return (mousePoint.getX(), mousePoint.getY()) else: return None def handleWindowClose(self): log.info("Window close requested -- shutting down client.") message = cmessages.RequestQuit() self.graphicsInterface.graphicsMessage(message.serialize()) def setupEventHandlers(self): def pushKey(key, value): self.keys[key] = value for key in ["arrow_up", "arrow_left", "arrow_right", "arrow_down", "w", "a", "d", "s"]: self.keys[key] = False self.accept(key, pushKey, [key, True]) self.accept("shift-%s" % key, pushKey, [key, True]) self.accept("%s-up" % key, pushKey, [key, False]) # Camera toggle. self.accept("f3", self.toggleCameraStyle, []) self.accept("shift-f3", self.toggleCameraStyle, []) # Center view. self.accept("space", self.centerView, []) # Handle mouse wheel. self.accept("wheel_up", self.zoomCamera, [True]) self.accept("wheel_down", self.zoomCamera, [False]) # Handle clicking. self.accept("mouse1", self.pandaEventMouseDown, [1, []]) self.accept("mouse1-up", self.pandaEventMouseUp, [1]) # TODO: Make sure this is always the right mouse button. self.accept("mouse3", self.pandaEventMouseDown, [3, []]) self.accept("mouse3-up", self.pandaEventMouseUp, [3]) # Handle clicking with modifier keys. self.accept("shift-mouse1", self.pandaEventMouseDown, [1, ["shift"]]) self.accept("control-mouse1", self.pandaEventMouseDown, [1, ["control"]]) self.accept("shift-mouse3", self.pandaEventMouseDown, [3, ["shift"]]) self.accept("control-mouse3", self.pandaEventMouseDown, [3, ["control"]]) # Handle window close request (clicking the X, Alt-F4, etc.) self.win.set_close_request_event("window-close") self.accept("window-close", self.handleWindowClose) def coord3dToScreen(self, coord3d): # Empirically, Lens.project takes coordinates in the *camera*'s # coordinate system, not its parent or the render. This was not very # clear from the documentation, and you'd be surprised how long it took # us to figure this out. Anyway, we need to convert the point to be # relative to self.camera here; otherwise we'll get bizarre, # nonsensical, and hard-to-debug results. coord3d = self.camera.getRelativePoint(self.render, coord3d) screenCoord = Point2() if not self.camLens.project(coord3d, screenCoord): log.debug("Attempting 3d-to-screen conversion on point outside of " "camera's viewing frustum.") # Convert to a tuple to ensure no one else is keeping a reference # around. x, y = screenCoord return (x, y) def coordScreenTo3d(self, screenCoord): x, y = screenCoord screenPoint = Point2(x, y) # Do this calculation using simple geometry, rather than the absurd # collision-traversal nonsense we used to use. Thanks to # https://www.panda3d.org/forums/viewtopic.php?t=5409 # for pointing us at the right methods to make this work. # Get two points along the ray extending from the camera, in the # direction of the mouse click. nearPoint = Point3() farPoint = Point3() self.camLens.extrude(screenPoint, nearPoint, farPoint) # These points are relative to the camera, so need to be converted to # be relative to the render. Thanks to the example code (see link # above) for saving us probably some hours of debugging figuring that # one out again :) nearPoint = self.render.getRelativePoint(self.camera, nearPoint) farPoint = self.render.getRelativePoint(self.camera, farPoint) intersection = Point3() if self.groundPlane.intersectsLine(intersection, nearPoint, farPoint): # Convert to a tuple to ensure no one else is keeping a reference # around. x, y, z = intersection return (x, y, z) # The ray didn't intersect the ground. This is almost certainly going # to happen at some point; all you have to do is find a way to aim the # camera (or manipulate the screen coordinate) so that the ray points # horizontally. But we don't have code to handle it, so for now just # abort. thisIsNotHandled()
class CameraAddons( DirectObject ): def __init__( self ): # setup key bindings keybindings = { "escape": [ sys.exit , None] , "f2" : [ self.printPos , None] , "f3" : [ self.toggleWireframe, None] , "f6" : [render.analyze , None] , "f9" : [ base.oobe , None] } # set keyboard mappings for mapping, [binding, setting] in keybindings.items(): if setting is not None: self.accept( mapping, binding, [setting] ) else: self.accept( mapping, binding ) if USESHOWPOS: self.guiposOnscreenText = OnscreenText(text = 'position', fg=(1,1,1,1), pos = (-0.9, 0.9), scale = 0.07, mayChange=True, align=TextNode.ALeft ) taskMgr.doMethodLater(0.1, self.updateGuiposTask, 'updateGuiposTask') if USESOUND: self.walkSound = loader.loadSfx("data/camera/sounds/walking.mp3") self.walkSound.setLoop(True) self.oldPos = None self.soundOn = False taskMgr.add(self.playSound, 'playSoundTask') if True: wp = WindowProperties() # set resolution wp.setSize(RESOLUTION[0], RESOLUTION[1]) # set fullscreen base.win.requestProperties(wp) # set background color to black base.setBackgroundColor( 0,0,0 ) # set camera field of view base.camLens.setFov(90) # set near and far clipping planes base.camLens.setNear( 1 ) base.camLens.setFar( 5000 ) def updateGuiposTask( self, task ): text = "%s:%s" % (str(base.camera.getPos( render )), str(base.camera.getHpr( render ))) self.guiposOnscreenText.setText( text ) return Task.cont def setToggleVerbose( self ): messenger.toggleVerbose() def playSound( self, task ): cameraPos = base.camera.getPos() if self.oldPos != cameraPos: soundOn = True else: soundOn = False self.oldPos = cameraPos if soundOn == True and self.soundOn == False: self.walkSound.play() self.soundOn = True elif soundOn == True and self.soundOn == True: pass else: self.walkSound.stop() self.soundOn = False return task.cont def toggleWireframe( self ): # toggle complete scene wireframe visualisation if render.getRenderMode() != 2: # 2 = wireframe render mode render.setRenderModeWireframe() else: render.setRenderModeFilled() def printPos( self ): cameraPos = base.camera.getPos( render ) print "current camera position is %s" % str(cameraPos) cameraHpr = base.camera.getHpr( render ) print "current camera rotation is %s" % str(cameraHpr) def map3dToAspect2d(self, node, point): #got this from the Panda3d forum. here it converts between objects on the screen and their 3D location for comparasion. # not in use currently """Maps the indicated 3-d point (a Point3), which is relative to the indicated NodePath, to the corresponding point in the aspect2d scene graph. Returns the corresponding Point3 in aspect2d. Returns None if the point is not onscreen. """ # Convert the point to the 3-d space of the camera p3 = base.cam.getRelativePoint(node, point) # Convert it through the lens to render2d coordinates p2 = Point2() if not base.camLens.project(p3, p2): return None r2d = Point3(p2[0], 0, p2[1]) # And then convert it to aspect2d coordinates a2d = aspect2d.getRelativePoint(render2d, r2d) return a2d
class Game(): HUD_TEXT_SCALE = 0.04 UPDATE_RATE = 1/60.0 MAX_PYLON_POWER = 50 def __init__(self): self.zoomLevels = deque([640, 512, 320, 1280]) self.curLev = self.zoomLevels[0] base.disableMouse() self.initCam() self.loadPhysics() self.loadLights() #map x boundary, map y boundary, amount of pylons self.map = Map(self, 150.0, 150.0, 7) self.shipList = [] self.ship1 = ShipTypes.Ship_1(self, Vec4(0.6, 0.0, 0.0, 0.0)) self.ship2 = ShipTypes.Ship_2(self, Vec4(0.0, 0.0, 0.6, 0.0)) self.ship1.setPos( Vec3(0, 120, 0) ) self.ship2.setPos( Vec3(0, -120, 0) ) self.shipList.append(self.ship1) self.shipList.append(self.ship2) self.LoadHUD() self.setKeys() self.collectibleList = [] self.pallo = CollectibleTypes.Pallo(self, Vec4(0.0, 0.3, 0.0, 0)) self.pallo.setPos( Vec3(0, 20, 0) ) self.pallo.addToCollectibleList(self.collectibleList) #self.pallo2 = CollectibleTypes.Pallo(self, Vec4(0.0, 0.3, 0.0, 0)) #self.pallo2.setPos( Vec3(30, 20, 0) ) #self.pallo2.addToCollectibleList(self.collectibleList) b=OnscreenImage(parent=render2d, image="Geminid.jpg") base.cam.node().getDisplayRegion(0).setSort(20) base.setBackgroundColor(0,0,0.0,0) self.collisionSfx = loader.loadSfx("shipcollision.wav") self.goalSfx = loader.loadSfx("goal.wav") self.victorySfx = loader.loadSfx("victory.wav") self.collision2Sfx = loader.loadSfx("pyloncollision.wav") filters = CommonFilters(base.win, base.cam) render.setShaderAuto() taskMgr.add(self.loop, 'game loop') run() def setKeys(self): base.accept('arrow_up', self.ship1.thrustOn) base.accept('arrow_up-up', self.ship1.thrustOff) base.accept('arrow_left', self.ship1.thrustLeftOn) base.accept('arrow_left-up', self.ship1.thrustLeftOff) base.accept('arrow_right', self.ship1.thrustRightOn) base.accept('arrow_right-up', self.ship1.thrustRightOff) base.accept('arrow_down', self.ship1.thrustBackOn) base.accept('arrow_down-up', self.ship1.thrustBackOff) base.accept('rshift', self.ship1.releaseBall) base.accept('w', self.ship2.thrustOn) base.accept('w-up', self.ship2.thrustOff) base.accept('a', self.ship2.thrustLeftOn) base.accept('a-up', self.ship2.thrustLeftOff) base.accept('d', self.ship2.thrustRightOn) base.accept('d-up', self.ship2.thrustRightOff) base.accept('s', self.ship2.thrustBackOn) base.accept('s-up', self.ship2.thrustBackOff) base.accept('q', self.ship2.releaseBall) base.accept('+', self.zoom) base.accept('p', self.toggleAI) def loadPhysics(self): self.physicsWorld = OdeWorld() self.physicsWorld.initSurfaceTable(1) self.physicsWorld.setSurfaceEntry( 0, 0, 1.0, # u 0.35, # elasticity 0.01, # minimum threshold for physical movement 0.01, 0.00000001, # softening 0.01, 0.01 # damping ) self.physicsWorld.setGravity(0, 0, -20) self.physicsSpace = OdeHashSpace() self.physicsSpace.setAutoCollideWorld(self.physicsWorld) self.contactGroup = OdeJointGroup() self.physicsSpace.setAutoCollideJointGroup(self.contactGroup) def LoadHUD(self): self.player1HUD = OnscreenText( text = "Player 1: " + str( self.ship1.getPoints() ), fg = (1,1,1,1), #pos = ( x, y ) pos = (0.7,0.9), align = TextNode.ALeft, scale = Game.HUD_TEXT_SCALE ) self.player2HUD = OnscreenText( text = "Player 2: " + str( self.ship2.getPoints() ), fg = (1,1,1,1), pos = (-0.7,0.9), align = TextNode.ALeft, scale = Game.HUD_TEXT_SCALE ) self.winnerText = OnscreenText( text = "Tekstia, tekstia, tekstia", fg = (1,1,1,1), pos = (-0.2, 0), align = TextNode.ALeft, scale = Game.HUD_TEXT_SCALE*3 ) # self.winnerText.setZ(200) self.winnerText.hide() def updateHUD(self): self.player1HUD.setText( "Player 1: " + str( self.ship1.getPoints() ) ) self.player2HUD.setText( "Player 2: " + str( self.ship2.getPoints() ) ) if (self.ship1.getPoints() > 9): self.winnerText.show() self.winnerText.setText( "Player 1 won " + str(self.ship1.getPoints()) + "-" + str(self.ship2.getPoints())) self.victorySfx.play() base.cam.node().getDisplayRegion(0).setSort(0) # self.Pause() if (self.ship2.getPoints() > 9): self.winnerText.show() self.winnerText.setText( "Player 2 won " + str(self.ship2.getPoints()) + "-" + str(self.ship1.getPoints())) self.victorySfx.play() base.cam.node().getDisplayRegion(0).setSort(0) def loadLights(self): light1 = DirectionalLight('light1') lightNode1 = render.attachNewNode(light1) light1.setDirection( Vec3(-1, 0.5, -0.25) ) light1.setColor( Vec4(0.6, 0.6, 0.6, 0) ) render.setLight(lightNode1) #checks all collectibles for possible collisions with ships def checkAllCollectibles(self, shipList): for collectible in self.collectibleList: collectible.hitShips(shipList) #updates all collectible positions def updateAllCollectibles(self): for collectible in self.collectibleList: collectible.update(Game.UPDATE_RATE) def applyForceAllShips(self, shipList): for ship in shipList: ship.applyForces() #updates all ship positions def updateAllShips(self, shipList): for ship in shipList: ship.update(Game.UPDATE_RATE) shipList[0].shipsCollide(shipList[1]) #checks all pylons for possible collisions with ships def checkAllPylons(self, pylonList, shipList): for pylon in pylonList: pylon.checkCollisionList(shipList) def loop(self, task): self.applyForceAllShips(self.shipList) self.physicsSpace.autoCollide() self.checkAllCollectibles(self.shipList) self.map.getBase1().checkCollision(self.ship1, self.collectibleList) self.map.getBase2().checkCollision(self.ship2, self.collectibleList) self.checkAllPylons(self.map.getPylonList(), self.shipList) self.physicsWorld.quickStep(Game.UPDATE_RATE) self.updateAllShips(self.shipList) self.updateAllCollectibles() self.contactGroup.empty() return task.cont def toggleAI(self): if taskMgr.hasTaskNamed('Simple AI'): taskMgr.remove('Simple AI') return taskMgr.add( self.chaseBallsAround, name='Simple AI', sort=None, extraArgs=(self.ship1, self.ship2, self.collectibleList, self.map.getBase1()), priority=None, uponDeath=None, appendTask=True, taskChain=None, owner=None) def chaseBallsAround(self, chaser, enemy, chaseList, base, task): pos = chaser.getPos() nearestNormedPos = 1e10000 #represents infinity nearestRelPos = [0,0] if chaser.hasBall(): chasePos = base.getPos() nearestRelPos = [ pos[0] - chasePos[0], pos[1] - chasePos[1] ] elif enemy.hasBall(): chasePos = enemy.getPos() nearestRelPos = [ pos[0] - chasePos[0], pos[1] - chasePos[1] ] else: for collectible in chaseList: chasePos = collectible.getPos() relPos = [ pos[0] - chasePos[0], pos[1] - chasePos[1] ] if (math.fabs(relPos[0]) + math.fabs(relPos[1])) < nearestNormedPos: nearestNormedPos = math.fabs(relPos[0]) + math.fabs(relPos[1]) nearestRelPos = relPos if nearestRelPos[0] > 0: chaser.thrustRightOff() chaser.thrustLeftOn() elif nearestRelPos[0] < 0: chaser.thrustLeftOff() chaser.thrustRightOn() if nearestRelPos[1] < 0: chaser.thrustBackOff() chaser.thrustOn() elif nearestRelPos[1] > 0: chaser.thrustOff() chaser.thrustBackOn() else: chaser.thrustOff() chaser.thrustBackOff() return task.cont def initCam(self): base.camera.setPos(0,0,self.curLev) base.camera.lookAt(0,0,0) def zoom(self): self.curLev = self.zoomLevels.popleft() base.camera.setPos(0, 0, self.curLev) self.zoomLevels.append(self.curLev) def shakeCam(self): taskMgr.add(self.shakeCamTask, name='ShakeCam') def shakeCamTask(self, task): oldPos = base.camera.getPos() base.camera.setPos(oldPos[0]+random.randint(-1, 1), oldPos[1]+random.randint(-1, 1), oldPos[2]+random.randint(-4, 4)) if task.time < 0.5: return task.cont self.initCam() return task.done
class Main(ShowBase): def __init__(self): ShowBase.__init__(self) global picture_names picture_names = [f for f in listdir('images') if isfile(join('images', f))] self.handScale = 1 self.handV=ZERO self.scale = 20 / self.handScale self.ex = Vec3(1,0,0) self.ez = Vec3(0,0,-1) self.leap = Leap.Controller() self.title = OnscreenText(text="Wen-Jye's Panda3D Leap Motion", style=1, fg=(1,1,0,1), pos=(0.7,-0.95), scale = .07) self.score = OnscreenText(text="", pos = (-1.3, .75), fg=(1,1,0,1), align = TextNode.ALeft, scale = .1) self.timer = OnscreenText(text="", pos = (-1.3, .85), fg=(1,1,0,1), align = TextNode.ALeft, scale = .1) self.cTrav = CollisionTraverser() self.cHandler = CollisionHandlerQueue() self.handLoader() self.tracks = self.loader.loadModel("models/tracks") self.tracks.setScale(1,1.5,1) self.tracks.setPosHpr(-3, STAGE_HEIGHT, 12, 90, 90, 90) self.train = self.loader.loadModel("models/train") self.train.setScale(1,0.5,0.5) self.train.setPosHpr(16, STAGE_HEIGHT+0.3, 12, 90, 180, 90) self.stage = self.loader.loadModel("models/stage") self.stage.setScale(0.55,0.50,0.25) self.stage.setPosHpr(0, STAGE_HEIGHT-0.5, 2, 90, 180, 90) self.mesh = self.stage.find("**/mesh_stage") self.floor = self.stage.find("**/floor") self.floor.node().setIntoCollideMask(BitMask32.bit(0)) self.wall_B = self.stage.find("**/wall_B") self.wall_B.node().setIntoCollideMask(BitMask32.bit(0)) self.wall_F = self.stage.find("**/wall_F") self.wall_F.node().setIntoCollideMask(BitMask32.bit(0)) self.wall_R = self.stage.find("**/wall_R") self.wall_R.node().setIntoCollideMask(BitMask32.bit(0)) self.wall_L = self.stage.find("**/wall_L") self.wall_L.node().setIntoCollideMask(BitMask32.bit(0)) self.buttonList = [render.attachNewNode("button_%i" % (i+1)) for i in range(3)] # @UndefinedVariable for i in range(len(self.buttonList)): self.buttonCreator(i) self.buttonList[i].detachNode() self.setLight() self.errorMsg = OnscreenText(text="", pos = (0,0), fg=(1,1,0,1), align = TextNode.ACenter, scale = .1) self.taskMgr.add(self.spinCameraTask, "SpinCameraTask") self.menuBG = self.loadImageAsPlane("tex/startScreen.jpg" ) self.menuBG.setScale(12.5,9,8.5) self.menuBG.reparentTo(self.render) self.menuBG.setPosHpr(0,STAGE_HEIGHT+1.5,-2, 0, -105, 0) self.menuBG.setTransparency(TransparencyAttrib.MAlpha) self.menuBG.setAlphaScale(1) self.taskMgr.add(self.deviceChecker, "deviceChecker") def spinCameraTask(self, task): self.camera.setPos(0,STAGE_HEIGHT+10,30) self.camera.setHpr(0,255,0) self.camLens.setFov(65) return Task.cont def loadImageAsPlane(self, filepath, yresolution = 600): tex = loader.loadTexture(filepath) # @UndefinedVariable tex.setBorderColor(Vec4(0,0,0,0)) tex.setWrapU(Texture.WMBorderColor) tex.setWrapV(Texture.WMBorderColor) cm = CardMaker(filepath + ' card') cm.setFrame(-tex.getOrigFileXSize(), tex.getOrigFileXSize(), -tex.getOrigFileYSize(), tex.getOrigFileYSize()) card = NodePath(cm.generate()) card.setTexture(tex) card.setScale(card.getScale()/ yresolution) card.flattenLight() # apply scale return card def handLoader(self): self.palm_R = self.loader.loadModel("%s/palm_R" % LOAD_HAND_FROM) # @UndefinedVariable self.palm_R_collider = self.palm_R.find("**/palm_R_collider") self.palm_R_collider.node().setIntoCollideMask(BitMask32.bit(0)) self.fing_R = [self.loader.loadModel("%s/fing%i_R" % (LOAD_HAND_FROM, i+1)) for i in range(5)] # @UndefinedVariable self.midd_R = [self.loader.loadModel("%s/m%i_R" % (LOAD_HAND_FROM, i+1)) for i in range(5)] # @UndefinedVariable self.base_R = [self.loader.loadModel("%s/b%i_R" % (LOAD_HAND_FROM, i+1)) for i in range(5)] # @UndefinedVariable self.fing_R_collider = [self.fing_R[i].find("**/fing%i_R_collider" % (i+1)) for i in range(5)] # @UndefinedVariable self.midd_R_collider = [self.midd_R[i].find("**/m%i_R_collider" % (i+1)) for i in range(5)] # @UndefinedVariable self.base_R_collider = [self.base_R[i].find("**/b%i_R_collider" % (i+1)) for i in range(5)] # @UndefinedVariable self.palm_L = self.loader.loadModel("%s/palm_L" % LOAD_HAND_FROM) # @UndefinedVariable self.palm_R_collider = self.palm_L.find("**/palm_L_collider") self.palm_R_collider.node().setIntoCollideMask(BitMask32.bit(0)) self.fing_L = [self.loader.loadModel("%s/fing%i_L" % (LOAD_HAND_FROM, i+1)) for i in range(5)] # @UndefinedVariable self.midd_L = [self.loader.loadModel("%s/m%i_L" % (LOAD_HAND_FROM, i+1)) for i in range(5)] # @UndefinedVariable self.base_L = [self.loader.loadModel("%s/b%i_L" % (LOAD_HAND_FROM, i+1)) for i in range(5)] # @UndefinedVariable self.fing_L_collider = [self.fing_L[i].find("**/fing%i_L_collider" % (i+1)) for i in range(5)] # @UndefinedVariable self.midd_L_collider = [self.midd_L[i].find("**/m%i_L_collider" % (i+1)) for i in range(5)] # @UndefinedVariable self.base_L_collider = [self.base_L[i].find("**/b%i_L_collider" % (i+1)) for i in range(5)] # @UndefinedVariable self.palm_R.setScale(self.handScale, self.handScale, self.handScale*1.5) self.palm_L.setScale(self.handScale, self.handScale, self.handScale*1.5) for f in self.fing_R: f.setScale(self.handScale, self.handScale*1.5, self.handScale*1.5) for f in self.midd_R: f.setScale(self.handScale, self.handScale*1.5, self.handScale*1.5) for f in self.base_R: f.setScale(self.handScale, self.handScale*1.5, self.handScale*1.5) for f in self.fing_L: f.setScale(self.handScale, self.handScale*1.5, self.handScale*1.5) for f in self.midd_L: f.setScale(self.handScale, self.handScale*1.5, self.handScale*1.5) for f in self.base_L: f.setScale(self.handScale, self.handScale*1.5, self.handScale*1.5) for f in self.fing_R_collider: f.node().setIntoCollideMask(BitMask32.bit(0)) for f in self.midd_R_collider: f.node().setIntoCollideMask(BitMask32.bit(0)) for f in self.base_R_collider: f.node().setIntoCollideMask(BitMask32.bit(0)) for f in self.fing_L_collider: f.node().setIntoCollideMask(BitMask32.bit(0)) for f in self.midd_L_collider: f.node().setIntoCollideMask(BitMask32.bit(0)) for f in self.base_L_collider: f.node().setIntoCollideMask(BitMask32.bit(0)) def deviceChecker(self, task): if self.leap.is_connected: if len(self.leap.frame().hands) is 0: self.errorMsg.setText("please place the hand above the device to start") return Task.cont else: base.cTrav = self.cTrav # @UndefinedVariable self.errorMsg.setText("") self.menuBG.detachNode() taskMgr.remove("handUpdater") # @UndefinedVariable self.handLoop = taskMgr.add(self.handUpdater, "handUpdater") # @UndefinedVariable self.handLoop.last = 0 self.homeInitial() return Task.done else: self.errorMsg.setText("please connect device") return Task.cont def buttonCreator(self, buttonRoot): button = loader.loadModel("models/button") # @UndefinedVariable button.setScale(0.3,0.4,0.25) button.reparentTo(self.buttonList[buttonRoot]) # @UndefinedVariable buttonMesh = button.find("**/mesh_button") myTexture = self.loader.loadTexture('tex/start_%i.png' %(buttonRoot+1)) buttonMesh.setTexture(myTexture,1) buttonCollider = button.find("**/collider_button") buttonCollider.node().setFromCollideMask(BitMask32.bit(0)) self.cTrav.addCollider(buttonCollider, self.cHandler) def cubeCreator(self, i, cubeRoot): global tempCubeList cube = loader.loadModel("models/cube") # @UndefinedVariable print(i) cube.reparentTo(tempCubeList[i][0]) # @UndefinedVariable cubeMesh = cube.find("**/mesh_cube") myTexture = self.loader.loadTexture('cubes/tex_%i.jpg' %(cubeRoot)) cubeMesh.setTexture(myTexture,1) cubeSphere = cube.find("**/collider_cube") cubeSphere.node().setFromCollideMask(BitMask32.bit(0)) self.cTrav.addCollider(cubeSphere, self.cHandler) def clamp(self, i, mn=0, mx=1): return min(max(i, mn), mx) def setLight(self): #self.ambientText = self.makeStatusLabel(0) self.ambientLight = self.render.attachNewNode(AmbientLight("ambientLight")) # Set the color of the ambient light self.ambientLight.node().setColor((1, 1, 1, 1)) self.render.setLight(self.ambientLight) self.directionalLight = self.render.attachNewNode( DirectionalLight("directionalLight")) self.directionalLight.node().setColor((.35, .35, .35, 1)) # The direction of a directional light is set as a 3D vector self.directionalLight.node().setDirection(Vec3(1, 1, -2)) # These settings are necessary for shadows to work correctly self.directionalLight.setY(6) dlens = self.directionalLight.node().getLens() dlens.setFilmSize(41, 21) dlens.setNearFar(50, 75) self.render.setLight(self.directionalLight) self.color = self.directionalLight.node().getColor() h, s, b = colorsys.rgb_to_hsv(self.color[0], self.color[1], self.color[2]) brightness = self.clamp(b + 0) r, g, b = colorsys.hsv_to_rgb(h, s, brightness) self.directionalLight.node().setColor((r, g, b, 1)) self.lightSourceSphere = self.loader.loadModel('models/sphere') self.lightSourceSphere.setColor((1, 1, 1, 1)) self.lightSourceSphere.setPos(0,STAGE_HEIGHT+4,3) self.lightSourceSphere.setScale(.25) self.lightSource = self.lightSourceSphere.attachNewNode(PointLight("lightSource")) self.lightSource.node().setAttenuation(Vec3(1, 0.04, 0.1)) self.lightSource.node().setColor((1, 1, 1, 1)) self.lightSource.node().setSpecularColor((1, 1, 1, 1)) self.render.setLight(self.lightSource) def homeInitial(self): global gameStart global returnHome global tryAgain gameStart = False tryAgain = False returnHome = False self.menuBG.reparentTo(self.render) myTexture = self.loader.loadTexture('tex/home.jpg') self.menuBG.setTexture(myTexture,1) self.buttonList[0].reparentTo(self.render) self.buttonList[0].setPosHpr(-6, STAGE_HEIGHT-1, 0, -90, 0, -105) taskMgr.remove("homeTask") # @UndefinedVariable self.menu = taskMgr.add(self.homeTask, "homeTask") # @UndefinedVariable self.menu.last = 0 def homeTask(self, task): global gameStart if pointable_finger is None: return Task.cont for i in range(len(self.buttonList)): buttonPressed = Vec3(1,1,1) for f in range(self.cHandler.getNumEntries()): entry = self.cHandler.getEntry(f) tipName = entry.getIntoNode().getName() name = entry.getFromNode().getName() if name == "collider_button" and tipName == fingerTip[pointable_finger.type]: if self.buttonPress(entry, i): buttonPressed= (Vec3(1.1,1.1,1.1)) self.buttonList[i].setScale(buttonPressed) if gameStart: self.stage.reparentTo(self.render) self.buttonList[0].detachNode() self.menuBG.detachNode() self.gameInitial(len(picture_names), True) taskMgr.remove("inGameTask") # @UndefinedVariable self.inGameTaskLoop = taskMgr.add(self.inGameTask, "inGameTask") # @UndefinedVariable self.inGameTaskLoop.last = 0 gameStart = False return Task.done else: return Task.cont def scoreInitial(self): global gameStart global returnHome global tryAgain global answer global renderedCube global score global question_list question_list.clear() gameStart = False tryAgain = False returnHome = False scoreCubes = [] for i in range(len(renderedCube)): taskMgr.remove("physicsTask_%i" % (i)) # @UndefinedVariable if len(answer)>i: self.cargos[i][0].removeNode() tempCubeList[i][0].removeNode() self.image.removeNode() self.cargos.clear() renderedCube.clear() tempCubeList.clear() answer.clear() self.train.setPosHpr(16, STAGE_HEIGHT+0.3, 12, 90, 180, 90) self.train.detachNode() self.stage.detachNode() self.tracks.detachNode() self.timer.setText("") self.score.setText("") self.menuBG.reparentTo(self.render) myTexture = self.loader.loadTexture('tex/score.jpg') self.menuBG.setTexture(myTexture,1) for i in range(len(str(score))): temp = cubeList.index(str(score)[i]) scoreCubes.append(loader.loadModel("models/cube"))# @UndefinedVariable scoreCubes[i].reparentTo(self.render) # @UndefinedVariable scoreCubes[i].setPos(3.5+(int(i)*2.4),STAGE_HEIGHT+2.5-(i*0.1),-1) scoreCubes[i].setHpr(0,-2,-15) cubeMesh = scoreCubes[i].find("**/mesh_cube") myTexture = self.loader.loadTexture('cubes/tex_%i.jpg' %(temp)) cubeMesh.setTexture(myTexture,1) self.buttonList[1].reparentTo(self.render) self.buttonList[1].setPosHpr(-7, STAGE_HEIGHT-5, 0, -90, 0, -105) self.buttonList[2].reparentTo(self.render) self.buttonList[2].setPosHpr(8.5, STAGE_HEIGHT-5, 0, -90, 0, -105) taskMgr.remove("scoreTask") # @UndefinedVariable self.scoreLoop = taskMgr.add(self.scoreTask, "scoreTask", extraArgs = [scoreCubes], appendTask=True) # @UndefinedVariable self.scoreLoop.last = 0 score = 0 def scoreTask(self, scoreCubes, task): global tryAgain global returnHome for i in range(len(self.buttonList)): buttonPressed = Vec3(1,1,1) for f in range(self.cHandler.getNumEntries()): entry = self.cHandler.getEntry(f) tipName = entry.getIntoNode().getName() name = entry.getFromNode().getName() if name == "collider_button" and tipName == fingerTip[pointable_finger.type]: if self.buttonPress(entry, i): buttonPressed= (Vec3(1.1,1.1,1.1)) self.buttonList[i].setScale(buttonPressed) if tryAgain: self.stage.reparentTo(self.render) for f in scoreCubes: f.removeNode() scoreCubes.clear() self.buttonList[1].detachNode() self.buttonList[2].detachNode() self.menuBG.detachNode() self.gameInitial(len(picture_names),True) taskMgr.remove("inGameTask") # @UndefinedVariable self.inGameTaskLoop = taskMgr.add(self.inGameTask, "inGameTask") # @UndefinedVariable self.inGameTaskLoop.last = 0 return task.done elif returnHome: for f in scoreCubes: f.removeNode() scoreCubes.clear() self.menuBG.detachNode() self.buttonList[1].detachNode() self.buttonList[2].detachNode() self.homeInitial() return task.done else: return task.cont def gameInitial(self, question, englishGame): global answer global gameStart global returnHome global tryAgain global score global question_list gameStart = False tryAgain = False returnHome = False tempQuestion= "" self.score.setText("Score: %i" % (score)) self.ballAccelV = GRAVITY self.tracks.reparentTo(self.render) self.trainV = Vec3(0,0,0) self.train.reparentTo(self.render) self.trainV = Vec3(-5,0,0) if(englishGame): temp = randint(0, question-1) while temp in question_list: temp = randint(0, question-1) tempQuestion = picture_names[temp][:picture_names[temp].index('.')] print(tempQuestion) question_list.append(temp) self.image = self.loadImageAsPlane("images/%s" % (picture_names[temp])) self.image.reparentTo(self.render) self.image.setScale(self.image.getScale()*1.2) self.image.setPosHpr(0,STAGE_HEIGHT+3.5,-11, 90, 270, 90) self.image.setTransparency(TransparencyAttrib.MAlpha) self.image.setAlphaScale(1) self.cargos = [[self.loader.loadModel("models/cargo"), -1] for i in range(len(tempQuestion))] # @UndefinedVariable for i in range(len(self.cargos)): self.cargos[i][0].reparentTo(self.render) self.cargos[i][0].setScale(1,0.3,0.3) self.cargos[i][0].setScale(1,0.32,0.32) if i == 0:self.cargos[i][0].setPosHpr(self.train.getX()+2.5, STAGE_HEIGHT+0.3, 12, 90, 180, 90) else: self.cargos[i][0].setPosHpr(self.cargos[i-1][0].getX()+2, STAGE_HEIGHT+0.3, 12, 90, 180, 90) taskMgr.remove("trainMovingTask") # @UndefinedVariable self.trainEnter = taskMgr.add(self.trainMovingTask, "trainMovingTask", extraArgs = [True], appendTask=True ) # @UndefinedVariable self.trainEnter.last = 0 usedPos = random.sample(range(0, 10), 10) for i in range(10): if i<len(tempQuestion): temp = cubeList.index(tempQuestion[i]) answer.append(temp) self.assignCube(temp, i, usedPos) else: temp = randint(10,35) while temp in answer: temp = randint(10,35) self.assignCube(temp, i, usedPos) else: temp = randint(0, question-1) while temp in question_list: temp = randint(0, question-1) tempQuestion = picture_names[temp][:picture_names[temp].index('.')] question_list.append(temp) self.image = self.loadImageAsPlane("images/%s" % (picture_names[temp])) self.image.reparentTo(self.render) self.image.setScale(self.image.getScale()*1.2) self.image.setPosHpr(0,STAGE_HEIGHT+3.5,-11, 90, 270, 90) self.image.setTransparency(TransparencyAttrib.MAlpha) self.image.setAlphaScale(1) self.cargos = [[self.loader.loadModel("models/cargo"), -1] for i in range(len(tempQuestion))] # @UndefinedVariable for i in range(len(self.cargos)): self.cargos[i][0].reparentTo(self.render) self.cargos[i][0].setScale(1,0.3,0.3) self.cargos[i][0].setScale(1,0.32,0.32) if i == 0:self.cargos[i][0].setPosHpr(self.train.getX()+2.5, STAGE_HEIGHT+0.3, 12, 90, 180, 90) else: self.cargos[i][0].setPosHpr(self.cargos[i-1][0].getX()+2, STAGE_HEIGHT+0.3, 12, 90, 180, 90) taskMgr.remove("trainMovingTask") # @UndefinedVariable self.trainEnter = taskMgr.add(self.trainMovingTask, "trainMovingTask", extraArgs = [True], appendTask=True ) # @UndefinedVariable self.trainEnter.last = 0 usedPos = random.sample(range(0, 10), 10) for i in range(10): if i<len(tempQuestion): temp = cubeList.index(tempQuestion[i]) answer.append(temp) self.assignCube(temp, i, usedPos) else: temp = randint(10,35) while temp in answer: temp = randint(10,35) self.assignCube(temp, i, usedPos) def assignCube(self, temp, i, usedPos): global renderedCube global tempCubeList pos = len(tempCubeList) renderedCube.append(temp) tempCubeList.append([render.attachNewNode("cubeRoot_%i" % (temp)), Vec3(randint(-3, 3),7,randint(-3, 3))]) # @UndefinedVariable self.cubeCreator(pos,temp) tempCubeList[pos][0].reparentTo(self.render) tempCubeList[pos][0].setPos(cubesPosList[usedPos[i]]) tempCubeList[pos][0].setHpr(0,0,0) taskMgr.remove("physicsTask_%i" % (i)) # @UndefinedVariable self.physicsTaskLoop = taskMgr.add(self.physicsTask, "physicsTask_%i" % (i),extraArgs = [pos], appendTask=True) # @UndefinedVariable self.physicsTaskLoop.last = 0 def inGameTask(self, task): global gameSuccess global score global gameInter global timer secs = timer - int(task.time) mins = int(secs/60) self.timer.setText('{:02d}:{:02d}'.format(mins, secs%60)) if secs <= -1: #score= score+22 gameInter= False self.errorMsg.setText("") taskMgr.remove("trainMovingTask") # @UndefinedVariable self.scoreInitial() return Task.done if gameInter: return Task.cont fail = True gameSuccess = True for i in range(len(answer)): if self.cargos[i][1] == -1: fail = False if answer[i] != renderedCube[self.cargos[i][1]]: gameSuccess = False if gameSuccess: self.errorMsg.setText("Success") score = score +1 self.score.setText("Score: %i" % (score)) gameInter = True taskMgr.remove("trainMovingTask") # @UndefinedVariable self.trainLeaving = taskMgr.add(self.trainMovingTask, "trainMovingTask", extraArgs = [False], appendTask=True ) # @UndefinedVariable self.trainLeaving.last = 0 elif fail: self.errorMsg.setText("FAIL") else: self.errorMsg.setText("") return Task.cont def buttonPress(self, colEntry, button): global gameStart global returnHome global tryAgain if colEntry.getFromNodePath().getPos(self.buttonList[button]).length() == 0: norm = colEntry.getSurfaceNormal(render) * -1 # The normal of the hand # @UndefinedVariable handCurSpeed = self.handV.length() # The current hand speed hitDir = colEntry.getSurfacePoint(render) - self.buttonList[button].getPos() # @UndefinedVariable hitDir.normalize() hitAngle = self.dotProduct(norm, hitDir) if hitAngle > 0 and handCurSpeed>100 and self.handV[2]<-1: if button == 0: gameStart = True elif button == 1: returnHome = True elif button == 2: tryAgain = True return True else: return False def trainMovingTask(self, arriving, task): global tempCubeList global answer global renderedCube global gameInter dt = task.time - task.last task.last = task.time if dt > .1: return Task.cont if arriving: if self.train.getX()<0: self.trainV += Vec3(1,0,0)* dt * trainAccel[len(answer)] self.train.setPos(self.train.getPos() + (self.trainV * dt)) for f in self.cargos: f[0].setPos(f[0].getPos() + (self.trainV * dt)) if self.trainV[0]>0: self.trainV = Vec3(0,0,0) return Task.done else: self.trainV += Vec3(-1,0,0)* dt * trainAccel[len(answer)] self.train.setPos(self.train.getPos() + (self.trainV * dt)) for i in range(len(answer)): newPos = self.cargos[i][0].getPos() + (self.trainV * dt) self.cargos[i][0].setPos(newPos) tempCubeList[self.cargos[i][1]][0].setPos(newPos+Vec3(0,1.4,0)) if self.cargos[len(answer)-1][0].getX()<-16: for i in range(len(renderedCube)): if len(answer)>i: self.cargos[i][0].remove_node() tempCubeList[i][0].removeNode() self.image.removeNode() tempCubeList.clear() renderedCube.clear() self.cargos.clear() answer.clear() gameInter = False self.train.setPosHpr(16, STAGE_HEIGHT+0.3, 12, 90, 180, 90) self.gameInitial(len(picture_names),True) return task.done return Task.cont def physicsTask(self, cube, task): global trigger_pinch global trigger_pinch_threshold global lastPinchFrame global pinch_cube if gameInter: return task.done isLoaded = False dt = task.time - task.last task.last = task.time if dt > .1: return Task.cont df = 0 if trigger_pinch and cube == pinch_cube: lastPinchFrame = task.time trigger_pinch_threshold = True else: df = task.time - lastPinchFrame if cube == pinch_cube: if df < 0.1 and trigger_pinch_threshold is True and trigger_pinch is False: cubeP = tempCubeList[pinch_cube][0].getPos() for f in self.cargos: cargoP = f[0].getPos() if cubeP[0]>cargoP[0]-1 and cubeP[0]<cargoP[0]+1 and cubeP[1] > cargoP[1] and cubeP[1] < cargoP[1]+4 and cubeP[2]>cargoP[2]-3 and cubeP[2]<cargoP[2]+3: tempCubeList[pinch_cube][0].setPos(cargoP+Vec3(0,1.4,0)) lastPinchFrame = 0 trigger_pinch_threshold = False f[1] = pinch_cube pinch_cube = -1 if trigger_pinch_threshold: currentPos = self.thowingTask(False) if currentPos.length() >0: tempCubeList[cube][0].setPos(currentPos) else: lastPinchFrame = 0 trigger_pinch_threshold = False elif df >= 0.1 and trigger_pinch_threshold is True: lastPinchFrame = 0 trigger_pinch_threshold = False pinch_cube = -1 tempCubeList[cube][1] = self.thowingTask(True) for f in self.cargos: if f[1] == cube: isLoaded=True if isLoaded : return Task.cont elif cube == pinch_cube and trigger_pinch_threshold: return Task.cont #if trigger_pinch_threshold is False: for i in range(self.cHandler.getNumEntries()): entry = self.cHandler.getEntry(i) name = entry.getIntoNode().getName() if name == "palm_L_collider": self.handCollideHandler(entry, cube) elif name == "palm_R_collider": self.handCollideHandler(entry, cube) elif name == "floor": self.wallCollideHandler(entry, cube) elif name == "wall_B": self.wallCollideHandler(entry, cube) elif name == "wall_F": self.wallCollideHandler(entry, cube) elif name == "wall_R": self.wallCollideHandler(entry, cube) elif name == "wall_L": self.wallCollideHandler(entry, cube) elif name == "collider_cube": self.cubeCollideHandler(entry, cube) elif trigger_pinch_threshold is False: self.handCollideHandler(entry, cube) tempCubeList[cube][1] += self.ballAccelV * dt * ACCEL if tempCubeList[cube][1].lengthSquared() > MAX_SPEED_SQ: tempCubeList[cube][1].normalize() tempCubeList[cube][1] *= MAX_SPEED tempCubeList[cube][0].setPos(tempCubeList[cube][0].getPos() + (tempCubeList[cube][1] * dt)) return Task.cont def thowingTask(self, thowing): global pinch_position global pinch_finger self.frame = self.leap.frame() temp = self.frame.hands[pinch_finger[0]].palm_velocity releaseHandV = Vec3((temp[0], temp[1], temp[2]))/self.scale thumb_tip = self.frame.hands[pinch_finger[0]].fingers[0].bone(3).next_joint joint_position = self.frame.hands[pinch_finger[0]].fingers[pinch_finger[1]].bone(3).next_joint distance = thumb_tip - joint_position release_position = joint_position + Vector(distance[0]/2, distance[1]/2, distance[2]/2) release_position = Vec3((release_position[0], release_position[1], release_position[2]))/self.scale if thowing is True: thowingV = release_position-pinch_position pinch_finger = [-1,-1] return releaseHandV else: return release_position def dotProduct(self, pos1, pos2): v1 = (round(pos1[0], 8),round(pos1[1], 8),round(pos1[2], 8)) v2 = (round(pos2[0], 8),round(pos2[1], 8),round(pos2[2], 8)) v1_u = v1 / numpy.linalg.norm(v1) v2_u = v2 / numpy.linalg.norm(v2) return numpy.dot(v1_u, v2_u) def cubeCollideHandler(self, colEntry, cube): if colEntry.getFromNodePath().getPos(tempCubeList[cube][0]).length() == 0: ballV=Vec3(0,0,0) tempCubeList[cube][1] = ballV disp = (colEntry.getSurfacePoint(render) - colEntry.getInteriorPoint(render)) # @UndefinedVariable newPos = tempCubeList[cube][0].getPos() + disp tempCubeList[cube][0].setPos(newPos) def handCollideHandler(self, colEntry, cube): if colEntry.getFromNodePath().getPos(tempCubeList[cube][0]).length() == 0: norm = colEntry.getSurfaceNormal(render) * -1 # The normal of the hand # @UndefinedVariable curSpeed = tempCubeList[cube][1].length() # The current ball speed inVec = tempCubeList[cube][1] / curSpeed # The direction of ball travel velAngle = self.dotProduct(norm, inVec) totalV = Vec3(tempCubeList[cube][1][0]+self.handV[0],tempCubeList[cube][1][1]+self.handV[1],tempCubeList[cube][1][2]+self.handV[2]) ballV=Vec3(totalV[0]/10,totalV[1]/10,totalV[2]/10) if velAngle > 0: tempCubeList[cube][1] = ballV disp = (colEntry.getSurfacePoint(render) - colEntry.getInteriorPoint(render)) # @UndefinedVariable newPos = tempCubeList[cube][0].getPos() + disp tempCubeList[cube][0].setPos(newPos) def wallCollideHandler(self, colEntry, cube): if colEntry.getFromNodePath().getPos(tempCubeList[cube][0]).length() == 0: ballV=Vec3(-tempCubeList[cube][1][0],tempCubeList[cube][1][1],tempCubeList[cube][1][2]) if colEntry.getIntoNode().getName() == "wall_F" or colEntry.getIntoNode().getName() == "wall_B": ballV=Vec3(tempCubeList[cube][1][0],tempCubeList[cube][1][1],-tempCubeList[cube][1][2]) elif colEntry.getIntoNode().getName() == "floor": ballV=Vec3(tempCubeList[cube][1][0]/2,-tempCubeList[cube][1][1]/2,tempCubeList[cube][1][2]/2) if ballV[2]<0.01: ballV[2] =0 tempCubeList[cube][1] = ballV disp = (colEntry.getSurfacePoint(render)- colEntry.getInteriorPoint(render)) # @UndefinedVariable newPos = tempCubeList[cube][0].getPos() + disp tempCubeList[cube][0].setPos(newPos) def handUpdater(self, task): self.frame = self.leap.frame() global trigger_pinch pointables = self.frame.pointables trigger_pinch = False rightHand=None if len(self.frame.hands)>0: front_pointable = pointables.frontmost for hand in self.frame.hands: if(hand.is_left and rightHand==None): self.plotHand(self.palm_L, self.fing_L, self.midd_L, self.base_L, self.frame.hands[0], 0, front_pointable) rightHand=False elif(hand.is_right and rightHand==None): self.plotHand(self.palm_R, self.fing_R, self.midd_R, self.base_R, self.frame.hands[0], 0, front_pointable) rightHand=True if(len(self.frame.hands)>1): if(rightHand): self.plotHand(self.palm_L, self.fing_L, self.midd_L, self.base_L, self.frame.hands[1], 0, front_pointable) else: self.plotHand(self.palm_R, self.fing_R, self.midd_R, self.base_R, self.frame.hands[1], 0, front_pointable) else: if(rightHand): self.plotHand(self.palm_L, self.fing_L, self.midd_L, self.base_L, None, None, front_pointable) else: self.plotHand(self.palm_R, self.fing_R, self.midd_R, self.base_R, None, None, front_pointable) else: self.plotHand(self.palm_L, self.fing_L, self.midd_L, self.base_L, None, None, None) self.plotHand(self.palm_R, self.fing_R, self.midd_R, self.base_R, None, None, None) rightHand=None return Task.cont def plotHand(self, palm, fingerTips, fingerMiddles, fingerbases, leapHand, pinchHand, front_pointable): global pinch_finger global pointable_position global pointable_finger usedFingers = 0 palmValid = False if(leapHand and leapHand.is_valid): palmValid = True palm_position, palm_quat = self.calcTrafo(leapHand.palm_position, -leapHand.palm_normal, self.ez, self.scale) palm.setPos(palm_position) #print(palm_position[2]) palm.setQuat(palm_quat) thumb_tip = leapHand.fingers[0].bone(3).next_joint self.handV=Vec3(leapHand.palm_velocity[0], leapHand.palm_velocity[1], leapHand.palm_velocity[2]) for i in range(len(leapHand.fingers)): lf = leapHand.fingers[i] if lf.is_valid: if i>0 and len(answer) >0: self.updatePinch(leapHand, thumb_tip, lf) if trigger_pinch is True: pinch_finger[0] = pinchHand pinch_finger[1] = i bf = fingerTips[usedFingers] bm = fingerMiddles[usedFingers] bb = fingerbases [usedFingers] usedFingers += 1 bf.reparentTo(self.render) tip_position, tip_quat = self.calcTrafo(lf.bone(3).next_joint, -lf.bone(3).direction, self.ex, self.scale) bf.setPos(tip_position) bf.setQuat(tip_quat) if str(front_pointable) == str(lf): pointable_position = tip_position pointable_finger = lf bm.reparentTo(self.render) m1 = lf.bone(3).next_joint+lf.bone(3).direction*30 m2 = lf.bone(2).next_joint-m1 mid_position, mid_quat = self.calcTrafo(m1, lf.bone(2).direction, self.ex, self.scale) #mid_position, mid_quat = self.calcTrafo(m1, m2, self.ex, self.scale) bm.setPos(mid_position) bm.setQuat(mid_quat) bb.reparentTo(self.render) b1 = lf.bone(2).next_joint+lf.bone(2).direction*30 b2 = leapHand.palm_position-b1 #base_position, base_quat = self.calcTrafo(b1, lf.bone(1).direction, self.ex, self.scale) base_position, base_quat = self.calcTrafo(b1, b2, self.ex, self.scale) bb.setPos(base_position) bb.setQuat(base_quat) if palmValid: palm.reparentTo(self.render) else: palm.detachNode() for i in range(usedFingers,5): fingerTips[i].detachNode() fingerMiddles[i].detachNode() fingerbases[i].detachNode() def updatePinch(self, hand, tip, finger): global tempCubeList global trigger_pinch global pinch_position global pinch_cube joint_position = finger.bone(3).next_joint distance = tip - joint_position if distance.magnitude < 35: trigger_pinch = True pinch_position = joint_position + Vector(distance[0]/2, distance[1]/2, distance[2]/2) pinch_position = Vec3((pinch_position[0], pinch_position[1], pinch_position[2]))/self.scale if trigger_pinch is True: temp = 1.5 for i in range(len(tempCubeList)): distance = pinch_position - tempCubeList[i][0].getPos() distance = Vector(distance[0], distance[1], distance[2]) if distance.magnitude<temp: temp = distance.magnitude self.unLoadedCube(i) pinch_cube = i if temp < 1.5: tempCubeList[pinch_cube][0].setPos(pinch_position) trigger_pinch = True else: trigger_pinch = False def unLoadedCube(self, cube): for f in self.cargos: if f[1] == cube: f[1]=-1 def calcTrafo(self, leapPosition, leapDirection, e_i, scale): position = Vec3((leapPosition[0], leapPosition[1], leapPosition[2]))/scale direction = Vec3((leapDirection[0], leapDirection[1], leapDirection[2])).normalized() ang = e_i.angleDeg(direction) axis = e_i.cross(direction).normalized() return position, LRotationf(axis, ang)
class Balls(ShowBase): def __init__(self): ShowBase.__init__(self) self.title = OnscreenText(text="0 balls", parent=base.a2dBottomRight, align=TextNode.ARight, fg=(1, 1, 1, 1), pos=(-0.1, 0.1), scale=.08, shadow=(0, 0, 0, 0.5)) # exit on esc self.accept('escape', sys.exit) # disable standart mouse based camera control self.disableMouse() # set camera position self.camera.setPos(0, -30, 25) self.camera.lookAt(0, 0, 0) # self.world = BulletWorld() self.world.setGravity(Vec3(0, 0, -9.81)) self.taskMgr.add(self.updateWorld, 'updateWorld') self.setupLight() # down self.makePlane(0, Vec3(0, 0, 1), (0, 0, 0), (0, 0, 0)) # up self.makePlane(1, Vec3(0, 0, -1), (0, 0, 10), (0, 0, 0)) # left self.makePlane(2, Vec3(1, 0, 0), (-5, 0, 5), (0, 0, 90)) # right self.makePlane(3, Vec3(-1, 0, 0), (5, 0, 5), (0, 0, -90)) # top self.makePlane(4, Vec3(0, 1, 0), (0, -5, 5), (0, 90, 0)) # buttom self.makePlane(5, Vec3(0, -1, 0), (0, 5, 5), (0, -90, 0)) self.accept('mouse1', self.pickBall) self.accept('mouse3', self.releaseBall) self.accept('arrow_up', partial(self.rotateCube, hpr = (0, ROTATE_SPEED, 0))) self.accept('arrow_down', partial(self.rotateCube, hpr = (0, -ROTATE_SPEED, 0))) self.accept('arrow_left', partial(self.rotateCube, hpr = (0, 0, -ROTATE_SPEED))) self.accept('arrow_right', partial(self.rotateCube, hpr = (0, 0, ROTATE_SPEED))) self.accept('space', self.shakeBalls) self.accept('page_up', self.addRandomBall) self.accept('page_down', self.rmBall) self.ballCnt = 0 self.ballColors = {} for num in xrange(DEFAULT_BALLS): self.addRandomBall() self.picked = set([]) def setupLight(self): ambientLight = AmbientLight("ambientLight") ambientLight.setColor((.8, .8, .8, 1)) directionalLight = DirectionalLight("directionalLight") directionalLight.setDirection(LVector3(0, 45, -45)) directionalLight.setColor((0.2, 0.2, 0.2, 1)) render.setLight(render.attachNewNode(directionalLight)) render.setLight(render.attachNewNode(ambientLight)) def updateWorld(self, task): dt = globalClock.getDt() # bug #1455084, simple doPhysics(dt) does nothing # looks like fixed already self.world.doPhysics(dt, 1, 1. / 60.) return task.cont def rayCollision(self): if self.mouseWatcherNode.hasMouse(): mouse = self.mouseWatcherNode.getMouse() pointFrom, pointTo = Point3(), Point3() self.camLens.extrude(mouse, pointFrom, pointTo) pointFrom = render.getRelativePoint(self.cam, pointFrom) pointTo = render.getRelativePoint(self.cam, pointTo) hits = self.world.rayTestAll(pointFrom, pointTo).getHits() return sorted(hits, key = lambda x: (x.getHitPos() - pointFrom).length()) return [] def pickBall(self): hits = self.rayCollision() for hit in hits: hit_node = hit.getNode() if 'ball' in hit_node.getName(): self.picked.add(hit_node.getName()) NodePath(hit_node.getChild(0).getChild(0)).setColor(HIGHLIGHT) def releaseBall(self): hits = self.rayCollision() if hits: foundBall = False for picked in hits: hit_node = picked.getNode() if 'ball' in hit_node.getName(): foundBall = True x, y, z = picked.getHitPos() bodies = self.world.getRigidBodies() for elem in bodies: name = elem.getName() if name in self.picked: # apply some physics node = NodePath(elem.getChild(0).getChild(0)) node_x, node_y, node_z = node.getPos(render) ix = (x - node_x) iy = (y - node_y) dir = atan2(iy, ix) dx, dy = SPEED * cos(dir), SPEED * sin(dir) elem.applyCentralImpulse(LVector3(dx, dy, z)) node.setColor(self.ballColors[elem.getName()]) if foundBall: self.picked = set([]) def rotateCube(self, hpr = (0, 0, 0)): # h, p, r = z, x, y # FIXME: something completely wrong goes here # need some time to figure it out planes = render.findAllMatches('**/plane*') for plane in planes: oldParent = plane.getParent() pivot = render.attachNewNode('pivot') pivot.setPos(render, 0, 0, 5) plane.wrtReparentTo(pivot) pivot.setHpr(render, Vec3(hpr)) if oldParent.getName() != 'render': oldParent.removeNode() def shakeBalls(self): balls = filter(lambda x: 'ball' in x.getName(), self.world.getRigidBodies()) for ball in balls: dx = uniform(-SHAKE_SPEED, SHAKE_SPEED) dy = uniform(-SHAKE_SPEED, SHAKE_SPEED) dz = uniform(-SHAKE_SPEED, SHAKE_SPEED) ball.applyCentralImpulse(LVector3(dx, dy, dz)) def updateBallsCounter(self, num): self.ballCnt += num self.title.setText('%d balls' % (self.ballCnt)) def addRandomBall(self): planes = render.findAllMatches('**/plane*') x, y, z = zip(*[tuple(plane.getPos()) for plane in planes]) xPos = uniform(min(x), max(x)) yPos = uniform(min(y), max(y)) zPos = uniform(min(z), max(z)) self.makeBall(self.ballCnt, (xPos, yPos, zPos)) self.updateBallsCounter(1) def rmBall(self): if self.ballCnt != 0: ball = render.find('**/ball_' + str(self.ballCnt - 1)) self.ballColors.pop(ball.getName()) ball.removeNode() self.updateBallsCounter(-1) def makePlane(self, num, norm, pos, hpr): shape = BulletPlaneShape(norm, 0) node = BulletRigidBodyNode('plane_' + str(num)) node.addShape(shape) physics = render.attachNewNode(node) physics.setPos(*pos) self.world.attachRigidBody(node) model = loader.loadModel('models/square') model.setScale(10, 10, 10) model.setHpr(*hpr) model.setTransparency(TransparencyAttrib.MAlpha) model.setColor(1, 1, 1, 0.25) model.reparentTo(physics) def makeColor(self): return (random(), random(), random(), 1) def makeBall(self, num, pos = (0, 0, 0)): shape = BulletSphereShape(0.5) node = BulletRigidBodyNode('ball_' + str(num)) node.setMass(1.0) node.setRestitution(.9) node.setDeactivationEnabled(False) node.addShape(shape) physics = render.attachNewNode(node) physics.setPos(*pos) self.world.attachRigidBody(node) model = loader.loadModel('models/ball') color = self.makeColor() model.setColor(color) self.ballColors['ball_' + str(num)] = color model.reparentTo(physics)