예제 #1
0
class Text(Billboard):
    def __init__(self,
                 name,
                 nodePath,
                 offset,
                 text,
                 stencilId,
                 scale=0.025000000000000001,
                 *args,
                 **kwargs):
        Billboard.__init__(self, name, nodePath, *args, **kwargs)
        self.setBin('fixed', 110)
        self.scale = scale
        self.textNode = OnscreenText(text=text,
                                     fg=Vec4(0, 0, 0, 1),
                                     scale=scale,
                                     shadow=Vec4(0, 0, 0, 0),
                                     mayChange=True,
                                     font=PiratesGlobals.getPirateFont())
        self.textNode.detachNode()
        sNode = self.attachNewNode('stencil')
        sNode.setY(-offset)
        self.textNode.instanceTo(sNode)
        sNode.setDepthTest(False)

    def setBold(self, bold):
        self.textNode.setShadow(Vec4(0, 0, 0, bold))

    def setTextScale(self, scale):
        self.textNode.setScale(self.scale * scale)
예제 #2
0
class Text(Billboard):

    def __init__(self, name, nodePath, offset, text, stencilId, scale = 0.025000000000000001, *args, **kwargs):
        Billboard.__init__(self, name, nodePath, *args, **kwargs)
        self.setBin('fixed', 110)
        self.scale = scale
        self.textNode = OnscreenText(text = text, fg = Vec4(0, 0, 0, 1), scale = scale, shadow = Vec4(0, 0, 0, 0), mayChange = True, font = PiratesGlobals.getPirateFont())
        self.textNode.detachNode()
        sNode = self.attachNewNode('stencil')
        sNode.setY(-offset)
        self.textNode.instanceTo(sNode)
        sNode.setDepthTest(False)


    def setBold(self, bold):
        self.textNode.setShadow(Vec4(0, 0, 0, bold))


    def setTextScale(self, scale):
        self.textNode.setScale(self.scale * scale)
예제 #3
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
예제 #4
0
class GameTextBox(DirectObject, NodePath):
    '''游戏文本显示器类  Main displayer of current game text.
        继承自Panda3D的DirectFram
    Attributes:
        currentText: A list that includes current game text (see sogal_text's recordedText)
        currentSpeaker: A string that represents the speaker
        textFont: The font of the text
        properties: Properties of the text box. 
    '''
    

    
    def __init__(self):
        '''
        Constructor
        '''
        self.currentText = []
        self.currentSpeaker = ""
        self.newText = None
        self.textfont = None
        self.properties = copy.deepcopy(base.getStyle('textbox'))
        self._normal_speakerLabel = None
        self._normal_textLabel = None
        self._large_label = None
        self._frame = None
        self._textArrow = None
        self.__namescale = None
        
        NodePath.__init__(self, 'GameTextBox')
        self.reparentTo(aspect2d)
        self.reload()
    
    def presave(self):
        runtime_data.RuntimeData.current_text = [self.currentText, self.currentSpeaker]
                    
    def reload(self):
        if runtime_data.RuntimeData.gameTextBox_properties: #this creates an reference
            self.properties = runtime_data.RuntimeData.gameTextBox_properties
        else: runtime_data.RuntimeData.gameTextBox_properties = self.properties
        
        self.applyStyle()
        
        if runtime_data.RuntimeData.current_text:
            if runtime_data.RuntimeData.current_text[0]:
                self.currentText = copy.copy(runtime_data.RuntimeData.current_text[0]) 
                if self.currentTextLabel:
                    self.currentTextLabel.loadRecordedText(runtime_data.RuntimeData.current_text[0])
            if runtime_data.RuntimeData.current_text[1]:
                self.currentSpeaker = runtime_data.RuntimeData.current_text[1]
                if self._normal_speakerLabel:
                    self._normal_speakerLabel.setText(runtime_data.RuntimeData.current_text[1])
                    
    def reloadTheme(self):
        self.properties = copy.deepcopy(base.getStyle('textbox'))
        runtime_data.RuntimeData.gameTextBox_properties = self.properties
        self.applyStyle()
    
    def showArrow(self):
        if self._textArrow: 
            if self.currentTextLabel:
                '''
                self._textArrow.setPos(self._frame.getWidth()/2-self.properties['arrow_rightspace'],
                             0,
                             self.currentTextLabel.textNode.getLowerRight3d()[2]-0.03)
                '''
                apos = self._frame.getRelativePoint(self.currentTextLabel, self.currentTextLabel.getEndPos())
                apos = (self._frame.getWidth()/2-self.properties['arrow_rightspace'],
                        0,
                        apos[2])
                self._textArrow.setPos(apos)
            else: self._textArrow.setPos(0,0,0)
            self._textArrow.show()
            
    def hideArrow(self):
        if self._textArrow:
            self._textArrow.hide()
    
            
    def quickFinish(self):
        '''Finish the current text typer quickly
        '''
        if self.currentTextLabel:
            self.currentTextLabel.quickFinish()

    def destroyElements(self):
        self.currentText = []
        self.currentSpeaker = None
        self.newText = ''

        
        if self._textArrow:
            self._textArrow.removeNode()
            self._textArrow = None
        
        if self._normal_textLabel:
            self._normal_textLabel.destroy()
            self._normal_textLabel = None
            
        if self._normal_speakerLabel:
            self._normal_speakerLabel.destroy()
            self._normal_speakerLabel = None
            
        if self._frame:
            self._frame.destroy()
            self._frame = None
            
        if self._large_label:
            self._large_label.destroy()
            self._large_label = None
            

        
    def destroy(self, *args, **kwargs):
        if self.currentTextLabel:
            self.currentTextLabel.destroy
        if self._frame:
            self._frame.destroy()
            self._frame = None
 
    def clearText(self):
        '''make current text empty'''

        self.currentText = []
        self.currentSpeaker = None
        self.newText = ''
        
        if self.currentTextLabel:
            self.currentTextLabel.clear()
        if self._currentStyle == GameTextBoxStyle.Normal and self._normal_speakerLabel:
            self._normal_speakerLabel.setText('')
            
        
    
    def pushText(self, text, speaker = None, continuous = False, text_speed = None, fadein = None, rate = 1.0,read = False):
        '''添加文字
        进行判断并改变文字
        parameters:
            speaker: A string contains the speaker's name. (None means no speaker)
            read: see if the text is already read
        '''
        if self.currentTextLabel and self.currentTextLabel.isWaiting():
            self.currentTextLabel.quickFinish()
        
        #The text is necessary
        if not text:
            return
        
        text = text.rstrip('\n')
        
        text_speed = (text_speed or base.getStyle('textbox')['text_speed'] or runtime_data.game_settings['text_speed']) * rate
        if fadein is None:
            fadein = base.getStyle('textbox')['text_fadein_duration']
        fadein_style = base.getStyle('textbox')['text_fadein_style']
        
        if self._currentStyle == GameTextBoxStyle.Normal:
            if not continuous:
                self.currentTextLabel.clear()
        elif self._currentStyle == GameTextBoxStyle.Large:
            if not continuous and self.currentTextLabel.hasContent():
                self.currentTextLabel.appendText('\n') #Inserting an empty line
       

        if continuous:    #When continuous, ignore the speaker
            speaker = None  
            #self.currentSpeaker = ''
        else:
            self.currentSpeaker = speaker
        
        if self._currentStyle == GameTextBoxStyle.Normal:
            if not continuous:
                if speaker:
                    self._normal_speakerLabel.setText(self.currentSpeaker) #TODO: use SogalText
                else:
                    self._normal_speakerLabel.setText(' ')
        elif self._currentStyle == GameTextBoxStyle.Large:
            if speaker:
                self.currentTextLabel.appendText(self.currentSpeaker,custom = True, newLine = True, 
                                                 textScale = self.__namescale)
                

        self.newText = text
        
        #This is *very* useful
        safeprint(self.newText)
        
        if not read:
            self.currentTextLabel.appendText(self.newText, speed = text_speed , newLine = (not continuous) , fadein = fadein, 
                                                 fadeinType = fadein_style)
        else:
            self.currentTextLabel.appendText(self.newText, speed = text_speed , newLine = (not continuous) , fadein = fadein, 
                                                 fadeinType = fadein_style, custom = True, fg = self.properties['read_fg'])            
        
        self.currentText = self.currentTextLabel.getCopiedText()
        
        #TODO: FADING TEXT AND TYPER AGAIN

    
    _currentStyle = None
    @property
    def currentStyle(self):
        '''Style of this box
        '''
        return self._currentStyle
    
    @property
    def currentTextLabel(self):
        '''current text label
        '''
        if self._currentStyle == GameTextBoxStyle.Normal:
            return self._normal_textLabel
        elif self._currentStyle == GameTextBoxStyle.Large:
            return self._large_label
    
    def applyStyle(self):
        '''套用风格 Apply style setting.
        override this to apply your own style
        '''
#        窝才想起来这是引用不是浅拷贝……所以构造函数中运行这个就能同步runtime_data了lol
#         if runtime_data.RuntimeData.gameTextBox_properties:  
#             self.properties = runtime_data.RuntimeData.gameTextBox_properties
#         else: runtime_data.RuntimeData.gameTextBox_properties = self.properties
        
        self.destroyElements()
        
        if self.properties.has_key('style'):
            self.setTextBoxStyle(self.properties['style'])
        else: self.setTextBoxStyle('normal')
            
        st = self._currentStyle
        
        if st == GameTextBoxStyle.Normal:
            height = self.properties['normal_height']
            width = self.properties['normal_width']
            
            
            self._frame = DirectFrame(
                    parent      = self,
                    frameSize   = (-width/2.0,width/2.0,-height/2.0,height/2.0),
                    frameColor  = self.properties['background_color'],
                    )
            
            if self.currentSpeaker:
                speaker = self.currentSpeaker
            else: speaker = ''
            
            self._normal_speakerLabel = OnscreenText(parent = self._frame
                                      , text = speaker
                                      , font = base.textFont
                                      , fg = self.properties['foreground_color']
                                      , mayChange = True  # @UndefinedVariable
                                      , align = TextNode.ALeft#@UndefinedVariable
                                      , scale = self.properties['normal_name_scale']
                                      )  
            
            self._normal_textLabel = SogalText(parent = self._frame,
                                               font = base.textFont,
                                               fg = self.properties['foreground_color'],
                                               scale = self.properties['normal_text_scale'],
                                               shadow = (0.1,0.1,0.1,0.5),
                                               pos = (-width/2.0 + self.properties['normal_text_pos'][0],
                                                      0,
                                                      height/2.0 + self.properties['normal_text_pos'][1]),
                                               wordwrap = self.properties['normal_text_wrap']
                                               )  
            

            self.setPos(self.properties['normal_pos'][0],0,self.properties['normal_pos'][1])
            
            
            self._normal_speakerLabel.setPos(-width/2.0 + self.properties['normal_name_pos'][0], 
                                          height/2.0 + self.properties['normal_name_pos'][1])
    
            self._normal_speakerLabel.setShadow((0.1,0.1,0.1,0.5))
            
            self._normal_textLabel.textMaker.setTabWidth(1.0)
            
            
        elif st == GameTextBoxStyle.Large:
            
           
            self.__namescale = self.properties['large_name_scale']/self.properties['large_text_scale']
            
            height = self.properties['large_height']
            width = self.properties['large_width']
              
            self._frame = DirectFrame(
                    parent      = self,
                    frameSize   = (-width/2.0,width/2.0,-height/2.0,height/2.0),
                    frameColor  = self.properties['background_color'],
                    )
            
            self._large_label = SogalText(parent = self._frame,
                                          font = base.textFont,
                                          fg = self.properties['foreground_color'],
                                          scale = self.properties['large_text_scale'],
                                          shadow = (0.1,0.1,0.1,0.5),
                                          pos = (-width/2.0 + self.properties['large_text_pos'][0],
                                                 0,
                                                 height/2.0 + self.properties['large_text_pos'][1]),
                                          wordwrap = self.properties['large_text_wrap']
                                         )  
            

            self.setPos(self.properties['large_pos'][0],0,self.properties['large_pos'][1])
            
            
    
            
            self._large_label.textMaker.setTabWidth(1.0)
           
        #generate an arrow after text 
        arrow = loader.loadModel('models/text_arrow/text_arrow')  # @UndefinedVariable
        arrow.reparentTo(self._frame)
        arrow.setColor(self.properties['arrow_color'])
        arrow.setScale(self.properties['arrow_scale'])
        width = 2.0
        if self._currentStyle == GameTextBoxStyle.Normal:
            width = self.properties['normal_width']
        elif self._currentStyle == GameTextBoxStyle.Large:
            width = self.properties['large_width']

        self._textArrow = arrow
        self._textArrow.hide()

    def setTextBoxStyle(self, style):
        if style.strip() == 'normal':
            self._currentStyle = GameTextBoxStyle.Normal
        elif style.strip() == 'large':
            self._currentStyle = GameTextBoxStyle.Large
        else: safeprint('Unknown style: ' + str(style))
        self.properties['style'] = style
        
        


    def paragraphSparator(self):
        #if self._currentStyle == GameTextBoxStyle.Large:
        self.clearText()

    def setTextBoxProperty(self, propname, value):
        runtime_data.RuntimeData.gameTextBox_properties[propname] = value

    def applyTextBoxProperties(self):
        self.applyStyle()
       
            
    def getIsWaitingForText(self):
        is_waiting = False
        
        if self.currentTextLabel:
            is_waiting = self.currentTextLabel.isWaiting()
        
        return is_waiting
    
    
    def getIsWaiting(self):
        '''Inherited from GameTextBoxBase
        Get whether the text typer is unfinished
        '''
        return self.getIsWaitingForText()


        


        
예제 #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
예제 #6
0
class GameTextBox(DirectObject, NodePath):
    '''游戏文本显示器类  Main displayer of current game text.
        继承自Panda3D的DirectFram
    Attributes:
        currentText: A list that includes current game text (see sogal_text's recordedText)
        currentSpeaker: A string that represents the speaker
        textFont: The font of the text
        properties: Properties of the text box. 
    '''
    def __init__(self):
        '''
        Constructor
        '''
        self.currentText = []
        self.currentSpeaker = ""
        self.newText = None
        self.textfont = None
        self.properties = copy.deepcopy(base.getStyle('textbox'))
        self._normal_speakerLabel = None
        self._normal_textLabel = None
        self._large_label = None
        self._frame = None
        self._textArrow = None
        self.__namescale = None

        NodePath.__init__(self, 'GameTextBox')
        self.reparentTo(aspect2d)
        self.reload()

    def presave(self):
        runtime_data.RuntimeData.current_text = [
            self.currentText, self.currentSpeaker
        ]

    def reload(self):
        if runtime_data.RuntimeData.gameTextBox_properties:  #this creates an reference
            self.properties = runtime_data.RuntimeData.gameTextBox_properties
        else:
            runtime_data.RuntimeData.gameTextBox_properties = self.properties

        self.applyStyle()

        if runtime_data.RuntimeData.current_text:
            if runtime_data.RuntimeData.current_text[0]:
                self.currentText = copy.copy(
                    runtime_data.RuntimeData.current_text[0])
                if self.currentTextLabel:
                    self.currentTextLabel.loadRecordedText(
                        runtime_data.RuntimeData.current_text[0])
            if runtime_data.RuntimeData.current_text[1]:
                self.currentSpeaker = runtime_data.RuntimeData.current_text[1]
                if self._normal_speakerLabel:
                    self._normal_speakerLabel.setText(
                        runtime_data.RuntimeData.current_text[1])

    def reloadTheme(self):
        self.properties = copy.deepcopy(base.getStyle('textbox'))
        runtime_data.RuntimeData.gameTextBox_properties = self.properties
        self.applyStyle()

    def showArrow(self):
        if self._textArrow:
            if self.currentTextLabel:
                '''
                self._textArrow.setPos(self._frame.getWidth()/2-self.properties['arrow_rightspace'],
                             0,
                             self.currentTextLabel.textNode.getLowerRight3d()[2]-0.03)
                '''
                apos = self._frame.getRelativePoint(
                    self.currentTextLabel, self.currentTextLabel.getEndPos())
                apos = (self._frame.getWidth() / 2 -
                        self.properties['arrow_rightspace'], 0, apos[2])
                self._textArrow.setPos(apos)
            else:
                self._textArrow.setPos(0, 0, 0)
            self._textArrow.show()

    def hideArrow(self):
        if self._textArrow:
            self._textArrow.hide()

    def quickFinish(self):
        '''Finish the current text typer quickly
        '''
        if self.currentTextLabel:
            self.currentTextLabel.quickFinish()

    def destroyElements(self):
        self.currentText = []
        self.currentSpeaker = None
        self.newText = ''

        if self._textArrow:
            self._textArrow.removeNode()
            self._textArrow = None

        if self._normal_textLabel:
            self._normal_textLabel.destroy()
            self._normal_textLabel = None

        if self._normal_speakerLabel:
            self._normal_speakerLabel.destroy()
            self._normal_speakerLabel = None

        if self._frame:
            self._frame.destroy()
            self._frame = None

        if self._large_label:
            self._large_label.destroy()
            self._large_label = None

    def destroy(self, *args, **kwargs):
        if self.currentTextLabel:
            self.currentTextLabel.destroy
        if self._frame:
            self._frame.destroy()
            self._frame = None

    def clearText(self):
        '''make current text empty'''

        self.currentText = []
        self.currentSpeaker = None
        self.newText = ''

        if self.currentTextLabel:
            self.currentTextLabel.clear()
        if self._currentStyle == GameTextBoxStyle.Normal and self._normal_speakerLabel:
            self._normal_speakerLabel.setText('')

    def pushText(self,
                 text,
                 speaker=None,
                 continuous=False,
                 text_speed=None,
                 fadein=None,
                 rate=1.0,
                 read=False):
        '''添加文字
        进行判断并改变文字
        parameters:
            speaker: A string contains the speaker's name. (None means no speaker)
            read: see if the text is already read
        '''
        if self.currentTextLabel and self.currentTextLabel.isWaiting():
            self.currentTextLabel.quickFinish()

        #The text is necessary
        if not text:
            return

        text = text.rstrip('\n')

        text_speed = (text_speed or base.getStyle('textbox')['text_speed']
                      or runtime_data.game_settings['text_speed']) * rate
        if fadein is None:
            fadein = base.getStyle('textbox')['text_fadein_duration']
        fadein_style = base.getStyle('textbox')['text_fadein_style']

        if self._currentStyle == GameTextBoxStyle.Normal:
            if not continuous:
                self.currentTextLabel.clear()
        elif self._currentStyle == GameTextBoxStyle.Large:
            if not continuous and self.currentTextLabel.hasContent():
                self.currentTextLabel.appendText(
                    '\n')  #Inserting an empty line

        if continuous:  #When continuous, ignore the speaker
            speaker = None
            #self.currentSpeaker = ''
        else:
            self.currentSpeaker = speaker

        if self._currentStyle == GameTextBoxStyle.Normal:
            if not continuous:
                if speaker:
                    self._normal_speakerLabel.setText(
                        self.currentSpeaker)  #TODO: use SogalText
                else:
                    self._normal_speakerLabel.setText(' ')
        elif self._currentStyle == GameTextBoxStyle.Large:
            if speaker:
                self.currentTextLabel.appendText(self.currentSpeaker,
                                                 custom=True,
                                                 newLine=True,
                                                 textScale=self.__namescale)

        self.newText = text

        #This is *very* useful
        safeprint(self.newText)

        if not read:
            self.currentTextLabel.appendText(self.newText,
                                             speed=text_speed,
                                             newLine=(not continuous),
                                             fadein=fadein,
                                             fadeinType=fadein_style)
        else:
            self.currentTextLabel.appendText(self.newText,
                                             speed=text_speed,
                                             newLine=(not continuous),
                                             fadein=fadein,
                                             fadeinType=fadein_style,
                                             custom=True,
                                             fg=self.properties['read_fg'])

        self.currentText = self.currentTextLabel.getCopiedText()

        #TODO: FADING TEXT AND TYPER AGAIN

    _currentStyle = None

    @property
    def currentStyle(self):
        '''Style of this box
        '''
        return self._currentStyle

    @property
    def currentTextLabel(self):
        '''current text label
        '''
        if self._currentStyle == GameTextBoxStyle.Normal:
            return self._normal_textLabel
        elif self._currentStyle == GameTextBoxStyle.Large:
            return self._large_label

    def applyStyle(self):
        '''套用风格 Apply style setting.
        override this to apply your own style
        '''
        #        窝才想起来这是引用不是浅拷贝……所以构造函数中运行这个就能同步runtime_data了lol
        #         if runtime_data.RuntimeData.gameTextBox_properties:
        #             self.properties = runtime_data.RuntimeData.gameTextBox_properties
        #         else: runtime_data.RuntimeData.gameTextBox_properties = self.properties

        self.destroyElements()

        if self.properties.has_key('style'):
            self.setTextBoxStyle(self.properties['style'])
        else:
            self.setTextBoxStyle('normal')

        st = self._currentStyle

        if st == GameTextBoxStyle.Normal:
            height = self.properties['normal_height']
            width = self.properties['normal_width']

            self._frame = DirectFrame(
                parent=self,
                frameSize=(-width / 2.0, width / 2.0, -height / 2.0,
                           height / 2.0),
                frameColor=self.properties['background_color'],
            )

            if self.currentSpeaker:
                speaker = self.currentSpeaker
            else:
                speaker = ''

            self._normal_speakerLabel = OnscreenText(
                parent=self._frame,
                text=speaker,
                font=base.textFont,
                fg=self.properties['foreground_color'],
                mayChange=True  # @UndefinedVariable
                ,
                align=TextNode.ALeft  #@UndefinedVariable
                ,
                scale=self.properties['normal_name_scale'])

            self._normal_textLabel = SogalText(
                parent=self._frame,
                font=base.textFont,
                fg=self.properties['foreground_color'],
                scale=self.properties['normal_text_scale'],
                shadow=(0.1, 0.1, 0.1, 0.5),
                pos=(-width / 2.0 + self.properties['normal_text_pos'][0], 0,
                     height / 2.0 + self.properties['normal_text_pos'][1]),
                wordwrap=self.properties['normal_text_wrap'])

            self.setPos(self.properties['normal_pos'][0], 0,
                        self.properties['normal_pos'][1])

            self._normal_speakerLabel.setPos(
                -width / 2.0 + self.properties['normal_name_pos'][0],
                height / 2.0 + self.properties['normal_name_pos'][1])

            self._normal_speakerLabel.setShadow((0.1, 0.1, 0.1, 0.5))

            self._normal_textLabel.textMaker.setTabWidth(1.0)

        elif st == GameTextBoxStyle.Large:

            self.__namescale = self.properties[
                'large_name_scale'] / self.properties['large_text_scale']

            height = self.properties['large_height']
            width = self.properties['large_width']

            self._frame = DirectFrame(
                parent=self,
                frameSize=(-width / 2.0, width / 2.0, -height / 2.0,
                           height / 2.0),
                frameColor=self.properties['background_color'],
            )

            self._large_label = SogalText(
                parent=self._frame,
                font=base.textFont,
                fg=self.properties['foreground_color'],
                scale=self.properties['large_text_scale'],
                shadow=(0.1, 0.1, 0.1, 0.5),
                pos=(-width / 2.0 + self.properties['large_text_pos'][0], 0,
                     height / 2.0 + self.properties['large_text_pos'][1]),
                wordwrap=self.properties['large_text_wrap'])

            self.setPos(self.properties['large_pos'][0], 0,
                        self.properties['large_pos'][1])

            self._large_label.textMaker.setTabWidth(1.0)

        #generate an arrow after text
        arrow = loader.loadModel(
            'models/text_arrow/text_arrow')  # @UndefinedVariable
        arrow.reparentTo(self._frame)
        arrow.setColor(self.properties['arrow_color'])
        arrow.setScale(self.properties['arrow_scale'])
        width = 2.0
        if self._currentStyle == GameTextBoxStyle.Normal:
            width = self.properties['normal_width']
        elif self._currentStyle == GameTextBoxStyle.Large:
            width = self.properties['large_width']

        self._textArrow = arrow
        self._textArrow.hide()

    def setTextBoxStyle(self, style):
        if style.strip() == 'normal':
            self._currentStyle = GameTextBoxStyle.Normal
        elif style.strip() == 'large':
            self._currentStyle = GameTextBoxStyle.Large
        else:
            safeprint('Unknown style: ' + str(style))
        self.properties['style'] = style

    def paragraphSparator(self):
        #if self._currentStyle == GameTextBoxStyle.Large:
        self.clearText()

    def setTextBoxProperty(self, propname, value):
        runtime_data.RuntimeData.gameTextBox_properties[propname] = value

    def applyTextBoxProperties(self):
        self.applyStyle()

    def getIsWaitingForText(self):
        is_waiting = False

        if self.currentTextLabel:
            is_waiting = self.currentTextLabel.isWaiting()

        return is_waiting

    def getIsWaiting(self):
        '''Inherited from GameTextBoxBase
        Get whether the text typer is unfinished
        '''
        return self.getIsWaitingForText()