Exemple #1
0
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
Exemple #2
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
Exemple #3
0
class Console(FSM.FSM):
   def __init__(self,print_messenger_events=False):
      FSM.FSM.__init__(self,'console.fsm')
      self.defaultTransitions={'Closed':['Open'],'Open':['Closed']}
      self.lines=[]
      #
      self.textObject=OnscreenText(text='',pos=(-1.3,.95),scale=0.06,align=TextNode.ALeft)
      self.textObject.setFg((.95,.95,.95,.6))
      self.textObject.setBg((.50,.50,.50,.5))
      self.max_rows=15
      #when true, prints panda messenger events traffic
      self.print_messenger=print_messenger_events
      self.out('console ready.')

   def enterClosed(self):
      self.accept(ConfigVariableString('console-trigger').getValue(),self.demand,extraArgs=['Open'])
      self.textObject.textNode.setOverallHidden(True)

   def enterOpen(self):
      self.accept(ConfigVariableString('console-trigger').getValue(),self.demand,extraArgs=['Closed'])
      self.textObject.textNode.setOverallHidden(False)

   def exitClosed(self):
      self.ignoreAll()

   def exitOpen(self):
      self.ignoreAll()

   def out(self,*args,**kwargs):
      line=[]
      if len(args)>0:
         line.extend([str(a)+' ' for a in args])
      if len(kwargs.keys())>0:
         line.extend([str(kwargs)])
      line=''.join(line)
      print line
      self.lines.append(line)
      self.lines=self.lines[-self.max_rows:]
      self.textObject.setText('\n'.join(self.lines))

   def get_print_messenger(self):
      return self._print_messenger

   def set_print_messenger(self,b):
      '''
      defines whether or not the console shows panda's messenger output.
      '''
      self._print_messenger=b
      if b and messenger.quiet:
         messenger.toggleVerbose()
         self.task_watch_messenger=taskMgr.add(self.watch_messenger,'Console.watch_messenger')
      else:
         messenger.toggleVerbose()
         taskMgr.remove(self.task_watch_messenger)

   def watch_messenger(self,task):
      '''
      prints out panda messenger's events traffic
      '''
      self.out(str(messenger))
      messenger.clear()
      return task.again if self._print_messenger else task.done

   print_messenger=property(get_print_messenger,set_print_messenger)
class ToontownLevelEditor(ShowBase):
    notify = directNotify.newCategory("Open Level Editor")
    APP_VERSION = open('ver', 'r').read()

    def __init__(self):

        # Load the prc file prior to launching showbase in order
        # to have it affect window related stuff
        loadPrcFile('editor.prc')

        builtins.userfiles = self.config.GetString('userfiles-directory')

        if not os.path.exists(userfiles):
            pathlib.Path(userfiles).mkdir(parents=True, exist_ok=True)

        # Check for -e or -d launch options
        parser = argparse.ArgumentParser(description="Modes")
        parser.add_argument("--experimental",
                            action='store_true',
                            help="Enables experimental features")
        parser.add_argument("--debug",
                            action='store_true',
                            help="Enables debugging features")
        parser.add_argument("--noupdate",
                            action='store_true',
                            help="Disables Auto Updating")
        parser.add_argument(
            "--compiler",
            nargs="*",
            help=
            "Specify which compiler to use (Only useful if your game uses a form of "
            "libpandadna.) Valid options are 'libpandadna', for games which use the "
            "modern c++ version of libpandadna (like Toontown Offline), and 'clash', "
            "for games that use the legacy python version of libpandadna, mainly Corporate Clash"
        )

        parser.add_argument(
            "--server",
            nargs="*",
            help="Enables features exclusive to various Toontown projects",
            default='online')
        parser.add_argument(
            "--holiday",
            nargs="*",
            help="Enables holiday modes. [halloween or winter]")
        parser.add_argument(
            "--hoods",
            nargs="*",
            help="Only loads the storage files of the specified hoods",
            default=[
                'TT', 'DD', 'BR', 'DG', 'DL', 'MM', 'GS', 'GZ', 'SBHQ', 'LBHQ',
                'CBHQ', 'BBHQ', 'OZ', 'PA', 'ES', 'TUT'
            ])
        parser.add_argument(
            "dnaPath",
            nargs="?",
            help="Load the DNA file through the specified path")

        args = parser.parse_args()
        if args.experimental:
            loadPrcFileData("", "want-experimental true")
        if args.debug:
            loadPrcFileData("", "want-debug true")
        if args.compiler:
            loadPrcFileData("", f"compiler {args.compiler[0]}")
        if args.holiday:
            loadPrcFileData("", f"holiday {args.holiday[0]}")

        server = SERVER_TO_ID.get(args.server[0].lower(), DEFAULT_SERVER)
        self.server = server

        self.hoods = args.hoods
        # HACK: Check for dnaPath in args.hoods
        for hood in self.hoods[:]:
            if hood.endswith('.dna'):
                args.dnaPath = hood
                args.hoods.remove(hood)
                break

        # Check for any files we need and such
        self.__checkForFiles()

        # Import the main dlls so we don't have to repeatedly import them everywhere
        self.__importMainLibs()

        # Setup the root for Tkinter!
        self.__createTk()

        if not args.noupdate:
            loop = asyncio.get_event_loop()
            loop.run_until_complete(self.__checkUpdates())

        self.__addCullBins()

        # Now we actually start the editor
        ShowBase.__init__(self)
        aspect2d.setAntialias(AntialiasAttrib.MAuto)

        # Create the framerate meter
        flag = self.config.GetBool('show-frame-rate-meter', False)
        if flag:
            self.toggleFrameRateMeter(flag)

        from toontown.leveleditor import LevelEditor
        self.le = LevelEditor.LevelEditor()
        self.le.startUp(args.dnaPath)

    def setFrameRateMeter(self, flag):
        return

    def toggleFrameRateMeter(self, flag):
        if flag:
            if not self.frameRateMeter:
                self.frameRateMeter = OnscreenText(
                    parent=base.a2dTopRight,
                    text='',
                    pos=(-0.1125, -0.05, 0.0),
                    scale=0.05,
                    style=3,
                    bg=(0, 0, 0, 0.4),
                    font=ToontownGlobals.getToonFont())
                taskMgr.add(self.frameRateCounter, 'fps')
        else:
            if self.frameRateMeter:
                self.frameRateMeter.destroy()
                self.frameRateMeter = None

    def frameRateCounter(self, task):
        """
        Base code inspired from
        https://discourse.panda3d.org/t/trying-to-create-custom-fps-counter/25328/15
        """
        fps = globalClock.getAverageFrameRate()

        # Color is green by default
        color = (0, 0.9, 0, 1)

        # At or below 45 fps is yellow
        if fps <= 45:
            color = (1, 0.9, 0, 1)
        # At or below 30 fps is red
        elif fps <= 30:
            color = (1, 0, 0, 1)

        text = f'{round(fps, 1)} FPS'
        self.frameRateMeter.setText(text)
        self.frameRateMeter.setFg(color)

        return task.cont

    def __checkForFiles(self):
        # Make custom hood directory if it doesn't exist
        if not os.path.exists(f'{userfiles}/hoods/'):
            os.mkdir(f'{userfiles}/hoods/')
        # Make a maps directory if we don't have one
        if not os.path.isdir("maps"):
            os.mkdir("maps")
        # Make a Screenshots directory if we don't have one
        if not os.path.isdir("screenshots"):
            os.mkdir("screenshots")

    def __importMainLibs(self):
        builtin_dict = builtins.__dict__
        builtin_dict.update(
            __import__('panda3d.core', fromlist=['*']).__dict__)
        builtin_dict.update(__import__('libotp', fromlist=['*']).__dict__)
        builtin_dict.update(__import__('libtoontown', fromlist=['*']).__dict__)

    def __createTk(self):
        tkroot = Tk()
        tkroot.withdraw()
        tkroot.title("Open Level Editor")
        if sys.platform == 'win32':
            # FIXME: This doesn't work in other platforms for some reason...
            tkroot.iconbitmap("resources/openttle_ico_temp.ico")

        self.tkRoot = tkroot

    def __addCullBins(self):
        cbm = CullBinManager.getGlobalPtr()
        cbm.addBin('ground', CullBinManager.BTUnsorted, 18)
        cbm.addBin('shadow', CullBinManager.BTBackToFront, 19)

    async def __checkUpdates(self):
        import aiohttp, webbrowser
        async with aiohttp.ClientSession() as session:
            try:
                async with session.get(
                        "https://raw.githubusercontent.com/OpenToontownTools/OpenLevelEditor/master/ver"
                ) as resp:
                    ver = await resp.text()
                    ver = ver.splitlines()[0]
                    if ver != self.APP_VERSION:
                        self.notify.info(
                            f"Client is out of date! Latest: {ver} | Client: {self.APP_VERSION}"
                        )
                        if messagebox.askokcancel(
                                "Error",
                                f"Client is out of date!\nLatest: {ver} | Client: {self.APP_VERSION}. Press OK to be taken to the download page."
                        ):
                            webbrowser.open(
                                "https://github.com/OpenToontownTools/OpenLevelEditor/releases/latest"
                            )
                    else:
                        self.notify.info("Client is up to date!")
            except:
                messagebox.showerror(
                    message=
                    "There was an error checking for updates! This is likely an issue with your connection. Press OK to continue using the application."
                )
Exemple #5
0
class Life(ShowBase):
    def __init__(self):
        ShowBase.__init__(self)

        base.disableMouse()
        base.setFrameRateMeter(True)

        mydir = os.path.abspath(sys.path[0])
        mydir = Filename.fromOsSpecific(mydir).getFullpath()

        self.bgmusic = self.loader.loadMusic(mydir + '/../sounds/bgmusic.ogg')
        self.bgmusic.play()

        # Setup collision for 3d picking
        self.picker = CollisionTraverser()
        self.pq = CollisionHandlerQueue()
        # Make a collision node for our picker ray
        self.pickerNode = CollisionNode('mouseRay')
        # Attach that node to the camera since the ray will need to be positioned
        #   relative to it
        self.pickerNP = camera.attachNewNode(self.pickerNode)
        # Everything to be picked will use bit 1. This way if we were doing other
        #   collision we could separate it
        self.pickerNode.setFromCollideMask(BitMask32.bit(1))
        self.pickerRay = CollisionRay()
        self.pickerNode.addSolid(self.pickerRay)
        # Register the ray as something that can cause collisions
        self.picker.addCollider(self.pickerNP, self.pq)
        #self.picker.showCollisions(render)

        # Configure boxes and textures
        self.box = [[None for x in range(CELL_WIDTH)] for x in range(CELL_HEIGHT)]
        self.textureempty = self.loader.loadTexture(mydir + '/../textures/box.png')
        self.texturefull = self.loader.loadTexture(mydir + '/../textures/boxfull.png')

        self.textureempty.setMagfilter(Texture.FTLinear)
        self.textureempty.setMinfilter(Texture.FTLinearMipmapLinear)
        self.texturefull.setMagfilter(Texture.FTLinear)
        self.texturefull.setMinfilter(Texture.FTLinearMipmapLinear)

        self.worldnode = render.attachNewNode('worldnode')
        self.boxnode = self.worldnode.attachNewNode('boxnode')

        self.worldnode.setPos(0, 200, 0)

        for row in range(CELL_HEIGHT):
            for col in range(CELL_WIDTH):
                box = self.loader.loadModel(mydir + '/../models/cube')
                box.reparentTo(self.boxnode)
                box.setPos((CELL_WIDTH * -1) + (col * 2), 0, CELL_HEIGHT - (row * 2))
                box.setTexture(self.textureempty)

                # Cube is the name of the polygon set in blender
                box.find("**/Cube").node().setIntoCollideMask(BitMask32.bit(1))
                box.find("**/Cube").node().setTag('square', str(row) + '-' + str(col))

                self.box[row][col] = box

        # Configure cell data
        self.cells = [[0 for x in range(CELL_WIDTH)] for x in range(CELL_HEIGHT)]
        self.cells[3][6] = 1
        self.cells[4][7] = 1
        self.cells[5][5] = 1
        self.cells[5][6] = 1
        self.cells[5][7] = 1

        self.editmode = False

        taskMgr.add(self.start, 'start')

        # Setup initial event handling
        self.accept('escape', sys.exit)
        self.accept('enter', self.startgame)
        self.accept('mouse1', self.startgame)

        # Prep the main screen
        self.boxnode.setPosHpr(self.worldnode, -5, -160, 0, 60, -25, 0)
        self.readyText = OnscreenText(text='Life', pos=(0.91, 0.7), scale=0.2, fg=(255, 255, 255, 255),
                                      shadow=(0, 0, 0, 100))

    def mouserotation(self, task):
        if not self.editmode and base.mouseWatcherNode.hasMouse():
            self.boxnode.setH(self.worldnode, base.mouseWatcherNode.getMouseX() * 60)
            self.boxnode.setP(self.worldnode, -base.mouseWatcherNode.getMouseY() * 60)

        return task.cont

    def startgame(self):
        # Transition to the game start state
        taskMgr.add(self.transition, 'transition')
        interval = LerpPosHprInterval(self.boxnode, TRANSITIONPERIOD, Point3(0, 0, 0), Point3(0, 0, 0),
                                      other=self.worldnode, blendType='easeInOut')
        interval.start()

    def transition(self, task):
        self.ignore('enter')
        self.ignore('mouse1')
        self.readyText.setFg((255, 255, 255, (max(0, TRANSITIONPERIOD - task.time) / TRANSITIONPERIOD)))
        self.readyText.setShadow((0, 0, 0, (max(0, TRANSITIONPERIOD - task.time) / TRANSITIONPERIOD)))

        if task.time > TRANSITIONPERIOD:
            self.accept('enter', self.handleenter)
            self.accept('mouse1', self.selectpiece)
            taskMgr.add(self.mouserotation, 'mouserotation')
            return task.done
        else:
            return task.cont

    def selectpiece(self):
        if self.editmode:
            mpos = base.mouseWatcherNode.getMouse()
            self.pickerRay.setFromLens(base.camNode, mpos.getX(), mpos.getY())

            #Do the actual collision pass (Do it only on the squares for
            #efficiency purposes)
            self.picker.traverse(self.boxnode)
            if self.pq.getNumEntries() > 0:
                # If we have hit something, sort the hits so that the closest
                #   is first, and highlight that node
                self.pq.sortEntries()
                tag = self.pq.getEntry(0).getIntoNode().getTag('square')
                tagsplit = tag.split('-')
                row = int(tagsplit[0])
                col = int(tagsplit[1])

                # Set the highlight on the picked square
                self.cells[row][col] = (0 if self.cells[row][col] == 1 else 1)

    def start(self, task):
        if not self.editmode:
            self.processcells(self.cells)

        for row in range(CELL_HEIGHT):
            for col in range(CELL_WIDTH):
                if self.cells[row][col] == 1:
                    self.box[row][col].setTexture(self.texturefull)
                else:
                    self.box[row][col].setTexture(self.textureempty)

        return task.cont

    def handleenter(self):
        self.editmode = not self.editmode

    @staticmethod
    def countsiblingcells(cells, x, y):
        return cells[y - 1][x - 1] + \
               cells[y][x - 1] + \
               cells[(y + 1) % CELL_HEIGHT][x - 1] + \
               cells[y - 1][x] + \
               cells[(y + 1) % CELL_HEIGHT][x] + \
               cells[y - 1][(x + 1) % CELL_WIDTH] + \
               cells[y][(x + 1) % CELL_WIDTH] + \
               cells[(y + 1) % CELL_HEIGHT][(x + 1) % CELL_WIDTH]

    def processcells(self, cells):
        newcells = copy.deepcopy(cells)

        for row in range(CELL_HEIGHT):
            for col in range(CELL_WIDTH):
                neighbours = self.countsiblingcells(newcells, col, row)

                if newcells[row][col] == 1:
                    if neighbours < 2:
                        cells[row][col] = 0
                    elif 2 <= neighbours <= 3:
                        pass
                    elif neighbours > 3:
                        cells[row][col] = 0
                else:
                    if neighbours == 3:
                        cells[row][col] = 1
Exemple #6
0
class Hood(StateData):
    def __init__(self, parentFSM, doneEvent, dnaStore, hoodId):
        StateData.__init__(self, doneEvent)
        self.parentFSM = parentFSM
        self.doneEvent = doneEvent
        self.dnaStore = dnaStore
        self.hoodId = hoodId
        self.id = None
        self.titleText = None
        self.suitFog = None
        self.suitLight = None
        self.suitLightColor = (0.4, 0.4, 0.4, 1)
        self.suitFogData = [(0.3, 0.3, 0.3), 0.0025]
        self.titleColor = (1, 1, 1, 1)
        return

    def enter(self, requestStatus):
        StateData.enter(self)
        hoodId = requestStatus['hoodId']
        zoneId = requestStatus['zoneId']
        rootZone = ZoneUtil.getZoneId(hoodId)
        if base.localAvatar.getLastHood(
        ) != rootZone and hoodId != CIGlobals.MinigameArea:
            base.localAvatar.b_setLastHood(rootZone)
        if not base.localAvatar.hasDiscoveredHood(rootZone):
            hoodsDiscovered = list(base.localAvatar.getHoodsDiscovered())
            hoodsDiscovered.append(rootZone)
            base.localAvatar.b_setHoodsDiscovered(hoodsDiscovered)
        text = self.getHoodText(zoneId)
        self.titleText = OnscreenText(text,
                                      fg=self.titleColor,
                                      font=CIGlobals.getMickeyFont(),
                                      scale=0.15,
                                      pos=(0, -0.65))
        self.titleText.hide()

    def enterTheLoader(self, requestStatus):
        self.fsm.request(requestStatus['loader'], [requestStatus])

    def getHoodText(self, zoneId):
        if ZoneUtil.getWhereName(zoneId) == 'street' and zoneId < 61000:
            hoodText = CIGlobals.BranchZone2StreetName[ZoneUtil.getBranchZone(
                zoneId)]
            hoodText += '\n' + self.id
        else:
            hoodText = self.id
            if self.id != CIGlobals.MinigameArea:
                hoodText += '\n' + ZoneUtil.getWhereName(zoneId).upper()
        return hoodText

    def spawnTitleText(self, zoneId):
        hoodText = self.getHoodText(zoneId)
        self.doSpawnTitleText(hoodText)

    def doSpawnTitleText(self, hoodText):
        self.titleText.setText(hoodText)
        self.titleText.show()
        self.titleText.setColor(Vec4(*self.titleColor))
        self.titleText.clearColorScale()
        self.titleText.setFg(self.titleColor)
        seq = Sequence(
            Wait(0.1), Wait(6.0),
            self.titleText.colorScaleInterval(0.5, Vec4(1.0, 1.0, 1.0, 0.0)),
            Func(self.titleText.hide))
        seq.start()

    def hideTitleText(self):
        if self.titleText:
            self.titleText.hide()

    def exit(self):
        if self.titleText:
            self.titleText.cleanup()
            self.titleText = None
        StateData.exit(self)
        return

    def load(self):
        StateData.load(self)
        if self.storageDNAFile:
            loadDNAFile(self.dnaStore, self.storageDNAFile)
        if self.holidayDNAFile:
            loadDNAFile(self.dnaStore, self.holidayDNAFile)
        if not base.cr.holidayManager.getHoliday() == HolidayType.CHRISTMAS:
            self.createNormalSky()
        else:
            self.createSpookySky()

    def unload(self):
        self.notify.info("unload()")
        if hasattr(self, 'loader'):
            self.loader.exit()
            self.loader.unload()
            del self.loader
        del self.parentFSM
        del self.fsm
        self.dnaStore.reset_nodes()
        self.dnaStore.reset_hood_nodes()
        self.dnaStore.reset_place_nodes()
        self.dnaStore.reset_hood()
        self.dnaStore.reset_fonts()
        self.dnaStore.reset_DNA_vis_groups()
        self.dnaStore.reset_textures()
        self.dnaStore.reset_block_numbers()
        self.dnaStore.reset_block_zones()
        self.dnaStore.reset_suit_points()
        del self.dnaStore
        self.deleteCurrentSky()
        self.stopSuitEffect(0)
        self.ignoreAll()
        ModelPool.garbageCollect()
        TexturePool.garbageCollect()
        StateData.unload(self)

    def enterOff(self):
        pass

    def exitOff(self):
        pass

    def isSameHood(self, status):
        return status['hoodId'] == self.hoodId and status['shardId'] == None

    def enterQuietZone(self, requestStatus):
        base.transitions.noTransitions()
        loaderName = requestStatus['loader']
        zoneID = requestStatus['zoneId']
        where = requestStatus['where']
        if where == 'playground' or where == 'toonInterior':
            name = self.id
        elif where == 'minigame':
            name = 'Minigame'
        elif where == 'street':
            name = CIGlobals.BranchZone2StreetName[ZoneUtil.getBranchZone(
                zoneID)]
        if loaderName == 'safeZoneLoader' or loaderName == 'townLoader':
            if not loader.inBulkBlock:
                loader.beginBulkLoad(
                    'hood', name, CIGlobals.safeZoneLSRanges.get(self.id, 6))
            self.loadLoader(requestStatus)
        else:
            base.transitions.fadeScreen(1.0)

        self._quietZoneDoneEvent = uniqueName('quietZoneDone')
        self.acceptOnce(self._quietZoneDoneEvent, self.handleQuietZoneDone)
        self.quietZoneStateData = QuietZoneState(self._quietZoneDoneEvent)
        self.quietZoneStateData.load()
        self.quietZoneStateData.enter(requestStatus)

    def exitQuietZone(self):
        self.ignore(self._quietZoneDoneEvent)
        del self._quietZoneDoneEvent
        self.quietZoneStateData.exit()
        self.quietZoneStateData.unload()
        self.quietZoneStateData = None
        return

    def loadLoader(self, requestStatus):
        pass

    def handleQuietZoneDone(self):
        status = self.quietZoneStateData.getDoneStatus()
        loader.endBulkLoad('hood')
        self.fsm.request(status['loader'], [status])
        if hasattr(self, 'loader'):
            self.loader.enterThePlace(status)

    def enterSafeZoneLoader(self, requestStatus):
        self.accept(self.loaderDoneEvent, self.handleSafeZoneLoaderDone)
        self.loader.enter(requestStatus)
        self.spawnTitleText(requestStatus['zoneId'])

    def exitSafeZoneLoader(self):
        self.ignore(self.loaderDoneEvent)
        self.hideTitleText()
        self.loader.exit()
        self.loader.unload()
        del self.loader

    def handleSafeZoneLoaderDone(self):
        doneStatus = self.loader.getDoneStatus()
        if self.isSameHood(doneStatus) or doneStatus['where'] == 'minigame':
            self.fsm.request('quietZone', [doneStatus])
        else:
            self.doneStatus = doneStatus
            messenger.send(self.doneEvent)

    def createNormalSky(self):
        self.deleteCurrentSky()
        self.sky = loader.loadModel(self.skyFilename)
        if self.__class__.__name__ != 'CTHood':
            self.sky.setScale(1.0)
            self.sky.setFogOff()
        else:
            self.sky.setScale(5.0)

    def createSpookySky(self):
        self.deleteCurrentSky()
        self.sky = loader.loadModel(self.spookySkyFile)
        self.sky.setScale(5.0)
        self.sky.setFogOff()

    def deleteCurrentSky(self):
        if hasattr(self, 'sky'):
            if self.sky:
                self.sky.removeNode()
                del self.sky

    def startSuitEffect(self):
        self.stopSuitEffect()
        light = AmbientLight("suitLight")
        light.setColor(Vec4(*self.suitLightColor))
        self.suitLight = render.attachNewNode(light)
        render.setLight(self.suitLight)
        self.suitFog = Fog("suitFog")
        self.suitFog.setColor(*self.suitFogData[0])
        self.suitFog.setExpDensity(self.suitFogData[1])
        render.setFog(self.suitFog)
        self.createSpookySky()
        Hood.startSky(self)

    def stopSuitEffect(self, newSky=1):
        render.clearFog()
        if self.suitLight:
            render.clearLight(self.suitLight)
            self.suitLight.removeNode()
            self.suitLight = None
        if self.suitFog:
            self.suitFog = None
        if newSky:
            if not base.cr.holidayManager.getHoliday(
            ) == HolidayType.CHRISTMAS:
                self.createNormalSky()
            else:
                self.createSpookySky()
            self.startSky()

    def startSky(self):
        self.sky.reparentTo(camera)
        self.sky.setZ(0.0)
        self.sky.setHpr(0.0, 0.0, 0.0)
        ce = CompassEffect.make(NodePath(),
                                CompassEffect.PRot | CompassEffect.PZ)
        self.sky.node().setEffect(ce)

    def stopSky(self):
        self.sky.reparentTo(hidden)
Exemple #7
0
class MyApp(ShowBase):
    gameMode = "Intro"

    def __init__(self):
        ShowBase.__init__(self)

        #self.cameraSetup()
        self.setupKeyboard()

        self.initIntro()

    def gameChangeMode(self):
        if base.gameMode == "Intro":
            self.initIntro()
        elif base.gameMode == "Convo":
            self.initConvo()

    def initIntro(self):
        self.fadeAlpha = 0.0
        self.fadeTime = 30.0
        self.fadeInc = 1.0 / self.fadeTime
        self.fadeDir = "up"

        self.sceneImage = OnscreenImage(image="images/scene.png",
                                        scale=(1920.0 / 1080.0, 1, 1))
        self.sceneImage.setTransparency(TransparencyAttrib.MAlpha)
        self.sceneImage.setAlphaScale(self.fadeAlpha)

        self.imageNumber = 0
        self.sceneImageList = ["images/scene.png", "images/image1.jpg"]

        #self.texty = OnscreenText(str(self.fadeAlpha))

        taskMgr.add(self.gameIntroUpdate, "GameIntroUpdate")

    def gameIntroUpdate(self, task):
        self.slideManager()
        if (base.gameMode != "Intro"):
            self.gameChangeMode()
            return Task.done

        return Task.cont

    def cameraSetup(self):
        base.camLens.setAspectRatio(1920.0 / 1080.0)

    def slideManager(self):
        if self.fadeDir == "up" and self.fadeAlpha < 1:
            self.fadeAlpha += self.fadeInc
            self.sceneImage.setAlphaScale(self.fadeAlpha)
            #self.texty.setText(str(self.fadeAlpha))

        if self.fadeDir == "down" and self.fadeAlpha > 0:
            self.fadeAlpha -= self.fadeInc
            self.sceneImage.setAlphaScale(self.fadeAlpha)

        if self.fadeDir == "up" and self.fadeAlpha >= 1:
            self.fadeDir = "down"

        if self.fadeDir == "down" and self.fadeAlpha <= 0:
            if self.imageNumber < 1:
                self.fadeDir = "up"
                self.sceneImage.setImage(self.nextImage())
                self.sceneImage.setTransparency(TransparencyAttrib.MAlpha)
                self.sceneImage.setAlphaScale(self.fadeAlpha)
            else:
                self.fadeDir = "up"
                base.gameMode = "Convo"
                self.sceneImage.setImage(self.sceneImageList[self.imageNumber])
                self.sceneImage.setTransparency(TransparencyAttrib.MAlpha)
                self.sceneImage.setAlphaScale(self.fadeAlpha)

    def nextImage(self):
        self.imageNumber += 1
        return self.sceneImageList[self.imageNumber]

    def initConvo(self):
        self.textToType = "This will be used for talking\nThis is a good conversation box"
        self.textVisible = ""

        self.strOptionA = "Yes"
        self.strOptionB = "No"
        self.strOptionC = "Maybe"

        self.convoResponseSelected = False
        self.convoDepth = "1"

        self.intOptionCount = 3

        #self.txtConvo = OnscreenText(self.textVisible, align = TextNode.ALeft)
        self.txtConvo = TextNode("Texty Bastard")
        self.txtConvo.setText(self.textToType)
        self.txtReply = TextNode("reply")
        self.txtReply.setText("")
        self.intHover = 0

        #self.txtConvo.setFrameColor(0, 0, 1, 1)
        #self.txtConvo.setFrameAsMargin(0.2, 0.2, 0.1, 0.1)

        myFrame = DirectFrame(frameColor=(0.8, 0.8, 0.8, 0.4),
                              frameSize=(-1, 0, -1, 0))
        nodePathConvo = aspect2d.attachNewNode(self.txtConvo)
        nodePathConvo.setScale(0.07)
        nodePathConvo.setPos(-1, 0, -0.1)
        self.i = 0
        self.indent = 0.0
        self.selectedResponse = 0
        self.txtOptionA = OnscreenText(text="",
                                       pos=(-1, -0.6),
                                       align=TextNode.ALeft)
        self.txtOptionB = OnscreenText(text="",
                                       pos=(-1, -0.7),
                                       align=TextNode.ALeft)
        self.txtOptionC = OnscreenText(text="",
                                       pos=(-1, -0.8),
                                       align=TextNode.ALeft)

        taskMgr.add(self.gameConvoUpdate, "GameConvoUpdate")

    def gameConvoUpdate(self, task):

        if (len(self.textVisible) != len(self.textToType)):
            task.delayTime = 0.001
            while (self.i < len(self.textToType)):

                self.textVisible += self.textToType[self.i]
                self.txtConvo.setText(self.textVisible)
                self.i += 1

                return Task.again

        else:
            taskMgr.add(self.gameConvoOptions, "ConvoOptions")
            return Task.done

    def gameConvoOptions(self, task):
        self.txtOptionA.setText(self.strOptionA)
        self.txtOptionB.setText(self.strOptionB)
        self.txtOptionC.setText(self.strOptionC)

        if self.convoResponseSelected == True:
            if self.convoCheckBranch("01", self.convoDepth):
                #self.txtConvo.setText(self.convoGetStrings("01", self.convoDepth))
                self.convoNextDialogue("01", self.convoDepth)
            else:
                #self.txtConvo.setText("It DIDn't worked")
                self.convoDepth = "1"
                self.convoNextDialogue("01", self.convoDepth)
            return Task.done

        elif self.selectedResponse == 0:
            if self.intOptionCount > 0:
                self.txtOptionA.setX(-1 + self.indent)
                self.txtOptionA.setFg(fg=(1, 0, 0, 1))
            if self.intOptionCount > 1:
                self.txtOptionB.setX(-1)
                self.txtOptionB.setFg(fg=(0, 0, 0, 1))
            if self.intOptionCount > 2:
                self.txtOptionC.setX(-1)
                self.txtOptionC.setFg(fg=(0, 0, 0, 1))
            self.indent = self.getIndent(self.indent, 0.01, 0.1)
            return Task.again

        elif self.selectedResponse == 1:
            if self.intOptionCount > 0:
                self.txtOptionA.setX(-1)
                self.txtOptionA.setFg(fg=(0, 0, 0, 1))
            if self.intOptionCount > 1:
                self.txtOptionB.setX(-1 + self.indent)
                self.txtOptionB.setFg(fg=(1, 0, 0, 1))
            if self.intOptionCount > 2:
                self.txtOptionC.setX(-1)
                self.txtOptionC.setFg(fg=(0, 0, 0, 1))
            self.indent = self.getIndent(self.indent, 0.01, 0.1)
            return Task.again

        elif self.selectedResponse == 2:
            if self.intOptionCount > 0:
                self.txtOptionA.setX(-1)
                self.txtOptionA.setFg(fg=(0, 0, 0, 1))
            if self.intOptionCount > 1:
                self.txtOptionB.setX(-1)
                self.txtOptionB.setFg(fg=(0, 0, 0, 1))
            if self.intOptionCount > 2:
                self.txtOptionC.setX(-1 + self.indent)
                self.txtOptionC.setFg(fg=(1, 0, 0, 1))
            self.indent = self.getIndent(self.indent, 0.01, 0.1)
            return Task.again

    def convoGetStrings(self, npcId, depth):
        if self.convoCheckBranch(npcId, depth) != True:
            return "#Error# String Not Found\nLooking for: " + "(" + str(
                npcId) + ")." + depth + ":"
        char = ""
        line = ""
        feed = ""

        path = os.path.abspath(os.getcwd())
        f = open(path + "\\text\\stringsConvo.txt", "r")
        while line != "(" + str(npcId) + ")." + depth + ":":
            while char != ":":
                char = f.readline(1)
                line += char
            feed += "\n" + line
            if line != "(" + str(npcId) + ")." + depth + ":":
                char = ""
                line = ""
                f.readline()
        print(feed + " Selected")
        f.readline(1)
        line = f.readline()
        line = line.replace("##", "\n")
        f.close()
        return line

    def convoCheckBranch(self, npcId, depth):
        path = os.path.abspath(os.getcwd())
        f = open(path + "\\text\\stringsConvo.txt", "r")
        char = ""
        line = ""
        branchFound = False

        while line != "<END>:":
            char = ""
            line = ""
            while char != ":":
                char = f.readline(1)
                line += char
            if line == "<END>:":
                f.close()
                return False
            elif line == "(" + str(npcId) + ")." + str(depth) + ":":
                f.close()
                return True
            else:
                f.readline()

    def convoNextDialogue(self, npcId, depth):
        self.textToType = self.convoGetStrings(npcId, depth)
        self.intOptionCount = self.convoGetOptionCount(npcId, depth)

        if self.intOptionCount == 1:
            self.strOptionA = self.convoGetStrings(npcId, depth + ".A")
            self.strOptionB = ""
            self.strOptionC = ""
        elif self.intOptionCount == 2:
            self.strOptionA = self.convoGetStrings(npcId, depth + ".A")
            self.strOptionB = self.convoGetStrings(npcId, depth + ".B")
            self.strOptionC = ""
        elif self.intOptionCount == 3:
            self.strOptionA = self.convoGetStrings(npcId, depth + ".A")
            self.strOptionB = self.convoGetStrings(npcId, depth + ".B")
            self.strOptionC = self.convoGetStrings(npcId, depth + ".C")
        else:
            self.strOptionA = ""
            self.strOptionB = ""
            self.strOptionC = ""

        self.textVisible = ""
        self.txtOptionA.setText("")
        self.txtOptionB.setText("")
        self.txtOptionC.setText("")
        self.txtConvo.setText(self.textVisible)
        #self.intOptionCount = 2
        self.selectedResponse = 0
        self.i = 0
        self.convoResponseSelected = False
        taskMgr.add(self.gameConvoUpdate, "GameConvoUpdate")

    def convoGetOptionCount(self, npcId, depth):
        if self.convoCheckBranch(
                npcId, depth + ".A") and self.convoCheckBranch(
                    npcId, depth + ".B") and self.convoCheckBranch(
                        npcId, depth + ".C"):
            return 3
        elif self.convoCheckBranch(npcId,
                                   depth + ".A") and self.convoCheckBranch(
                                       npcId, depth + ".B"):
            return 2
        elif self.convoCheckBranch(npcId, depth + ".A"):
            return 1
        else:
            return 0

    def getIndent(self, value, increment, limit):
        if (value + increment >= limit):
            return limit
        else:
            return value + increment

    def setupKeyboard(self):
        self.accept("arrow_down", self.convoOptionDown)
        self.accept("arrow_up", self.convoOptionUp)
        self.accept("enter", self.convoOptionSelect)

    def convoOptionUp(self):
        self.indent = 0.0
        if self.selectedResponse == 0:
            self.selectedResponse = self.intOptionCount - 1
        elif self.selectedResponse > 0:
            self.selectedResponse -= 1

    def convoOptionDown(self):
        self.indent = 0.0
        if self.selectedResponse < self.intOptionCount - 1:
            self.selectedResponse += 1
        elif self.selectedResponse == self.intOptionCount - 1:
            self.selectedResponse = 0

    def convoOptionSelect(self):
        if self.selectedResponse == 0:
            self.convoDepth += ".A.1"
        elif self.selectedResponse == 1:
            self.convoDepth += ".B.1"
        elif self.selectedResponse == 2:
            self.convoDepth += ".C.1"

        self.convoResponseSelected = True
Exemple #8
0
class Hood(StateData):
    def __init__(self, parentFSM, doneEvent, dnaStore, hoodId):
        StateData.__init__(self, doneEvent)
        self.parentFSM = parentFSM
        self.doneEvent = doneEvent
        self.dnaStore = dnaStore
        self.hoodId = hoodId
        self.abbr = ""
        self.id = None
        self.titleText = None
        self.suitFog = None
        self.suitLight = None
        self.suitLightColor = (0.4, 0.4, 0.4, 1)
        self.suitFogData = [(0.3, 0.3, 0.3), 0.0025]
        self.titleColor = (1, 1, 1, 1)

        self.wantLighting = True

        self.olc = ZoneUtil.getOutdoorLightingConfig(self.hoodId)

        return

    def makeLampLight(self, lamp):
        col = (255, 255, 255, 350)
        lightNP = CIGlobals.makePointLight(
            'DLlamp', CIGlobals.colorFromRGBScalar255(col),
            lamp.getPos(render) + (0, 0, 9.5), 0.1)
        lamp.setLightOff(1)
        return lightNP

    def enter(self, requestStatus):
        StateData.enter(self)

        hoodId = requestStatus['hoodId']
        zoneId = requestStatus['zoneId']
        rootZone = ZoneUtil.getZoneId(hoodId)
        if base.localAvatar.getLastHood(
        ) != rootZone and hoodId != ZoneUtil.MinigameArea:
            base.localAvatar.b_setLastHood(rootZone)
        if not base.localAvatar.hasDiscoveredHood(rootZone):
            hoodsDiscovered = list(base.localAvatar.getHoodsDiscovered())
            hoodsDiscovered.append(rootZone)
            base.localAvatar.b_setHoodsDiscovered(hoodsDiscovered)
        text = self.getHoodText(zoneId)
        self.titleText = OnscreenText(text,
                                      fg=self.titleColor,
                                      font=CIGlobals.getMickeyFont(),
                                      scale=0.15,
                                      pos=(0, -0.65))
        self.titleText.hide()

    def enterTheLoader(self, requestStatus):
        self.fsm.request(requestStatus['loader'], [requestStatus])

    def getHoodText(self, zoneId):
        if ZoneUtil.getWhereName(zoneId) == 'street' and zoneId < 61000:
            hoodText = ZoneUtil.BranchZone2StreetName[ZoneUtil.getBranchZone(
                zoneId)]
            hoodText += '\n' + self.id
        else:
            hoodText = self.id
            if self.id != ZoneUtil.MinigameArea:
                whereName = ZoneUtil.getWhereName(zoneId)

                if whereName == 'toonInterior':
                    whereName = 'Unknown'
                    try:
                        whereName = ZoneUtil.zone2TitleDict.get(zoneId)[0]
                        return whereName.upper() + '\n' + self.id
                    except:
                        pass

                hoodText += '\n' + whereName.upper()
        return hoodText

    def spawnTitleText(self, zoneId):
        hoodText = self.getHoodText(zoneId)
        self.doSpawnTitleText(hoodText)

    def doSpawnTitleText(self, hoodText):
        self.titleText.setText(hoodText)
        self.titleText.show()
        self.titleText.setColor(Vec4(*self.titleColor))
        self.titleText.clearColorScale()
        self.titleText.setFg(self.titleColor)
        seq = Sequence(
            Wait(0.1), Wait(6.0),
            self.titleText.colorScaleInterval(0.5, Vec4(1.0, 1.0, 1.0, 0.0)),
            Func(self.hideTitleText))
        seq.start()

    def hideTitleText(self):
        if self.titleText:
            self.titleText.hide()

    def exit(self):
        if self.titleText:
            self.titleText.cleanup()
            self.titleText = None
        StateData.exit(self)
        return

    def setupOutdoorLighting(self):
        self.olc.setup()

    def enableOutdoorLighting(self):
        self.olc.apply()

    def disableOutdoorLighting(self):
        self.olc.unapply()

    def cleanupOutdoorLighting(self):
        self.olc.cleanup()

    def load(self):
        StateData.load(self)
        if self.storageDNAFile:
            loadDNAFile(self.dnaStore, self.storageDNAFile)
        if self.holidayDNAFile:
            loadDNAFile(self.dnaStore, self.holidayDNAFile)

        self.setupOutdoorLighting()

    def unload(self):
        self.cleanupOutdoorLighting()

        if hasattr(self, 'loader'):
            self.loader.exit()
            self.loader.unload()
            del self.loader
        del self.parentFSM
        del self.fsm
        self.dnaStore.reset_nodes()
        self.dnaStore.reset_hood_nodes()
        self.dnaStore.reset_place_nodes()
        self.dnaStore.reset_hood()
        self.dnaStore.reset_fonts()
        self.dnaStore.reset_DNA_vis_groups()
        self.dnaStore.reset_materials()
        self.dnaStore.reset_block_numbers()
        self.dnaStore.reset_block_zones()
        self.dnaStore.reset_suit_points()
        del self.dnaStore
        self.ignoreAll()

        #CIGlobals.doSceneCleanup()

        StateData.unload(self)

    def enterOff(self):
        pass

    def exitOff(self):
        pass

    def isSameHood(self, status):
        return status['hoodId'] == self.hoodId and status['shardId'] is None

    def enterQuietZone(self, requestStatus):
        base.transitions.noTransitions()
        loaderName = requestStatus['loader']
        zoneID = requestStatus['zoneId']
        where = requestStatus['where']
        if where == 'playground' or where == 'toonInterior':
            name = self.id
        elif where == 'minigame':
            name = 'Minigame'
        elif where == 'street':
            name = ZoneUtil.BranchZone2StreetName[ZoneUtil.getBranchZone(
                zoneID)]
        if loaderName == 'safeZoneLoader' or loaderName == 'townLoader':
            if not loader.inBulkBlock:
                loader.beginBulkLoad('hood', name,
                                     ZoneUtil.safeZoneLSRanges.get(self.id, 6))
            self.loadLoader(requestStatus)
        else:
            base.transitions.fadeScreen(1.0)

        self._quietZoneDoneEvent = uniqueName('quietZoneDone')
        self.acceptOnce(self._quietZoneDoneEvent, self.handleQuietZoneDone)
        self.quietZoneStateData = QuietZoneState(self._quietZoneDoneEvent)
        self.quietZoneStateData.load()
        self.quietZoneStateData.enter(requestStatus)

    def exitQuietZone(self):
        self.ignore(self._quietZoneDoneEvent)
        del self._quietZoneDoneEvent
        self.quietZoneStateData.exit()
        self.quietZoneStateData.unload()
        self.quietZoneStateData = None
        return

    def loadLoader(self, requestStatus):
        pass

    def handleQuietZoneDone(self):
        status = self.quietZoneStateData.getDoneStatus()
        loader.endBulkLoad('hood')
        self.fsm.request(status['loader'], [status])
        if hasattr(self, 'loader'):
            self.loader.enterThePlace(status)

    def enterSafeZoneLoader(self, requestStatus):
        self.accept(self.loaderDoneEvent, self.handleSafeZoneLoaderDone)
        self.loader.enter(requestStatus)
        self.spawnTitleText(requestStatus['zoneId'])

    def exitSafeZoneLoader(self):
        self.ignore(self.loaderDoneEvent)
        self.hideTitleText()
        self.loader.exit()
        self.loader.unload()
        del self.loader

    def handleSafeZoneLoaderDone(self):
        doneStatus = self.loader.getDoneStatus()
        if self.isSameHood(doneStatus) or doneStatus['where'] == 'minigame':
            self.fsm.request('quietZone', [doneStatus])
        else:
            self.doneStatus = doneStatus
            messenger.send(self.doneEvent)
Exemple #9
0
class ScoreScreen(GameScreen):
    def __init__(self, screen_manager):
        '''
        Constructor
        '''
        super(ScoreScreen, self).__init__(screen_manager, 'score_screen')

        self.player_text = OnscreenText(
            "Player 1",
            1,
            font=base.fontLoader.load('digital.ttf'),
            fg=(1, 1, 1, 1),
            pos=(0, .93),
            align=TextNode.ACenter,
            scale=.1,
            mayChange=True,
            parent=self.node2d)

        self.score_text = OnscreenText("00",
                                       1,
                                       font=base.fontLoader.load('arial.ttf'),
                                       fg=((0.0 / 255.0), (255.0 / 255.0),
                                           (255.0 / 255.0), 1),
                                       pos=(0, .8),
                                       align=TextNode.ACenter,
                                       scale=.15,
                                       mayChange=True,
                                       parent=self.node2d)

        self.ball_text = OnscreenText(
            "BALL 1",
            1,
            font=base.fontLoader.load('motorwerk.ttf'),
            fg=(1, 1, 1, 1),
            pos=(1.15, 0.92),
            scale=.1,
            mayChange=True,
            parent=self.node2d)

        self.acmag_text = DMDSpriteFont("assets/sprites/num_font_dotmatrix",
                                        self.node2d,
                                        sX=0.2,
                                        sY=0.2,
                                        sZ=0.2)
        self.acmag_text.hide()
        self.acmag_text.setPos((1.0, 0, 0.7))

        self.clock = OnscreenImage(image='assets/images/time.png',
                                   pos=(0.78, 0, 0.93),
                                   parent=self.node2d,
                                   scale=.06)

        self.bonus2x = OnscreenImage(image='assets/images/2x.png',
                                     pos=(-1.25, 0, 0.93),
                                     parent=self.node2d,
                                     scale=.06)
        self.bonus3x = OnscreenImage(image='assets/images/3x.png',
                                     pos=(-1.25, 0, 0.93),
                                     parent=self.node2d,
                                     scale=.06)
        self.bonus4x = OnscreenImage(image='assets/images/4x.png',
                                     pos=(-1.25, 0, 0.93),
                                     parent=self.node2d,
                                     scale=.06)
        self.bonus5x = OnscreenImage(image='assets/images/5x.png',
                                     pos=(-1.25, 0, 0.93),
                                     parent=self.node2d,
                                     scale=.06)
        self.cfb = OnscreenImage(image='assets/images/cfb.png',
                                 pos=(-1.1, 0, 0.93),
                                 parent=self.node2d,
                                 scale=.06)

        self.sj = OnscreenImage(image='assets/images/hud_superjets.png',
                                pos=(-1.0, 0, 0.93),
                                parent=self.node2d,
                                scale=.06)

        self.sj_text = OnscreenText("25",
                                    1,
                                    font=base.fontLoader.load('motorwerk.ttf'),
                                    fg=(1, 0, 0, 1),
                                    pos=(-0.5, 0.92),
                                    scale=.1,
                                    mayChange=True,
                                    parent=self.node2d)

        self.timer_text = OnscreenText(
            "--",
            1,
            font=base.fontLoader.load('motorwerk.ttf'),
            fg=(1, 0, 0, 1),
            pos=(0.88, 0.92),
            scale=.1,
            mayChange=True,
            parent=self.node2d)

        modInfo = self.place_model(model_name="spinner.egg",
                                   scale=(0.1, 0.2, 0.2),
                                   pos=(-23, 120, -30),
                                   rotate=False,
                                   p=7,
                                   h=15,
                                   reference="spinner")

        self.random_award_text = OnscreenText(
            "",
            1,
            font=base.fontLoader.load('eurostile.ttf'),
            fg=(0, 1, 0, 1),
            pos=(0, 0, 0),
            scale=.15,
            mayChange=True,
            parent=self.node2d)

        #modInfo['interval'] = modInfo['model'].hprInterval( 0.6, Vec3(15,450,0) )
        #modInfo['interval'].loop()
        modInfo['interval'] = None

        self.spinner = modInfo

        self.laser_millions = OnscreenImage(
            parent=self.node2d,  # Parented to our 2d node renderer
            image="assets/images/laser_millions.png",  # File name specified
            pos=(0, 0, -2),  # z: -2 is off screen at the bottom
            scale=(0.3, 0.3, 0.3)
        )  # Scale it down a bit horizontally and vertically to make it look right

        self.ef_bonus = OnscreenImage(
            parent=self.node2d,  # Parented to our 2d node renderer
            image="assets/images/edgar_friendly.png",  # File name specified
            pos=(0, 0, 0),  # z: -2 is off screen at the bottom
            scale=(0.3, 0.3, 0.3)
        )  # Scale it down a bit horizontally and vertically to make it look right

        self.ef_bonus_task = None
        self.toggle_ef = False
        self.ef_bonus.hide()

        self.top_popper_award = OnscreenImage(
            parent=self.node2d,  # Parented to our 2d node renderer
            image="assets/images/top_award_bg.png",  # File name specified
            pos=(0, 0, 0),  # z: -2 is off screen at the bottom
            scale=(0.75, 0.3, 0.3),
            sort=-20,
        )  # Scale it down a bit horizontally and vertically to make it look right

        self.top_popper_award.hide()

        self.standup_collected = OnscreenImage(
            parent=self.node2d,  # Parented to our 2d node renderer
            image="assets/images/standup_spotted.png",  # File name specified
            pos=(0, 0, -2),  # z: -2 is off screen at the bottom
            scale=(0.6, 0.3, 0.4)
        )  # Scale it down a bit horizontally and vertically to make it look right

        self.mtlM = Sprite(parent=self.node,
                           file_name="assets/sprites/mtl/m/m",
                           file_type="png",
                           num_frames=33,
                           int_padding=4,
                           scale=(2.5, 2.5, 2.5),
                           pos=(6, 40, 15))
        self.mtlT = Sprite(parent=self.node,
                           file_name="assets/sprites/mtl/t/t",
                           file_type="png",
                           num_frames=33,
                           int_padding=4,
                           scale=(2.5, 2.5, 2.5),
                           pos=(9, 40, 15))

        self.mtlL = Sprite(parent=self.node,
                           file_name="assets/sprites/mtl/l/l",
                           file_type="png",
                           num_frames=33,
                           int_padding=4,
                           scale=(2.5, 2.5, 2.5),
                           pos=(12, 40, 15))

        self.retina = Sprite(parent=self.node,
                             file_name="assets/sprites/retina/retina_scan_",
                             file_type="png",
                             num_frames=36,
                             int_padding=2,
                             scale=(7.5, 7.5, 7.5),
                             pos=(-10, 40, 0),
                             auto_gc=False)

        self.hide_m()
        self.hide_t()
        self.hide_l()
        self.hide_retina()

    def set_award_text(self, text):
        self.random_award_text.setText(text)

    def show_top_award(self):
        self.top_popper_award.show()
        self.random_award_text.show()

    def hide_top_award(self):
        self.random_award_text.hide()
        self.top_popper_award.hide()

    def spin_spinner(self):
        blue_side = 3435
        red_side = 3255

        if random.randint(1, 2) == 1:
            angle = blue_side
        else:
            angle = red_side

        if self.spinner['interval'] != None:
            self.spinner['interval'].finish()
            self.spinner['interval'] = None

        self.spinner['model'].setP(0)
        self.spinner['interval'] = self.spinner['model'].hprInterval(
            3, Vec3(15, angle, 0), blendType='easeOut')
        self.spinner['interval'].start()

    def update_acmag_text(self, text):
        self.acmag_text.setText(text)
        self.acmag_text.show()

    def hide_acmag_text(self):
        self.acmag_text.hide()

    def update_timer_text(self, text):
        self.timer_text.setText(text)

    def update_score(self, player, score):
        self.player_text.setText(str(player))
        if score == 0:
            self.score_text.setText("00")
        else:
            #self.score_text.setText(str(locale.format("%d", score, grouping=True)))
            self.score_text.setText(str(base.format_score(score)))

    def update_ball(self, ball):
        self.ball_text.setText("BALL " + str(ball))
        self.update_hud()

    def show_score(self):
        self.player_text.show()
        self.score_text.show()

    def hide_score(self):
        self.player_text.hide()
        self.score_text.hide()

    def hide_ball(self):
        self.ball_text.hide()

    def show_ball(self):
        self.ball_text.show()

    def hide_timer(self):
        self.timer_text.hide()
        self.clock.hide()

    def show_timer(self):
        self.timer_text.show()
        self.clock.show()

    def blink_score(self):
        i = Sequence(
            LerpColorScaleInterval(self.score_text, 0.5, VBase4(0, 0, 1, 1)),
            LerpColorScaleInterval(self.score_text, 0.5, VBase4(1, 1, 1, 1)))

        i.start()

    def set_score_color(self, color):
        self.score_text.setFg(color)

    def show_laser_millions(self):
        # Load our trunk bonus image, parent it to our 2d renderer

        # We must also enable transparency on the image otherwise we get big ugly black squares
        self.laser_millions.setTransparency(TransparencyAttrib.MAlpha)

        # Set up a sequence to perform the animation in, pause and out... "sequentially"
        s = Sequence(
            # Lerp stands for "linearly interpolate", so we move from one position to the other with
            # an 'easeOut' blend so it comes to a nice slow stop at the end instead of an abrupt finish
            LerpPosInterval(self.laser_millions,
                            0.7,
                            pos=(-1, 0, 0.7),
                            startPos=(-3, 0, 0.7),
                            blendType='easeOut'),
            # Pause the sequence for 2.5 seconds
            Wait(2.5),
            # Animate back to our home position (off screen) with an ease in so it starts moving gradually
            LerpPosInterval(self.laser_millions,
                            0.7,
                            pos=(-3, 0, 0.7),
                            blendType='easeIn'))
        # Fire off the sequence
        s.start()

    def show_standup_collected(self):
        # Load our trunk bonus image, parent it to our 2d renderer

        # We must also enable transparency on the image otherwise we get big ugly black squares
        self.standup_collected.setTransparency(TransparencyAttrib.MAlpha)

        # Set up a sequence to perform the animation in, pause and out... "sequentially"
        s = Sequence(
            # Lerp stands for "linearly interpolate", so we move from one position to the other with
            # an 'easeOut' blend so it comes to a nice slow stop at the end instead of an abrupt finish
            LerpPosInterval(self.standup_collected,
                            0.7,
                            pos=(0, 0, 0),
                            startPos=(-3, 0, 0),
                            blendType='easeOut'),
            # Pause the sequence for 2.5 seconds
            Wait(2.5),
            # Animate back to our home position (off screen) with an ease in so it starts moving gradually
            LerpPosInterval(self.standup_collected,
                            0.7,
                            pos=(-3, 0, 0),
                            blendType='easeIn'))
        # Fire off the sequence
        s.start()

    def show_ef_bonus(self):
        if self.ef_bonus_task != None: return
        self.ef_bonus.show()
        self.ef_bonus_task = base.taskMgr.doMethodLater(
            0.01, self.toggle_ef_bonus, 'ef_bonus')

    def toggle_ef_bonus(self, task):
        self.toggle_ef = not self.toggle_ef

        if self.toggle_ef:
            self.ef_bonus.hide()
        else:
            self.ef_bonus.show()

        return task.again

    def hide_ef_bonus(self):
        if self.ef_bonus_task != None:
            base.taskMgr.remove(self.ef_bonus_task)
            self.ef_bonus.hide()
            self.ef_bonus_task = None

    def show_m(self):
        self.mtlM.show()

    def show_t(self):
        self.mtlT.show()

    def show_l(self):
        self.mtlL.show()

    def hide_m(self):
        self.mtlM.hide()

    def hide_t(self):
        self.mtlT.hide()

    def hide_l(self):
        self.mtlL.hide()

    def show_retina(self):
        self.retina.show(1)

    def hide_retina(self):
        self.retina.hide()

    def update_hud(self):
        self.bonus2x.hide()
        self.bonus3x.hide()
        self.bonus4x.hide()
        self.bonus5x.hide()

        self.cfb.hide()
        self.sj.hide()
        self.sj_text.hide()

        if base.hwgame.current_player().bonus_x == 2: self.bonus2x.show()
        if base.hwgame.current_player().bonus_x == 3: self.bonus3x.show()
        if base.hwgame.current_player().bonus_x == 4: self.bonus4x.show()
        if base.hwgame.current_player().bonus_x >= 5: self.bonus5x.show()

        if base.hwgame.current_player().call_for_backup: self.cfb.show()

        if base.hwgame.current_player().super_jets:
            self.sj.show()
            self.sj_text.setText(
                str(base.hwgame.current_player().super_jets_left))
Exemple #10
0
class example_sounds(BaseNodeScript):
    '''
    Gives an example of how to play and manage sounds. 
    
    The code below runs as the managing script of the example_sounds node which is defined in example_sounds.node .
    Such managing scripts are termed NodeScript and are essentially an FSM linked with a node for the purpose of
    managing its state. Nodescripts are optional though, nodes can be defined without a nodescript.
    
    Being state machines in nature, you will methods such as 'enter', 'exit' and 'update'. The 'enter' method
    will be called only once, at the time the node becomes active. Likewise 'exit' will be called only once, when
    the node becomes inactive. On the other hand 'update' will be invoked with the game logic update, so many times
    per second.         
    '''

    def __init__(self, game, node):
        BaseNodeScript.__init__(self, game, 'SoundsExample', node)
        self.log = logging.getLogger('SoundsExample')
        
        # reference to sounds fx player
        self.sounds = None
        
        # the following set of fields are UI labels
        self.instructions = None
        self.soundsStatusText = None
        self.volumeText = None
        self.rateText = None
        self.balanceText = None
        self.loopText = None
        self.eventText = None
        
        # reference to the 'blah' sound 
        self.blahSound = None
        
        # holds the status of sounds, if True then sounds are globally enabled
        self.lastStatus = True
        
        # flags that indicate if the respective property has been update by the user
        self.updateVolume = False
        self.updateRate = False
        self.updateBalance = False
        self.updateLooping = False
        
        # 
        self.looping = 0

            
    def registerMessages(self):        
        '''
        The purpose of this method is to declare the list of messages IDs for which we are interested to receive. 
        Here we are interested in a single message besides the standard list of message IDs returned by the
        base class.
        It is not necessary to include the list of messages from the base class but it contains some very useful
        message IDs like game_paused, game_resumed, etc., so most probably you will want to do this.
        '''
        return ['sound_finished'].extend(BaseNodeScript.registerMessages(self))
            
            
    def enter(self):
        '''
        Here we initialize some fields and flags and setup our UI which constists only of labels.
        '''
        
        # call the super class implementation first, this is optional
        BaseNodeScript.enter(self)
        
        self.sounds = self.game.getSoundsFx()
                
        # hold the camera fixed
        self.game.getView().getCameraController().disable()
        
        # display instructions
        self.instructions = OnscreenText(text = 'Press 1 for blah-blah, 2 for cling and 3 for zipper',
                                         pos = (base.a2dLeft + 0.1, 0.9),
                                         align = TextNode.ALeft,
                                         scale = 0.07,
                                         fg = (1.0, 1.0, 1.0, 1.0),
                                         shadow = (0.0, 0.0, 0.0, 0.7)
                                         )
        
        # gets the status of sounds
        self.lastStatus = self.sounds.isEnabled()
        
        self.soundsStatusText = OnscreenText(text = 'Sounds status: %s' % self.lastStatus,
                                             pos = (base.a2dLeft + 0.1, 0.8),
                                             align = TextNode.ALeft,
                                             scale = 0.07,
                                             fg = (1.0, 1.0, 1.0, 1.0),
                                             shadow = (0.0, 0.0, 0.0, 0.7),
                                             mayChange = True
                                             )
        
        self.volumeText = OnscreenText(text = 'Volume: %.1f' % self.sounds.getVolume(),
                                             pos = (base.a2dLeft + 0.1, 0.7),
                                             align = TextNode.ALeft,
                                             scale = 0.07,
                                             fg = (1.0, 1.0, 1.0, 1.0),
                                             shadow = (0.0, 0.0, 0.0, 0.7),
                                             mayChange = True
                                             )
        
        self.rateText = OnscreenText(text = 'Rate: %.1f' % self.sounds.getPlayRate(),
                                             pos = (base.a2dLeft + 0.1, 0.6),
                                             align = TextNode.ALeft,
                                             scale = 0.07,
                                             fg = (1.0, 1.0, 1.0, 1.0),
                                             shadow = (0.0, 0.0, 0.0, 0.7),
                                             mayChange = True
                                             )
        
        self.balanceText = OnscreenText(text = 'Balance: %.1f' % self.sounds.getBalance(),
                                             pos = (base.a2dLeft + 0.1, 0.5),
                                             align = TextNode.ALeft,
                                             scale = 0.07,
                                             fg = (1.0, 1.0, 1.0, 1.0),
                                             shadow = (0.0, 0.0, 0.0, 0.7),
                                             mayChange = True
                                             )
        
        self.loopText = OnscreenText(text = 'Looping: %d' % self.looping,
                                             pos = (base.a2dLeft + 0.1, 0.4),
                                             align = TextNode.ALeft,
                                             scale = 0.07,
                                             fg = (1.0, 1.0, 1.0, 1.0),
                                             shadow = (0.0, 0.0, 0.0, 0.7),
                                             mayChange = True
                                             )
        
        self.eventText = OnscreenText(text = 'Finished event received',
                                             pos = (base.a2dLeft + 0.1, 0.3),
                                             align = TextNode.ALeft,
                                             scale = 0.07,
                                             fg = (1.0, 0.0, 0.0, 1.0),
                                             shadow = (0.0, 0.0, 0.0, 0.7),
                                             mayChange = True
                                             )
        self.eventText.hide()
        
        OnscreenText(text = 'Press P, R to pause/resume playing sounds',
                                             pos = (base.a2dLeft + 0.1, 0.2),
                                             align = TextNode.ALeft,
                                             scale = 0.05,
                                             fg = (1.0, 1.0, 1.0, 1.0),
                                             shadow = (0.0, 0.0, 0.0, 0.7),
                                             mayChange = True
                                             )
        OnscreenText(text = 'Press L, Shift-L to increase/decrease the loop count',
                                             pos = (base.a2dLeft + 0.1, 0.1),
                                             align = TextNode.ALeft,
                                             scale = 0.05,
                                             fg = (1.0, 1.0, 1.0, 1.0),
                                             shadow = (0.0, 0.0, 0.0, 0.7),
                                             mayChange = True
                                             )
        OnscreenText(text = 'Press +, - to increase/decrease playing rate',
                                             pos = (base.a2dLeft + 0.1, 0.0),
                                             align = TextNode.ALeft,
                                             scale = 0.05,
                                             fg = (1.0, 1.0, 1.0, 1.0),
                                             shadow = (0.0, 0.0, 0.0, 0.7),
                                             mayChange = True
                                             )
        OnscreenText(text = 'Press [, ] to decrease/increase sound volume',
                                             pos = (base.a2dLeft + 0.1, -0.1),
                                             align = TextNode.ALeft,
                                             scale = 0.05,
                                             fg = (1.0, 1.0, 1.0, 1.0),
                                             shadow = (0.0, 0.0, 0.0, 0.7),
                                             mayChange = True
                                             )
        OnscreenText(text = 'Press D, E to disable/enable sounds',
                                             pos = (base.a2dLeft + 0.1, -0.2),
                                             align = TextNode.ALeft,
                                             scale = 0.05,
                                             fg = (1.0, 1.0, 1.0, 1.0),
                                             shadow = (0.0, 0.0, 0.0, 0.7),
                                             mayChange = True
                                             )
        OnscreenText(text = 'Press B, Shift-B to increase/decrease balance',
                                             pos = (base.a2dLeft + 0.1, -0.3),
                                             align = TextNode.ALeft,
                                             scale = 0.05,
                                             fg = (1.0, 1.0, 1.0, 1.0),
                                             shadow = (0.0, 0.0, 0.0, 0.7),
                                             mayChange = True
                                             )
        
        
        
        # add our input mappings to the active mappings, the existing mappings were not deleted
        # but they can be partially overridden by this.
        self.game.getInput().addMappings('sounds')
        
        
    def exit(self):
        '''
        Performs some cleanup.
        '''
        
        # call the super class implementation first, this is optional
        BaseNodeScript.exit(self)
        if self.instructions is not None:
            self.instructions.destroy()                
            
        # this will stop all active sounds
        if self.sounds is not None:
            self.sounds.stopAll()
            
            
    def update(self, millis):
        '''
        Gets called on every logic update and we use it to update the UI texts based on user input actions.
        The millis parameter is the milliseconds that elapsed since the last logic update.
        '''
        
        # call the super class implementation first, this is optional
        BaseNodeScript.update(self, millis)
        
        # detects if sounds status has been toggled in order to update the UI label
        if self.lastStatus != self.sounds.isEnabled():
            self.lastStatus = self.sounds.isEnabled()
            self.soundsStatusText.setText('Sounds status: %s' % self.lastStatus)
            
        # updates the volume label if needed
        if self.updateVolume:
            self.volumeText.setText('Volume: %.1f' % self.sounds.getVolume())
            self.updateVolume = False
        
        # updates the rate label if needed
        if self.updateRate:
            self.rateText.setText('Rate: %.1f' % self.sounds.getPlayRate())
            self.updateRate = False
            
        # updates the balance label if needed
        if self.updateBalance:
            self.balanceText.setText('Balance: %.1f' % self.sounds.getBalance())
            self.updateBalance = False
            
        # updates the looping label if needed
        if self.updateLooping:
            self.loopText.setText('Looping: %d' % self.looping)
            self.updateLooping = False
            
    
    def onInputAction(self, action):
        '''
        When an input action occurs the active nodescript will get notified through this method. 
        The given parameter is the name of the action that occured.
        Here we just branch based on the action name. You can see the defined actions of this example in data/example_sounds/sounds.mappings. 
        
        You return a True value to indicate that you handled the action and False to indicate that you ignored it.
        '''
        if action == "play_blah":
            '''
            We play the blah sound but keep a reference to it in order to have only one instance of this sound.
            The first time we call sounds.playSound to create the sound and get back a SoundPlaybackInterface 
            which we use for controlling playback. Notice that in the call to playSound we don't provide a filename.
            That's because the sound's properties, along with the filename, is defined in a .sound file name blah.sound.
            The file is located at data/example_sounds/blah.sound
            On subsequent invocations of this action we only call SoundPlaybackInterface.play() to get the sound
            playing.                        
            '''
            if self.blahSound is None:
                self.blahSound = self.sounds.playSound('blah', rate = self.sounds.getPlayRate(), loop = self.looping)
            else:
                self.blahSound.play()
                
        elif action == "play_cling":
            '''
            The sound is defined in data/example_sounds/cling.sound. We do not keep a reference to the playback interface
            here. Instead we create a new sound each time the action gets invoked.
            '''
            self.sounds.playSound('cling', rate = self.sounds.getPlayRate(), loop = self.looping)
            
        elif action == "play_zipper":
            '''
            For the zipper sound we instead provide a filename and use Sounds.playSoundFile for that purpose.
            We also don't keep a reference to the playback interface so a new sound is created each time.
            '''
            self.sounds.playSoundFile('zipper_bag_1.ogg', rate = self.sounds.getPlayRate(), loop = self.looping)
            
        elif action == "pause_sounds":            
            if self.blahSound is not None:
                self.blahSound.pause()
                
            # Sounds.pauseAll just pauses all currently playing sounds
            self.sounds.pauseAll()
            
        elif action == "resume_sounds":
            if self.blahSound is not None:
                self.blahSound.play()
                
            # Sounds.resumeAll just pauses all paused sounds
            self.sounds.resumeAll()    
            
        elif action == "enable_sounds":
            # Sounds.enableSounds enables global sound playback
            self.sounds.enableSounds()
            
        elif action == "disable_sounds":
            # Sounds.enableSounds disables global sound playback, a sound that was playing prior to this call will get stopped
            self.sounds.disableSounds()
            
        elif action == "increase_volume":
            # this demonstrates updating the properties of a single sound
            if self.blahSound is not None:
                self.blahSound.setVolume(self.sounds.getVolume() + 0.1)
                
            # while here we update the volume property affecting all sounds at the same time
            self.sounds.setVolume(self.sounds.getVolume() + 0.1)
            self.updateVolume = True
            
        elif action == "decrease_volume":
            # same here as we did with the increase_volume action
            if self.blahSound is not None:
                self.blahSound.setVolume(self.sounds.getVolume() - 0.1)
            self.sounds.setVolume(self.sounds.getVolume() - 0.1)
            self.updateVolume = True
            
        elif action == "increase_rate":
            # same here as we did with the increase_volume action
            if self.blahSound is not None:
                self.blahSound.setPlayRate(self.sounds.getPlayRate() + 0.1)
            self.sounds.setPlayRate(self.sounds.getPlayRate() + 0.1)
            self.updateRate = True
            
        elif action == "decrease_rate":
            # same here as we did with the increase_volume action
            if self.blahSound is not None:
                self.blahSound.setPlayRate(self.sounds.getPlayRate() - 0.1)
            self.sounds.setPlayRate(self.sounds.getPlayRate() - 0.1)
            self.updateRate = True
            
        elif action == "increase_balance":
            # same here as we did with the increase_volume action
            if self.blahSound is not None:
                self.blahSound.setBalance(self.sounds.getBalance() + 0.1)
            self.sounds.setBalance(self.sounds.getBalance() + 0.1)
            self.updateBalance = True
            
        elif action == "decrease_balance":
            # same here as we did with the increase_volume action
            if self.blahSound is not None:
                self.blahSound.setBalance(self.sounds.getBalance() - 0.1)
            self.sounds.setBalance(self.sounds.getBalance() - 0.1)
            self.updateBalance = True
            
        elif action == "increase_loop":
            # looping in this example only affects the blah sound
            self.looping += 1
            self.updateLooping = True
            if self.blahSound is not None:
                self.blahSound.setLoop(self.looping)
                
        elif action == "decrease_loop":
            self.updateLooping = True
            self.looping -= 1            
            if self.looping < 0:
                self.looping = 0            
            if self.blahSound is not None:
                self.blahSound.setLoop(self.looping)
                    
        else:
            # we didn't handle this, indicate it by returning False
            return False 
            
        # action was handled, return True
        return True    
    
    
    def onMessage(self, msg, *args):
        '''
        Using Messenger objects any game component can broadcast messages which will become available to the active
        nodescript through this method.
        The msg parameter is the name of the message, while *args is a list of arguments provided by the sender.
        
        Each nodescript must first declare the list of messages for which it is interested to receive. The list is declared
        in the NodeScript.registerMessages method.
        '''
        
        # When a sound has finished playing the sound_finished message is broadcasted. 
        # We handle it here to get notified when the blah sound has finished and update the UI accordingly.
        if msg == 'sound_finished':
            print 'FINISHED'
            self.eventText.setFg((1.0, 0.0, 0.0, 0.0))
            self.eventText.show()
            Sequence(
                     LerpColorScaleInterval(self.eventText, 0.5, (1,1,1,1), (1,1,1,0)),
                     LerpColorScaleInterval(self.eventText, 0.5, (1,1,1,0), (1,1,1,1))
                     ).start()
                
                        
Exemple #11
0
class MouseTunnel(ShowBase):
    def __init__(self):
        # Initialize the ShowBase class from which we inherit, which will
        # create a window and set up everything we need for rendering into it.
        ShowBase.__init__(self)
        self.stimtype = 'random image'

        # session_start
        self.session_start_time = datetime.datetime.now()

        # self.accept("escape", sys.exit, [0])#don't let the user do this, because then the data isn't saved.
        self.accept('q', self.close)
        self.accept('Q', self.close)

        self.upArrowIsPressed = base.mouseWatcherNode.isButtonDown(KeyboardButton.up())
        self.downArrowIsPressed = base.mouseWatcherNode.isButtonDown(KeyboardButton.down())
        self.rightArrowIsPressed = base.mouseWatcherNode.isButtonDown(KeyboardButton.right())
        self.leftArrowIsPressed = base.mouseWatcherNode.isButtonDown(KeyboardButton.left())

        self.AUTO_REWARD = AUTO_REWARD
        # disable mouse control so that we can place the camera
        base.disableMouse()
        camera.setPosHpr(0, 0, 10, 0, -90, 0)
        mat = Mat4(camera.getMat())
        mat.invertInPlace()
        base.mouseInterfaceNode.setMat(mat)
        # base.enableMouse()

        props = WindowProperties()
        # props.setOrigin(0, 0)
        props.setFullscreen(True)
        props.setCursorHidden(True)
        props.setMouseMode(WindowProperties.M_relative)
        base.win.requestProperties(props)
        base.setBackgroundColor(0, 0, 0)  # set the background color to black

        print('FULSCREEN:')
        print(props.getFullscreen())
        print('=============')
        # set up the textures
        # we now get buffer thats going to hold the texture of our new scene
        altBuffer = self.win.makeTextureBuffer("hello", 1524, 1024)
        # altBuffer.getDisplayRegion(0).setDimensions(0.5,0.9,0.5,0.8)
        # altBuffer = base.win.makeDisplayRegion()
        # altBuffer.makeDisplayRegion(0,1,0,1)

        # now we have to setup a new scene graph to make this scene
        self.dr2 = base.win.makeDisplayRegion(0, 0.001, 0, 0.001)#make this really,really small so it's not seeable by the subject

        altRender = NodePath("new render")
        # this takes care of setting up ther camera properly
        self.altCam = self.makeCamera(altBuffer)
        self.dr2.setCamera(self.altCam)
        self.altCam.reparentTo(altRender)
        self.altCam.setPos(0, -10, 0)

        self.bufferViewer.setPosition("lrcorner")
        # self.bufferViewer.position = (-.1,-.4,-.1,-.4)
        self.bufferViewer.setCardSize(1.0, 0.0)
        print(self.bufferViewer.position)

        self.imagesTexture = MovieTexture("image_sequence")
        # success = self.imagesTexture.read("models/natural_images.avi")
        # success = self.imagesTexture.read("models/movie_5hz.mpg")
        self.imagesTexture.setPlayRate(1.0)
        self.imagesTexture.setLoopCount(10)
        # self.imageTexture =loader.loadTexture("models/NaturalImages/BSDs_8143.tiff")
        # self.imagesTexture.reparentTo(altRender)

        self.fixationPoint = OnscreenImage(image='models/fixationpoint.jpg', pos=(0, 0,0),scale=0.01)

        cm = CardMaker("stimwindow")
        cm.setFrame(-4, 4, -3, 3)
        # cm.setUvRange(self.imagesTexture)
        self.card = NodePath(cm.generate())
        self.card.reparentTo(altRender)
        if self.stimtype == 'image_sequence':
            self.card.setTexture(self.imagesTexture, 1)

        # add the score display
        self.scoreLabel = OnscreenText(text='Current Score:', pos=(-1, 0.9), scale=0.1, fg=(0.8, 0.8, 0.8, 1))
        self.scoreText = OnscreenText(text=str(0), pos=(-1, 0.76), scale=0.18, fg=(0, 1, 0, 1),
                                      shadow=(0.1, 1, 0.1, 0.5))
        self.feebackScoreText = OnscreenText(text='+ ' + str(0), pos=(-0.5, 0.5), scale=0.3, fg=(0, 1, 0, 1),
                                             shadow=(0.1, 1, 0.1, 0.5))
        self.feebackScoreText.setX(3.)

        # self.imagesTexture.play()

        # self.bufferViewer.setPosition("lrcorner")
        # self.bufferViewer.setCardSize(1.0, 0.0)
        self.accept("v", self.bufferViewer.toggleEnable)
        self.accept("V", self.bufferViewer.toggleEnable)

        # Load the tunnel
        self.initTunnel()

        # initialize some things
        # for the tunnel construction:
        self.boundary_to_add_next_segment = -1 * TUNNEL_SEGMENT_LENGTH
        self.current_number_of_segments = 8
        # task flow booleans
        self.in_waiting_period = False
        self.stim_started = False
        self.looking_for_a_cue_zone = True
        self.in_reward_window = False
        self.show_stimulus = False
        # for task control
        self.interval = 0
        self.time_waiting_in_cue_zone = 0
        self.wait_time = 1.83
        self.stim_duration = 0  # in seconds
    
#        self.distribution_type = np.random.uniform#
#        self.distribution_type_inputs = [0.016,0.4] #change the min & max stim duration times

    #New lines    EAS: set weights higher for faster image durations
        self.durWeights = list()
        a = np.linspace(0.016,0.4,10)
        for i,j in enumerate(a):
            if j<0.1:
                p1 = 0.25
                self.durWeights.append(p1)
            elif j > 0.1 and j < 0.21:
                p1 = 0.1
                self.durWeights.append(p1)
            elif j> 0.21:
                p1 = 0.04
                self.durWeights.append(p1)
        self.rng = np.random.default_rng()
        a = np.asarray(a)
        self.distribution_type_inputs = a
        #subset_size = len(p)

    #End new lines
      
#        self.distribution_type_inputs = [0.05,1.5]  #can be anytong should match 
#        self.distribution_type_inputs = [0.016,0.4] #change the min & max stim duration times
#        self.distribution_type_inputs = [0.016,0.4, 10] #change the min & max stim duration times

        self.max_stim_duration = 1.0  # in seconds
        self.stim_elapsed = 0.0       # in seconds
        self.last_position = base.camera.getZ()
        self.position_on_track = base.camera.getZ()
        # for reward control
        self.reward_window = REWARD_WINDOW  # in seconds
        self.reward_elapsed = 0.0
        
#        self.new_dt = list()
        
        # self.reward_volume = 0.008 # in mL. this is for the hardcoded 0.1 seconds of reward time
        self.reward_volume = int(REWARD_VOLUME)  # in uL, for the stepper motor
        self.reward_time = 0.1  # in sec, based on volume. hard coded right now but should be modified by the (1) calibration and (2) optionally by the main loop for dynamic reward scheduling
        # self.lick_buffer = []
        self.current_score = 0
        self.score = 0
        self.feedback_score_startime = -2

        # INITIALIZE NIDAQ
        self.nidevice = 'Dev2'
        self.encodervinchannel = 1
        self.encodervsigchannel = 0
        self.invertdo = False
        self.diport = 1
        self.lickline = 1
        self.doport = 0
        self.rewardline = 0
        self.rewardlines = [0]
        self.encoder_position_diff = 0
        if have_nidaq:
            self._setupDAQ()
            self.do.WriteBit(1, 1)
            self.do.WriteBit(3,
                             1)  # set reward high, because the logic is flipped somehow. possibly by haphazard wiring of the circuit (12/24/2018 djd)
            self.previous_encoder_position = self.ai.data[0][self.encodervsigchannel]
        else:
            self.previous_encoder_position = 0
        self.encoder_gain = 3

        # INITIALIZE LICK SENSOR
        self._lickSensorSetup()

        # INITIALIZE  output data
        self.lickData = []
        self.x = []
        self.t = []
        self.trialData = []
        self.reactionTimeData = []
        self.rewardData = []
        self.rightKeyData = []
        self.leftKeyData = []
        self.imageData = []
        self.imageTimeData = []
        self.scoreData = []
        self.trialDurationData = []
        self.new_dt = []

        # INITIALIZE KEY SENSOR, for backup inputs and other user controls
        self.keys = key.KeyStateHandler()
        self.accept('r', self._give_reward, [self.reward_volume])
        self.accept('l', self._toggle_reward)

        # initialize the image list and populate what images you want included


#        self.img_list = glob.glob('models/2AFC_IMAGES_HUMAN/*.tif')
#        self.img_list = glob.glob('models/2AFC_IMAGES_HUMAN2/*.tif')  
#        self.img_list = glob.glob('/Users/elizabethstubblefield/Desktop/cheetah_or_elephant/composite_images/masks/all_same_num_ea/*.tif')  #Newest images
        self.img_list = glob.glob('models/all_same_ea/*.tif')  #Newest images

        #No longer hard-coded:
        self.original_indices = [0,0]  #this was manually counted... first number must was the index of the first easy img; was [43, -18]
        for ndx, name in enumerate(self.img_list):
            if 'Cheetah255' in name:
                self.original_indices[0] = ndx
            elif 'Elephant0' in name:
                self.original_indices[1] = ndx

        # print(self.img_list)
        
#        self.original_indices = [43,-18] #manually counted, grump  #Problematic w/out at least 43 images in the folder        

        self.imageTextures =[loader.loadTexture(img) for img in self.img_list]
        self.img_id = None   #this variable is used so we know which stimulus is being presented
        self.img_mask = None #this tells us what the image mask being presented is

        # self._setupEyetracking()
        # self._startEyetracking()

        if AUTO_MODE:
            self.gameTask = taskMgr.add(self.autoLoop2, "autoLoop2")
            self.rewardTask = taskMgr.add(self.rewardControl, "reward")
            self.cue_zone = concatenate((self.cue_zone, arange( \
                self.current_number_of_segments * -TUNNEL_SEGMENT_LENGTH-50, \
                self.current_number_of_segments * -TUNNEL_SEGMENT_LENGTH - TUNNEL_SEGMENT_LENGTH - 100, \
                -1)))
            self.auto_position_on_track = 0
            self.auto_restart = False
            self.auto_running = True
            self.contTunnel()
        else:
            # Now we create the task. taskMgr is the task manager that actually
            # calls the function each frame. The add method creates a new task.
            # The first argument is the function to be called, and the second
            # argument is the name for the task.  It returns a task object which
            # is passed to the function each frame.
            self.gameTask = taskMgr.add(self.gameLoop, "gameLoop")
            # self.stimulusTask = taskMgr.add(self.stimulusControl, "stimulus")
            self.lickTask = taskMgr.add(self.lickControl, "lick")
            self.rewardTask = taskMgr.add(self.rewardControl, "reward")
            self.keyTask = taskMgr.add(self.keyControl, "Key press")

    # Code to initialize the tunnel
    def initTunnel(self):
        self.tunnel = [None] * 8

        for x in range(8):
            # Load a copy of the tunnel
            self.tunnel[x] = loader.loadModel('models/tunnel')
            # The front segment needs to be attached to render
            if x == 0:
                self.tunnel[x].reparentTo(render)
            # The rest of the segments parent to the previous one, so that by moving
            # the front segement, the entire tunnel is moved
            else:
                self.tunnel[x].reparentTo(self.tunnel[x - 1])
                # We have to offset each segment by its length so that they stack onto
            # each other. Otherwise, they would all occupy the same space.
            self.tunnel[x].setPos(0, 0, -TUNNEL_SEGMENT_LENGTH)
            # Now we have a tunnel consisting of 4 repeating segments with a
            # hierarchy like this:
            # render<-tunnel[0]<-tunnel[1]<-tunnel[2]<-tunnel[3]

        self.tunnel[0] = loader.loadModel('models/grating')
        self.tunnel[0].reparentTo(render)
        self.cue_zone = arange(0, TUNNEL_SEGMENT_LENGTH, -1)-280

    # This function is called to snap the front of the tunnel to the back
    # to simulate traveling through it
    def contTunnel(self):
        self.auto_position_on_track -= 50
        position_on_track = self.auto_position_on_track
        print(str(int(position_on_track)) + '   ' + str(self.cue_zone))
        if int(position_on_track) in np.array(self.cue_zone):  # check for cue zone
            if not self.auto_restart:
                print('STOP!')
                self.tunnelMove.pause()
                self.auto_presentation = True
                # self.current_number_of_segments +=1
            else:
                self.auto_restart = True
                self.tunnelMove.resume()

        else:
            self.in_waiting_period = False
            self.auto_presentation = False

            # base.setBackgroundColor([1,0 , 0])
            if self.looking_for_a_cue_zone == False:
                self.looking_for_a_cue_zone = True
            if self.stim_started == True:
                self.stop_a_presentation()

            # This line uses slices to take the front of the list and put it on the
            # back. For more information on slices check the Python manual
            self.tunnel = self.tunnel[1:] + self.tunnel[0:1]

            # Set the front segment (which was at TUNNEL_SEGMENT_LENGTH) to 0, which
            # is where the previous segment started
            self.tunnel[0].setZ(0)
            # Reparent the front to render to preserve the hierarchy outlined above
            self.tunnel[0].reparentTo(render)
            # Set the scale to be apropriate (since attributes like scale are
            # inherited, the rest of the segments have a scale of 1)
            self.tunnel[0].setScale(.155, .155, .305)
            # Set the new back to the values that the rest of the segments have
            self.tunnel[3].reparentTo(self.tunnel[2])
            self.tunnel[3].setZ(-TUNNEL_SEGMENT_LENGTH)
            self.tunnel[3].setScale(1)

            # Set up the tunnel to move one segment and then call contTunnel again
            # to make the tunnel move infinitely
            self.tunnelMove = Sequence(
                LerpFunc(self.tunnel[0].setZ,
                         duration=TUNNEL_TIME,
                         fromData=0,
                         toData=TUNNEL_SEGMENT_LENGTH * .305),
                Func(self.contTunnel)
            )
            self.tunnelMove.start()
    
    def get_trial_duration(self):      #EAS updated 10.5.20
        self.stim_duration = self.rng.choice(self.distribution_type_inputs, 1, p=self.durWeights)  #pull out one value in array a, w/ probability based on weights
        return self.stim_duration[0]

#        return self.distribution_type(*self.distribution_type_inputs)

    def start_a_presentation(self):
        self.save_data()
        self.stim_duration = self.get_trial_duration()
        
        self.fixationPoint.destroy()
#        import pickle
#        with open('objs.pkl', 'wb') as f:  # Python 3: open(..., 'wb')
#            pickle.dump([self.stim_duration,self.distribution_type_inputs], f)
#            print('variables saved!!!')

        self.in_reward_window = True
        print("start")
        if have_nidaq:
            self.do.WriteBit(2, 1)
        # self.bufferViewer.toggleEnable()

        self.lick_buffer = []
        self.trialData.extend([globalClock.getFrameTime()])
        self.reactionTimeData.extend([-1])

        if self.stimtype == 'random image':

            if len(self.trialData) < 4:
                i=self.original_indices[int(np.round(np.random.random()))]   #commented out due to <43 images [see l. 290ish]
                self.stim_duration = 2.0
            else:                                                            #commented out due to <43 images
                i = randint(len(self.imageTextures))
                
            self.card.setTexture(self.imageTextures[i],0)
            self.dr2.setDimensions(0.25, 0.75, 0.25, 0.75)  # floats (left, right, bottom, top)
            self.img_id = self.img_list[i] #this assigns the current presented image to self.image_id
            print(self.img_id)
            self.imageData.extend(self.img_id)                    
        
        if self.stimtype == 'image_sequence':
            self.imagesTexture.setTime(0.)
            self.dr2.setDimensions(0.4, 0.8, 0.4, 0.70)  # floats (left, right, bottom, top)
            self.imagesTexture.play()
        self.imageTimeData.extend([globalClock.getFrameTime()])
        self.imageData.extend(self.img_id)
  
    def check_arrows(self):
        # this function will report which arrow was pressed. right = 1, left = 2, no press = 0
        if self.rightArrowIsPressed:
            #print('check arrows RIGHT')
            return 1
            # time.sleep(2)
        elif self.leftArrowIsPressed:
            #print('check arrows LEFT')
            return 2
            # time.sleep(2)
        else:
            return 0

    def stop_a_presentation(self):
        if self.stim_started == True:
            if self.stim_elapsed > self.stim_duration:
                self.trialDurationData.append(self.stim_duration)
            else: self.trialDurationData.append(self.stim_duration)
            self.dr2.setDimensions(0, 0.001, 0, 0.001)#make this really,really small so it's not seeable by the subject
            # self.bufferViewer.toggleEnable()
            self.stim_started = False
            self.stim_elapsed = 0.
            self.stim_duration = 0.
            self.stim_off_time = globalClock.getFrameTime()
            if have_nidaq:
                self.do.WriteBit(2, 0)
            # if globalClock.getFrameTime() > self.feedback_score_startime + 1.5:  # arbitrary wait to make sure this isn't after a correct trial
            #     self.feebackScoreText.setText('+' + str(0))
            #     self.feebackScoreText.setFg((1, 0, 0, 1))
            #     self.feebackScoreText.setX(.5)
            #     self.feedback_score_startime = globalClock.getFrameTime()
            self.scoreData.append(self.current_score)
            self.fixationPoint = OnscreenImage(image='models/fixationpoint.jpg', pos=(0, 0,0),scale=0.01)

            
    #   def keySensorSetup(self):


    def show_the_score(self):
            self.feebackScoreText.setText('+' + str(self.score))
            if self.score == 0:
                self.feebackScoreText.setFg((1, 0, 0, 1))
            else:
                self.feebackScoreText.setFg((0, 1, 0, 1))
            self.feebackScoreText.setX(.5)
            self.feedback_score_startime = globalClock.getFrameTime()
    # sets up the task to listen for user input from the keys

    def _lickSensorSetup(self):

        """ Attempts to set up lick sensor NI task. """
        ##TODO: Make lick sensor object if necessary. Let user select port and line.
        if have_nidaq:
            if self.di:
                self.lickSensor = self.di  # just use DI for now
                licktest = []
                for i in range(30):
                    licktest.append(self.rightArrowIsPressed.Read()[self.lickline])
                    time.sleep(0.01)
                licktest = np.array(licktest, dtype=np.uint8)
                if len(licktest[np.where(licktest > 0)]) > 25:
                    self.lickSensor = None
                    self.lickData = [np.zeros(len(self.rewardlines))]
                    print("Lick sensor failed startup test.")
                else:
                    print('lick sensor setup succeeded.')
                self.keycontrol = True
            else:
                print("Could not initialize lick sensor.  Ensure that NIDAQ is connected properly.")
                self.keycontrol = True
                self.lickSensor = None
                self.lickData = [np.zeros(len(self.rewardlines))]
                self.keys = key.KeyStateHandler()
                # self.window.winHandle.push_handlers(self.keys)
        else:
            print("Could not initialize lick sensor.  Ensure that NIDAQ is connected properly.")
            self.keycontrol = True
            self.lickSensor = None
            self.lickData = [np.zeros(len(self.rewardlines))]
            self.keys = key.KeyStateHandler()

    def reactiontime_to_score(self):
        rt = globalClock.getFrameTime() - self.trialData[-1]
        self.reactionTimeData[-1] = rt
        score = 100. / rt  # scale the reaction time, with faster producing more points
        return int(score / 20.)

    # def _read_licks(self): # not yet implemented; should be replaces with check to beam break
    def _give_reward(self, volume):
        print("reward!")
        self.rewardData.extend([globalClock.getFrameTime()])

        # for humans
        self.score = self.reactiontime_to_score()
        self.current_score += self.score
        self.show_the_score()
        self.scoreText.setText(str(self.current_score))
        

        # for mice
        if have_nidaq:
            self.do.WriteBit(3, 0)
            time.sleep(self.reward_time)
            self.do.WriteBit(3, 1)  # put a TTL on a line to indicate that a reward was given
            s.dispense(volume)  # pass # not yet implemented

    def _toggle_reward(self):
        if self.AUTO_REWARD:
            self.AUTO_REWARD = False
            print('switched to lick sensing for reward.')
        else:
            self.AUTO_REWARD = True
            print('switched to automatic rewards after stimuli.')

    def autoLoop2(self, task):
        dt = globalClock.getDt()
        current_time = globalClock.getFrameTime()

        self.x.extend([self.auto_position_on_track])
        self.t.extend([globalClock.getFrameTime()])

        if self.auto_presentation:
            self.auto_running = False
            if self.in_waiting_period:
                self.time_waited += dt
            else:
                self.time_waited = 0
                self.in_waiting_period = True
            if self.time_waited > self.wait_time:  # if in cue zone,see if we have been ther for long enough
                # start a trial
                self.start_position = self.auto_position_on_track
                self.start_time = current_time
                if not self.stim_started:
                    self.start_a_presentation()
                    # print(self.stim_duration)
                    self.stim_started = True
                    self.show_stimulus = True
                else:
                    self.stim_elapsed += dt
                    if self.stim_elapsed > self.stim_duration:
                        self.show_stimulus = False
                        self.in_reward_window = True
                        self.stop_a_presentation()
                        self.auto_restart = False
                        # print(self.current_number_of_segments)
                        self.current_number_of_segments += 9
                        # redefine the cue zone as the next one
                        self.cue_zone = arange(self.current_number_of_segments * -TUNNEL_SEGMENT_LENGTH,
                                               self.current_number_of_segments * -TUNNEL_SEGMENT_LENGTH - TUNNEL_SEGMENT_LENGTH - 280,
                                               -1)
                        # extend cue zone, keeping old ones
                        # self.cue_zone = concatenate((self.cue_zone,arange(self.current_number_of_segments*-TUNNEL_SEGMENT_LENGTH-40,
                        #                             self.current_number_of_segments*-TUNNEL_SEGMENT_LENGTH-TUNNEL_SEGMENT_LENGTH-40,
                        #                             -1)))
                        self.contTunnel()
                        self.time_waited = 0
                        self.looking_for_a_cue_zone = False
                # base.setBackgroundColor([0, 0, 1])
            else:
                pass  # base.setBackgroundColor([0, 1, 0])
        else:
            self.auto_running = True
        return Task.cont  # Since every return is Task.cont, the task will

    def gameLoop(self, task):
        # get the time elapsed since the next frame.
        dt = globalClock.getDt()
        self.new_dt.append(dt)                  #Store the append here for dt
        
        current_time = globalClock.getFrameTime()    #This is for the key press
        if current_time > self.feedback_score_startime + 1.5:
            self.feebackScoreText.setX(3.)
        # get the camera position.
        position_on_track = base.camera.getZ()

        # get the encoder position from NIDAQ Analog Inputs channel 2
        if have_nidaq:
            encoder_position = self.ai.data[0][self.encodervsigchannel]  # zeroth sample in buffer [0], from ai2 [2]
            # convert to track coordinates
            encoder_position_diff = (encoder_position - self.previous_encoder_position)
            if encoder_position_diff > 4.5: encoder_position_diff -= 5.
            if encoder_position_diff < -4.5: encoder_position_diff += 5.
            self.encoder_position_diff = encoder_position_diff * self.encoder_gain
            self.previous_encoder_position = encoder_position
        else:
            self.read_keys()
            if self.upArrowIsPressed:
                self.encoder_position_diff = -1 * self.encoder_gain
            if self.downArrowIsPressed:
                self.encoder_position_diff = 1 * self.encoder_gain
            if not self.downArrowIsPressed:
                if not self.upArrowIsPressed:
                    self.encoder_position_diff = 0
        position_on_track = base.camera.getZ() + self.encoder_position_diff
        # reset the camera position
        self.camera.setPos(base.camera.getX(), base.camera.getY(), position_on_track)

        self.x.extend([position_on_track])
        self.t.extend([globalClock.getFrameTime()])

        # first check if the mouse moved on the last frame.
        if abs(self.last_position - position_on_track) < 1.5:  # the mouse didn't move more than 0.5 units on the track
            self.moved = False
            if int(position_on_track) in self.cue_zone:  # check for cue zone
                if self.looking_for_a_cue_zone:  # make sure we transitioning from the tunnel to a cue zone
                    # increment how long we've been waiting in the cue zone.
                    if self.in_waiting_period:
                        self.time_waited += dt
                    else:
                        self.time_waited = 0
                        self.in_waiting_period = True
                    if self.time_waited > self.wait_time:  # if in cue zone,see if we have been ther for long enough
                        # start a trial
                        self.start_position = position_on_track
                        self.start_time = current_time
                        if not self.stim_started:
                            self.start_a_presentation()
                            print(self.stim_duration)
                            self.stim_started = True
                            self.show_stimulus = True
                        else:
                            self.stim_elapsed += dt
                            if self.stim_elapsed > self.stim_duration:
                                self.show_stimulus = False
                                self.stop_a_presentation()
                                self.time_waited = 0
                                self.looking_for_a_cue_zone = False
                        # base.setBackgroundColor([0, 0, 1])
                    else:
                        pass  # base.setBackgroundColor([0, 1, 0])
            else:
                self.in_waiting_period = False
                # base.setBackgroundColor([1,0 , 0])
                if self.looking_for_a_cue_zone == False:
                    self.looking_for_a_cue_zone = True
                if self.stim_started == True:
                    self.stop_a_presentation()
        else:  # the mouse did move
            self.moved = True
            if self.stim_started == True:  # check if it moved during a presenation
                self.stop_a_presentation()
                self.time_waited = 0
                self.looking_for_a_cue_zone = False
                self.show_stimulus = False

        # if we need to add another segment, do so
        if position_on_track < self.boundary_to_add_next_segment:
            self.tunnel.extend([None])
            x = self.current_number_of_segments
            if x % 8 == 0:
                self.tunnel[x] = loader.loadModel('models/grating')
                self.cue_zone = concatenate((self.cue_zone, arange( \
                    self.current_number_of_segments * -TUNNEL_SEGMENT_LENGTH - 50, \
                    self.current_number_of_segments * -TUNNEL_SEGMENT_LENGTH - TUNNEL_SEGMENT_LENGTH - 100, \
                    -1)))
            else:
                self.tunnel[x] = loader.loadModel('models/tunnel')
            self.tunnel[x].setPos(0, 0, -TUNNEL_SEGMENT_LENGTH)
            self.tunnel[x].reparentTo(self.tunnel[x - 1])
            # increment
            self.boundary_to_add_next_segment -= TUNNEL_SEGMENT_LENGTH
            self.current_number_of_segments += 1
        else:
            pass  # print('current:'+str(position_on_track) +'      next boundary:' + str(self.boundary_to_add_next_segment))

        self.last_position = position_on_track

        # lick_times = self.
        # self._read_licks()
        return Task.cont  # Since every return is Task.cont, the task will
        # continue indefinitely, under control of the mouse (animal)

    def stimulusControl(self, task):
        if self.show_stimulus and not self.bufferViewer.isEnabled():
            # self.bufferViewer.toggleEnable()
            self.dr2.setDimensions(0.5, 0.9, 0.5, 0.8)
        if not self.show_stimulus and self.bufferViewer.isEnabled():
            # self.bufferViewer.toggleEnable()
            self.dr2.setDimensions(0, 0.1, 0, 0.1)
        return Task.cont

    def lickControl(self, task):
        """ Checks to see if a lick is occurring. """
        ##TODO: Let user select line for lick sensing.
        if self.lickSensor:
            if self.lickSensor.Read()[self.lickline]:
                self.lickData.extend([globalClock.getFrameTime()])
                print('lick happened at: ' + str(self.lickData[-1]))
        elif self.keycontrol == True:  # NO NI BOARD.  KEY INPUT?
            if self.keys[key.SPACE]:
                data = [globalClock.getFrameTime()]
            elif self.keys[key.NUM_1]:
                # print(self.lickData)
                # elif self.keys[key.NUM_3]:
                #     data = [0,1]
                # else:
                #     data = [0,0]
                self.lickData.extend(data)
        return Task.cont

    def keyControl(self, task):
        # listen to and record when the arrows are pressed
        self.read_keys()
        if self.rightArrowIsPressed:
            self.rightKeyData.extend([globalClock.getFrameTime()])
            print('right arrow at: ' + str(self.rightKeyData[-1]))
#            time.sleep(.2)  #EAS changed this only allows for one keystroke to be recorded every 0.5s
        elif self.leftArrowIsPressed:
            self.leftKeyData.extend([globalClock.getFrameTime()])
            print('left arrow at: ' + str(self.leftKeyData[-1]))
#            time.sleep(.2)  #EAS changed this only allows for one keystroke to be recorded every 0.5s
        return Task.cont

    def rewardControl(self, task):
        # print(self.in_reward_window)
        if self.in_reward_window == True:
            if self.reward_elapsed < self.reward_window:
            
                self.reward_elapsed += globalClock.getDt()
#                self.new_reward_elapsed.append(self.reward_elapsed)
                
#                import pickle
#                with open('objs.pkl', 'wb') as f:  # Python 3: open(..., 'wb')
#                    pickle.dump([self.stim_duration,self.distribution_type_inputs, self.new_rew_control], f)
#                    print('variables saved!!!')

                self.check_arrows()
                if not self.AUTO_REWARD:
                    
                    if self.check_arrows() == 1:  # if check arrows returns a 1 the right arrow was pressed during stimulus presentation
                        # note reaction time
                        if self.img_id.find("Elephant") != -1: #if the current image file contains the string in () the value is not -1
                            self._give_reward(self.reward_volume)
                            print('correct: image was mostly elephant')
                            self.in_reward_window = False;
                            self.reward_elapsed = 0.  # reset
                        
                        elif 'Same' in self.img_id:                     #updated 8.24.20: reward 50/50 images 1/2 the time
                            if round(np.random.random(1)[0]):
                                self._give_reward(self.reward_volume)
                                print('correct: image was same')
                                self.in_reward_window = False;
                                self.reward_elapsed = 0.  # reset
                            else:
                                print(self.img_mask)
                                print('incorrect: image was same')
                                self.in_reward_window = False
                                self.reward_elapsed = 0.  # reset
                                self.score=0
                                self.show_the_score()
                        else:
                            print(self.img_mask)
                            print('image was not mostly elephant!')
                            self.in_reward_window = False
                            self.reward_elapsed = 0.  # reset
                            self.score=0
                            self.show_the_score()
                                                        
                    if self.check_arrows() == 2:                          #if check arrows returns a 2 the left arrow was pressed during stimulus presentation
                        if self.img_id.find("Cheetah") != -1:             #if the current image file contains the string in () the value is not -1
                            self._give_reward(self.reward_volume)
                            print('correct: image was mostly cheetah')
                            self.in_reward_window = False;
                            self.reward_elapsed = 0.  # reset
                        
                        elif 'Same' in self.img_id:                      #updated 8.24.20: reward 50/50 images 1/2 the time
                            if round(np.random.random(1)[0]):
                                self._give_reward(self.reward_volume)
                                print('correct: image was same')
                                self.in_reward_window = False;
                                self.reward_elapsed = 0.  # reset
                            else:
                                print(self.img_mask)
                                print('incorrect: image was same')
                                self.in_reward_window = False
                                self.reward_elapsed = 0.  # reset
                                self.score=0
                                self.show_the_score()
                        else:
                            print(self.img_mask)
                            print('image was not mostly cheetah!')
                            self.in_reward_window = False
                            self.reward_elapsed = 0.  # reset
                            self.score=0
                            self.show_the_score()
                    
                        

                else:
                    self._give_reward(self.reward_volume)
                    self.in_reward_window = False;
                    self.reward_elapsed = 0.  # reset
                    # base.setBackgroundColor([1, 1, 0])

#            # if self.keys[key.NUM_1]:
#            #     print('reward!')
            else:
                self.score=0
                self.show_the_score()
                self.in_reward_window = False
                self.reward_elapsed = 0.
        else:
            pass#print('not listening for reward'+str(globalClock.getFrameTime()))
        return Task.cont

    def _setupEyetracking(self):
        """ sets up eye tracking"""
        try:
            eyetrackerip = "DESKTOP-EE5KKDO"
            eyetrackerport = 10000
            trackeyepos = False
            from aibs.Eyetracking.EyetrackerClient import Client
            self.eyetracker = Client(outgoing_ip=eyetrackerip,
                                     outgoing_port=eyetrackerport,
                                     output_filename=str(datetime.datetime.now()).replace(':', '').replace('.',
                                                                                                           '').replace(
                                         ' ', '-'))
            self.eyetracker.setup()
            # eyedatalog = []
            # if trackeyepos:
            #     eyeinitpos = None
        except:
            print("Could not initialize eyetracker:")
            self.eyetracker = None

    def _startEyetracking(self):
        if self.eyetracker:
            self.eyetracker.recordStart()

    def _setupDAQ(self):
        """ Sets up some digital IO for sync and tiggering. """
        print('SETTING UP DAQ')
        try:
            if self.invertdo:
                istate = 'low'
            else:
                istate = 'high'
            self.do = DigitalOutput(self.nidevice, self.doport,
                                    initial_state='low')
            self.do.StartTask()
        except:  # Exception, e:
            print("Error starting DigitalOutput task:")
            self.do = None
        try:
            self.di = DigitalInput(self.nidevice, self.diport)
            self.di.StartTask()
        except:  # Exception, e:
            print("Error starting DigitalInput task:")
            self.di = None
        # try:
        # set up 8 channels, only use 2 though for now
        self.ai = AnalogInput(self.nidevice, range(8), buffer_size=25, terminal_config='RSE',
                              clock_speed=6000.0, voltage_range=[-5.0, 5.0])
        self.ai.StartTask()
        # except:# Exception, e:
        # print("Error starting AnalogInput task:")
        # self.ai = None
        try:
            self.ao = AnalogOutput(self.nidevice, channels=[0, 1], terminal_config='RSE',
                                   voltage_range=[0.0, 5.0])
            self.ao.StartTask()
        except:  # Exception, e:
            print("Error starting AnalogOutput task:")
            self.ao = None

    def read_keys(self):
        self.upArrowIsPressed = base.mouseWatcherNode.isButtonDown(KeyboardButton.up())
        self.downArrowIsPressed = base.mouseWatcherNode.isButtonDown(KeyboardButton.down())
        self.rightArrowIsPressed = base.mouseWatcherNode.isButtonDown(KeyboardButton.right())
        self.leftArrowIsPressed = base.mouseWatcherNode.isButtonDown(KeyboardButton.left())

    def save_data(self):
        if not os.path.isdir(os.path.join(os.getcwd(), 'data')):
            os.mkdir(os.path.join(os.getcwd(), 'data'))
        save_path = os.path.join(os.getcwd(), 'data', str(MOUSE_ID) + '_' + \
                                 str(self.session_start_time.year) + '_' + \
                                 str(self.session_start_time.month) + '_' + \
                                 str(self.session_start_time.day) + '-' + \
                                 str(self.session_start_time.hour) + '_' + \
                                 str(self.session_start_time.minute) + '_' + \
                                 str(self.session_start_time.second))
        if not os.path.isdir(save_path):
            os.mkdir(save_path)

        print("saving data to " + save_path)
        np.save(os.path.join(save_path, 'licks.npy'), self.lickData)
        np.save(os.path.join(save_path, 'x.npy'), self.x)
        np.save(os.path.join(save_path, 't.npy'), self.t)
        np.save(os.path.join(save_path, 'trialData.npy'), self.trialData)
        np.save(os.path.join(save_path, 'rewardData.npy'), self.rewardData)
        np.save(os.path.join(save_path, 'rtData.npy'), self.reactionTimeData)
        np.save(os.path.join(save_path, 'rightKeyData.npy'), self.rightKeyData)
        np.save(os.path.join(save_path, 'leftKeyData.npy'), self.leftKeyData)
        np.save(os.path.join(save_path, 'imageData.npy'), self.imageData)
        np.save(os.path.join(save_path, 'imageTimeData.npy'), self.imageTimeData)
        np.save(os.path.join(save_path, 'scoreData.npy'), self.scoreData)
        np.save(os.path.join(save_path, 'trialDurationData.npy'), self.trialDurationData)
        np.save(os.path.join(save_path, 'dT.npy'), self.new_dt)

    def close(self):
        self.save_data()

        print('rewardData:')
        print(np.shape(self.rewardData))
        try:
            #push anonymized data to Denman Lab Open Science Framework project for human psychophysics
            subprocess.call('osf -p 7xruh -u [email protected] upload -r '+save_path+' data/'+os.path.basename(save_path),shell=True)     #commented these lines out to test if saving to osf is the hangup; it's not
        except:pass

        sys.exit(0)
Exemple #12
0
class MyApp(ShowBase):
    gameMode = "Intro"

    def __init__(self):
        ShowBase.__init__(self)

        #self.cameraSetup()
        self.setupKeyboard()

        self.initIntro()

    def gameChangeMode(self):
        if base.gameMode == "Intro":
            self.initIntro()
        elif base.gameMode == "Convo":
            self.initConvo()

    def initIntro(self):
        self.fadeAlpha = 0.0
        self.fadeTime = 30.0
        self.fadeInc = 1.0/self.fadeTime
        self.fadeDir = "up"

        self.sceneImage = OnscreenImage(image = "images/scene.png", scale = (1920.0/1080.0,1,1))
        self.sceneImage.setTransparency(TransparencyAttrib.MAlpha)
        self.sceneImage.setAlphaScale(self.fadeAlpha)

        self.imageNumber = 0
        self.sceneImageList = ["images/scene.png","images/image1.jpg"]

        #self.texty = OnscreenText(str(self.fadeAlpha))

        taskMgr.add(self.gameIntroUpdate, "GameIntroUpdate")

    def gameIntroUpdate(self, task):
        self.slideManager()
        if (base.gameMode != "Intro"):
            self.gameChangeMode()
            return Task.done

        return Task.cont

    def cameraSetup(self):
        base.camLens.setAspectRatio(1920.0/1080.0)

    def slideManager(self):
        if self.fadeDir == "up" and self.fadeAlpha<1:
            self.fadeAlpha += self.fadeInc
            self.sceneImage.setAlphaScale(self.fadeAlpha)
            #self.texty.setText(str(self.fadeAlpha))

        if self.fadeDir == "down" and self.fadeAlpha > 0:
            self.fadeAlpha -= self.fadeInc
            self.sceneImage.setAlphaScale(self.fadeAlpha)

        if self.fadeDir == "up" and self.fadeAlpha >= 1:
            self.fadeDir = "down"

        if self.fadeDir == "down" and self.fadeAlpha <= 0:
            if self.imageNumber < 1:
                self.fadeDir = "up"
                self.sceneImage.setImage(self.nextImage())
                self.sceneImage.setTransparency(TransparencyAttrib.MAlpha)
                self.sceneImage.setAlphaScale(self.fadeAlpha)
            else:
                self.fadeDir = "up"
                base.gameMode = "Convo"
                self.sceneImage.setImage(self.sceneImageList[self.imageNumber])
                self.sceneImage.setTransparency(TransparencyAttrib.MAlpha)
                self.sceneImage.setAlphaScale(self.fadeAlpha)

    def nextImage(self):
            self.imageNumber += 1
            return self.sceneImageList[self.imageNumber]

    def initConvo(self):
        self.textToType = "This will be used for talking\nThis is a good conversation box"
        self.textVisible = ""

        self.strOptionA = "Yes"
        self.strOptionB = "No"
        self.strOptionC = "Maybe"

        self.convoResponseSelected = False
        self.convoDepth = "1"

        self.intOptionCount = 3

        #self.txtConvo = OnscreenText(self.textVisible, align = TextNode.ALeft)
        self.txtConvo = TextNode("Texty Bastard")
        self.txtConvo.setText(self.textToType)
        self.txtReply = TextNode("reply")
        self.txtReply.setText("")
        self.intHover = 0

        #self.txtConvo.setFrameColor(0, 0, 1, 1)
        #self.txtConvo.setFrameAsMargin(0.2, 0.2, 0.1, 0.1)



        myFrame = DirectFrame(frameColor=(0.8, 0.8, 0.8, 0.4),
                      frameSize=(-1, 0, -1, 0))
        nodePathConvo = aspect2d.attachNewNode(self.txtConvo)
        nodePathConvo.setScale(0.07)
        nodePathConvo.setPos(-1, 0, -0.1)
        self.i = 0
        self.indent = 0.0
        self.selectedResponse = 0
        self.txtOptionA = OnscreenText(text = "", pos = (-1,-0.6), align = TextNode.ALeft)
        self.txtOptionB = OnscreenText(text = "", pos = (-1,-0.7), align = TextNode.ALeft)
        self.txtOptionC = OnscreenText(text = "", pos = (-1,-0.8), align = TextNode.ALeft)

        taskMgr.add(self.gameConvoUpdate, "GameConvoUpdate")

    def gameConvoUpdate(self, task):

        if (len(self.textVisible) != len(self.textToType)):
			task.delayTime = 0.001
			while (self.i < len(self.textToType)):

				self.textVisible += self.textToType[self.i]
				self.txtConvo.setText(self.textVisible)
				self.i += 1

				return Task.again

        else:
            taskMgr.add(self.gameConvoOptions, "ConvoOptions")
            return Task.done

    def gameConvoOptions(self, task):
        self.txtOptionA.setText(self.strOptionA)
        self.txtOptionB.setText(self.strOptionB)
        self.txtOptionC.setText(self.strOptionC)

        if self.convoResponseSelected == True:
            if self.convoCheckBranch("01", self.convoDepth):
                #self.txtConvo.setText(self.convoGetStrings("01", self.convoDepth))
                self.convoNextDialogue("01", self.convoDepth)
            else:
                #self.txtConvo.setText("It DIDn't worked")
                self.convoDepth = "1"
                self.convoNextDialogue("01", self.convoDepth)
            return Task.done

        elif self.selectedResponse == 0:
            if self.intOptionCount > 0:
                self.txtOptionA.setX(-1+self.indent)
                self.txtOptionA.setFg(fg = (1,0,0,1))
            if self.intOptionCount > 1:
                self.txtOptionB.setX(-1)
                self.txtOptionB.setFg(fg = (0,0,0,1))
            if self.intOptionCount > 2:
                self.txtOptionC.setX(-1)
                self.txtOptionC.setFg(fg = (0,0,0,1))
            self.indent = self.getIndent(self.indent,0.01,0.1)
            return Task.again

        elif self.selectedResponse == 1:
            if self.intOptionCount > 0:
                self.txtOptionA.setX(-1)
                self.txtOptionA.setFg(fg = (0,0,0,1))
            if self.intOptionCount > 1:
                self.txtOptionB.setX(-1+self.indent)
                self.txtOptionB.setFg(fg = (1,0,0,1))
            if self.intOptionCount > 2:
                self.txtOptionC.setX(-1)
                self.txtOptionC.setFg(fg = (0,0,0,1))
            self.indent = self.getIndent(self.indent,0.01,0.1)
            return Task.again

        elif self.selectedResponse == 2:
            if self.intOptionCount > 0:
                self.txtOptionA.setX(-1)
                self.txtOptionA.setFg(fg = (0,0,0,1))
            if self.intOptionCount > 1:
                self.txtOptionB.setX(-1)
                self.txtOptionB.setFg(fg = (0,0,0,1))
            if self.intOptionCount > 2:
                self.txtOptionC.setX(-1+self.indent)
                self.txtOptionC.setFg(fg = (1,0,0,1))
            self.indent = self.getIndent(self.indent,0.01,0.1)
            return Task.again

    def convoGetStrings(self,npcId,depth):
        if self.convoCheckBranch(npcId,depth) != True:
            return "#Error# String Not Found\nLooking for: "+"("+str(npcId)+")."+depth+":"
        char = ""
        line = ""
        feed = ""



        path = os.path.abspath(os.getcwd())
        f = open(path+"\\text\\stringsConvo.txt","r")
        while line != "("+str(npcId)+")."+depth+":":
            while char != ":":
                char = f.readline(1)
                line += char
            feed += "\n"+line
            if line != "("+str(npcId)+")."+depth+":":
                char = ""
                line = ""
                f.readline()
        print(feed + " Selected")
        f.readline(1)
        line = f.readline()
        line = line.replace("##", "\n")
        f.close()
        return line

    def convoCheckBranch(self,npcId,depth):
        path = os.path.abspath(os.getcwd())
        f = open(path+"\\text\\stringsConvo.txt","r")
        char = ""
        line = ""
        branchFound = False

        while line != "<END>:":
            char = ""
            line = ""
            while char != ":":
                char = f.readline(1)
                line += char
            if line == "<END>:":
                f.close()
                return False
            elif line == "("+str(npcId)+")."+str(depth)+":":
                f.close()
                return True
            else:
                f.readline()

    def convoNextDialogue(self,npcId,depth):
        self.textToType = self.convoGetStrings(npcId, depth)
        self.intOptionCount = self.convoGetOptionCount(npcId, depth)

        if self.intOptionCount == 1:
            self.strOptionA = self.convoGetStrings(npcId, depth+".A")
            self.strOptionB = ""
            self.strOptionC = ""
        elif self.intOptionCount == 2:
            self.strOptionA = self.convoGetStrings(npcId, depth+".A")
            self.strOptionB = self.convoGetStrings(npcId, depth+".B")
            self.strOptionC = ""
        elif self.intOptionCount == 3:
            self.strOptionA = self.convoGetStrings(npcId, depth+".A")
            self.strOptionB = self.convoGetStrings(npcId, depth+".B")
            self.strOptionC = self.convoGetStrings(npcId, depth+".C")
        else:
            self.strOptionA = ""
            self.strOptionB = ""
            self.strOptionC = ""

        self.textVisible = ""
        self.txtOptionA.setText("")
        self.txtOptionB.setText("")
        self.txtOptionC.setText("")
        self.txtConvo.setText(self.textVisible)
        #self.intOptionCount = 2
        self.selectedResponse = 0
        self.i = 0
        self.convoResponseSelected = False
        taskMgr.add(self.gameConvoUpdate, "GameConvoUpdate")

    def convoGetOptionCount(self,npcId,depth):
        if self.convoCheckBranch(npcId,depth+".A") and self.convoCheckBranch(npcId,depth+".B") and self.convoCheckBranch(npcId,depth+".C"):
            return 3
        elif self.convoCheckBranch(npcId,depth+".A") and self.convoCheckBranch(npcId,depth+".B"):
            return 2
        elif self.convoCheckBranch(npcId,depth+".A"):
            return 1
        else:
            return 0

    def getIndent(self, value, increment, limit):
        if (value + increment >= limit):
            return limit
        else:
            return value+increment

    def setupKeyboard(self):
        self.accept("arrow_down", self.convoOptionDown)
        self.accept("arrow_up", self.convoOptionUp)
        self.accept("enter",self.convoOptionSelect)

    def convoOptionUp(self):
        self.indent = 0.0
        if self.selectedResponse == 0:
            self.selectedResponse = self.intOptionCount-1
        elif self.selectedResponse > 0:
            self.selectedResponse -= 1

    def convoOptionDown(self):
        self.indent = 0.0
        if self.selectedResponse < self.intOptionCount-1:
            self.selectedResponse += 1
        elif self.selectedResponse == self.intOptionCount-1:
            self.selectedResponse = 0

    def convoOptionSelect(self):
        if self.selectedResponse == 0:
            self.convoDepth += ".A.1"
        elif self.selectedResponse == 1:
            self.convoDepth += ".B.1"
        elif self.selectedResponse == 2:
            self.convoDepth += ".C.1"

        self.convoResponseSelected = True
class HUD(DirectObject):
	#TODO: Preload all images
	def __init__(self, base, player):
		self.base   = base
		self.player = player

		self.heartmax = 160
		self.heartmin = 80
		self.heartbpm = self.heartmin
		self.heartaccum = 0
		self.last = 0
		self.heartbasis = 'assets/images/heartbeat2-%d.png'
		self.heartframe = 0
		self.heartimage = OnscreenImage(self.heartbasis % (1,), scale=(0.1,0.1,0.1), pos=(-1,0, 0.8))
		self.keyimage = OnscreenImage('assets/images/key.png', scale=(0.08,0.08,0.08), pos=(-1,0,0.60))
		self.keyimage.setTransparency(TransparencyAttrib.MAlpha)
		self.text = OnscreenText('', pos=(-0.8, 0.8), scale=0.05, fg=(0,1,0,1),	bg=(0,0,0,0))

		self.hasKey = False

		self.base.taskMgr.add(self.update, 'hud')
		
	def __del__(self):
		self.base   = None
		self.player = None
		self.heartimage.destroy()
		self.text.destroy()

	def update(self, task):
		if self.player.isAlive():
			elapsed = task.time - self.last
			self.last = task.time

			# After a certain point, it should be cleared
			# Fear must also increase heartbeat
			f, b = self.player.fear, self.player.breath
			bpm = 80 + 200 * (0.75 + 0.25 * f) * (1 - b) + 40 * f

			self.heartaccum += elapsed * (bpm + self.heartbpm) / 2.0
			self.heartbpm = bpm
			self.heartframe = int(8 * self.heartaccum / 60) % 8
			self.heartimage.setImage(self.heartbasis % (self.heartframe + 1,))
			self.heartimage.setTransparency(TransparencyAttrib.MAlpha)

			#TODO: Update parameters
			heartampl = self.heartmax - self.heartmin
			if self.heartbpm < self.heartmax:
				s = float(self.heartbpm - self.heartmin) / heartampl
				self.text.setFg((s,1,0,1))
			else:
				s = float(self.heartbpm - self.heartmax) / heartampl
				self.text.setFg((1,1-s,0,1))

			self.text.setText('%d BPM' % (self.heartbpm,))
		else:
			self.text.setFg((1,1,1,1))
			self.text.setText('0 BPM')
			#TODO: send a 'death' event and, possibly, play back a nice heart stopping animation
			#return task.done

		if (self.hasKey):
			self.keyimage.show()
		else:
			self.keyimage.hide()
		self.heartimage.show()
		self.text.show()

		return task.cont

	def hide(self):
		self.heartimage.hide()
		self.text.hide()

	def setKey(self, key):
		self.hasKey = key