예제 #1
0
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()
예제 #2
0
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))
예제 #3
0
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
예제 #5
0
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()
예제 #7
0
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)
예제 #8
0
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))
예제 #10
0
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)
예제 #11
0
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")
예제 #12
0
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"
예제 #13
0
파일: hud.py 프로젝트: ekiefl/pooltool
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
예제 #15
0
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()
예제 #16
0
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))
예제 #17
0
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
예제 #18
0
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)
예제 #19
0
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)
예제 #20
0
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
예제 #21
0
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
예제 #23
0
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 + ")"
예제 #24
0
파일: hud.py 프로젝트: ekiefl/pooltool
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
예제 #25
0
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)
예제 #26
0
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()
예제 #27
0
	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
예제 #28
0
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)
예제 #29
0
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)
예제 #30
0
파일: parts.py 프로젝트: moonburnt/a2s3
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()
예제 #31
0
파일: hud.py 프로젝트: iPazu/Slimy
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
예제 #32
0
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()
예제 #33
0
파일: gui.py 프로젝트: arikel/openlancer
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()
예제 #34
0
					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
예제 #35
0
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
예제 #36
0
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()
예제 #37
0
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")
예제 #38
0
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))
예제 #40
0
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))"""
        
        
예제 #41
0
 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
예제 #42
0
파일: boids.py 프로젝트: lettier/boids
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 )
예제 #43
0
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()
예제 #44
0
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()
예제 #46
0
파일: menu1.py 프로젝트: cricrishi/3dracing
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
예제 #48
0
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
예제 #49
0
파일: round.py 프로젝트: H3LLB0Y/Warlocks
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
예제 #50
0
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)
예제 #52
0
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
예제 #53
0
파일: game.py 프로젝트: Ahumm/GD1P3
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
예제 #54
0
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)
예제 #55
0
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()
예제 #56
0
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
예제 #57
0
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
예제 #58
0
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)
예제 #59
0
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)