Exemplo n.º 1
0
class game_controller(object):
    """
    Main game loop and receives GUI callback events for keypresses etc...
    """
    def __init__(self, parent, lines, game_number = 0):
        self.lines = lines
        self.auto_mode = False
        self.game_number = game_number
        if lines != None:
            self.lines = shape.list_from_str_list(lines)
            self.lines_shape_index = 0
            self.auto_mode = True

        

        """
        Intialise the game...
        """
        self.parent = parent
        self.score = 0
        self.level = 0
        self.delay = 1000    #ms
        
        #lookup table
        self.shapes = [square_shape,
                      t_shape,
                      l_shape,
                      reverse_l_shape,
                      z_shape,
                      s_shape,
                      i_shape ]
        
        self.thresholds = level_thresholds( 500, NO_OF_LEVELS )
        
        self.status_bar = status_bar( parent )
        self.status_bar.pack(side=TOP,fill=X)
        #print "Status bar width",self.status_bar.cget("width")

        self.status_bar.set("Score: %-7d\t Level: %d " % (
            self.score, self.level+1)
        )
        #create the status window
        self.status_window = StatusWindow(parent)
        self.status_window.pack()

        #create the game board
        self.board = Board(
            parent,
            scale=SCALE,
            max_x=MAXX,
            max_y=MAXY,
            offset=OFFSET
            )
        
        self.board.pack(side=BOTTOM)
        self.board.focus()
        

        self.parent.bind("<Left>", self.left_callback)
        self.parent.bind("<Right>", self.right_callback)
        self.parent.bind("<Up>", self.up_callback)
        self.parent.bind("<Down>", self.down_callback)
        self.parent.bind("a", self.a_callback)
        self.parent.bind("s", self.s_callback)
        self.parent.bind("p", self.p_callback)
        self.parent.bind("q", self.quit_callback)
        
        self.shape = self.get_next_shape()

        self.after_id = self.parent.after( self.delay, self.move_my_shape )
    
    
    
    def eval(self):
        touching = 0
        already_hit = []
        for block in self.shape.blocks:
            current = block.coord()
            print "current:", current
            
            #create tuples of coordinates of blocks to check
            right = (current[0]+1, current[1])
            left = (current[0]-1, current[1])
            #TK coord system is down and to right
            #that's why up and down are reversed
            down = (current[0], current[1]+1)
            up = (current[0], current[1]-1)
            
            right_hit = self.board.landed.get(right)
            left_hit = self.board.landed.get(left)
            up_hit = self.board.landed.get(up)
            down_hit = self.board.landed.get(down)
            
            
            if( right_hit and (right not in already_hit)):
                print "\tright hit", right
                already_hit.append(right)
                touching += 1
            if ( left_hit and (left not in already_hit) ):
                print "\tleft hit", left
                already_hit.append(left)
                touching += 1
            if ( up_hit and (up not in already_hit) ):
                print "\tup hit", up
                already_hit.append(up)
                touching += 1
            if ( down_hit and (down not in already_hit) ):
                print "\tdown hit", down
                already_hit.append(down)
                touching += 1
        print "\tTouching: ", touching
        print "-"*20
        
        
    def handle_move(self, direction):
        #if you can't move then you've hit something
        if not self.shape.move( direction ):
            self.status_window.log_text("HIT")
            # if your heading down then the shape has 'landed'
            if direction == DOWN:
                self.eval()
                tmp_score = self.score
                self.score += self.board.check_for_complete_row(
                    self.shape.blocks
                    )
                #check for points added                
                if(self.score > tmp_score):
                    self.status_window.log_text("POINTS " + str(self.score - tmp_score))
                    
                del self.shape
                self.status_window.log_text("LANDED")
                self.shape = self.get_next_shape()

                # If the shape returned is None, then this indicates that
                # that the check before creating it failed and the
                # game is over!
                if self.shape is None:
                    self.status_window.log_text("GAME OVER! SCORE: " + str(self.score))
                    tkMessageBox.showwarning(
                        title="GAME OVER",
                        message ="Score: %7d\tLevel: %d\t" % (
                            self.score, self.level),

                        )

                    Toplevel().quit()
                    self.parent.quit()

                    # self.status_window.quit()
                    # self.status_window.destroy()
                    # sys.exit(0) 
                
                # do we go up a level?
                if (self.level < NO_OF_LEVELS and 
                    self.score >= self.thresholds[ self.level]):
                    self.level+=1
                    self.delay-=100
                    
                self.status_bar.set("Score: %-7d\t Level: %d " % (
                    self.score, self.level+1)
                )
                
                # Signal that the shape has 'landed'
                return False
        return True

    def left_callback( self, event ):
        if self.shape:
            self.status_window.log_text("LEFT")
            self.handle_move( LEFT )
        
    def right_callback( self, event ):
        if self.shape:
            self.status_window.log_text("RIGHT")
            self.handle_move( RIGHT )

    def up_callback( self, event ):
        if self.shape:
            # drop the tetrominoe to the bottom
            while self.handle_move( DOWN ):
                pass

    def down_callback( self, event ):
        if self.shape:
            self.status_window.log_text("DOWN")            
            self.handle_move( DOWN )
            
    def a_callback( self, event):
        if self.shape:
            self.shape.rotate(clockwise=True)
            self.status_window.log_text("ROTATE CLOCKWISE")           
            
    def s_callback( self, event):
        if self.shape:
            self.shape.rotate(clockwise=False)
            self.status_window.log_text("ROTATE COUNTERCLOCKWISE")           
        
    def p_callback(self, event):
        self.parent.after_cancel( self.after_id )
        tkMessageBox.askquestion(
            title = "Paused!",
            message="Continue?",
            type=tkMessageBox.OK)
        self.after_id = self.parent.after( self.delay, self.move_my_shape )
    
    def quit_callback(self, event):
        sys.exit(0)

    def move_my_shape( self ):
        if self.shape:
            self.handle_move( DOWN )
            self.after_id = self.parent.after( self.delay, self.move_my_shape )
        
    def get_next_shape( self ):
        """
        Select the next shape in the list
        """
        if self.lines and len(self.lines) > 0 and self.lines_shape_index < len(self.lines): 
            the_shape = self.lines[self.lines_shape_index]
            self.lines_shape_index = self.lines_shape_index + 1
        else:
            """
            If we were in auto mode, that means we have now ran out of pieces
            Log the score, and move on to the next game
            """
            if self.auto_mode == True:
                print "Game #" + str(self.game_number) + " " + "Score: " + str(self.score)
                return None #This will end the game
            
            """
            Randomly select which tetrominoe will be used next.
            """
            self.shapes = self.status_window.get_shapes()
            the_shape = self.shapes[ randint(0,len(self.shapes)-1) ]

        #check_and_create is a factory function
        s = the_shape.check_and_create(self.board)
        self.status_window.new_shape(s)
        self.status_window.log_board(self.board)
        BoardStates.generate_child_states(self.board, the_shape)
        return s
Exemplo n.º 2
0
class game_controller(object):
    """
    Main game loop and receives GUI callback events for keypresses etc...
    """
    def __init__(self, parent, lines, game_number=0):
        self.lines = lines
        self.auto_mode = False
        self.game_number = game_number
        if lines != None:
            self.lines = shape.list_from_str_list(lines)
            self.lines_shape_index = 0
            self.auto_mode = True
        """
        Intialise the game...
        """
        self.parent = parent
        self.score = 0
        self.level = 0
        self.delay = 1000  #ms

        #lookup table
        self.shapes = [
            square_shape, t_shape, l_shape, reverse_l_shape, z_shape, s_shape,
            i_shape
        ]

        self.thresholds = level_thresholds(500, NO_OF_LEVELS)

        self.status_bar = status_bar(parent)
        self.status_bar.pack(side=TOP, fill=X)
        #print "Status bar width",self.status_bar.cget("width")

        self.status_bar.set("Score: %-7d\t Level: %d " %
                            (self.score, self.level + 1))
        #create the status window
        self.status_window = StatusWindow(parent)
        self.status_window.pack()

        #create the game board
        self.board = Board(parent,
                           scale=SCALE,
                           max_x=MAXX,
                           max_y=MAXY,
                           offset=OFFSET)

        self.board.pack(side=BOTTOM)
        self.board.focus()

        self.parent.bind("<Left>", self.left_callback)
        self.parent.bind("<Right>", self.right_callback)
        self.parent.bind("<Up>", self.up_callback)
        self.parent.bind("<Down>", self.down_callback)
        self.parent.bind("a", self.a_callback)
        self.parent.bind("s", self.s_callback)
        self.parent.bind("p", self.p_callback)
        self.parent.bind("q", self.quit_callback)

        self.shape = self.get_next_shape()

        self.after_id = self.parent.after(self.delay, self.move_my_shape)

    def eval(self):
        touching = 0
        already_hit = []
        for block in self.shape.blocks:
            current = block.coord()
            print "current:", current

            #create tuples of coordinates of blocks to check
            right = (current[0] + 1, current[1])
            left = (current[0] - 1, current[1])
            #TK coord system is down and to right
            #that's why up and down are reversed
            down = (current[0], current[1] + 1)
            up = (current[0], current[1] - 1)

            right_hit = self.board.landed.get(right)
            left_hit = self.board.landed.get(left)
            up_hit = self.board.landed.get(up)
            down_hit = self.board.landed.get(down)

            if (right_hit and (right not in already_hit)):
                print "\tright hit", right
                already_hit.append(right)
                touching += 1
            if (left_hit and (left not in already_hit)):
                print "\tleft hit", left
                already_hit.append(left)
                touching += 1
            if (up_hit and (up not in already_hit)):
                print "\tup hit", up
                already_hit.append(up)
                touching += 1
            if (down_hit and (down not in already_hit)):
                print "\tdown hit", down
                already_hit.append(down)
                touching += 1
        print "\tTouching: ", touching
        print "-" * 20

    def handle_move(self, direction):
        #if you can't move then you've hit something
        if not self.shape.move(direction):
            self.status_window.log_text("HIT")
            # if your heading down then the shape has 'landed'
            if direction == DOWN:
                self.eval()
                tmp_score = self.score
                self.score += self.board.check_for_complete_row(
                    self.shape.blocks)
                #check for points added
                if (self.score > tmp_score):
                    self.status_window.log_text("POINTS " +
                                                str(self.score - tmp_score))

                del self.shape
                self.status_window.log_text("LANDED")
                self.shape = self.get_next_shape()

                # If the shape returned is None, then this indicates that
                # that the check before creating it failed and the
                # game is over!
                if self.shape is None:
                    self.status_window.log_text("GAME OVER! SCORE: " +
                                                str(self.score))
                    tkMessageBox.showwarning(
                        title="GAME OVER",
                        message="Score: %7d\tLevel: %d\t" %
                        (self.score, self.level),
                    )

                    Toplevel().quit()
                    self.parent.quit()

                    # self.status_window.quit()
                    # self.status_window.destroy()
                    # sys.exit(0)

                # do we go up a level?
                if (self.level < NO_OF_LEVELS
                        and self.score >= self.thresholds[self.level]):
                    self.level += 1
                    self.delay -= 100

                self.status_bar.set("Score: %-7d\t Level: %d " %
                                    (self.score, self.level + 1))

                # Signal that the shape has 'landed'
                return False
        return True

    def left_callback(self, event):
        if self.shape:
            self.status_window.log_text("LEFT")
            self.handle_move(LEFT)

    def right_callback(self, event):
        if self.shape:
            self.status_window.log_text("RIGHT")
            self.handle_move(RIGHT)

    def up_callback(self, event):
        if self.shape:
            # drop the tetrominoe to the bottom
            while self.handle_move(DOWN):
                pass

    def down_callback(self, event):
        if self.shape:
            self.status_window.log_text("DOWN")
            self.handle_move(DOWN)

    def a_callback(self, event):
        if self.shape:
            self.shape.rotate(clockwise=True)
            self.status_window.log_text("ROTATE CLOCKWISE")

    def s_callback(self, event):
        if self.shape:
            self.shape.rotate(clockwise=False)
            self.status_window.log_text("ROTATE COUNTERCLOCKWISE")

    def p_callback(self, event):
        self.parent.after_cancel(self.after_id)
        tkMessageBox.askquestion(title="Paused!",
                                 message="Continue?",
                                 type=tkMessageBox.OK)
        self.after_id = self.parent.after(self.delay, self.move_my_shape)

    def quit_callback(self, event):
        sys.exit(0)

    def move_my_shape(self):
        if self.shape:
            self.handle_move(DOWN)
            self.after_id = self.parent.after(self.delay, self.move_my_shape)

    def get_next_shape(self):
        """
        Select the next shape in the list
        """
        if self.lines and len(self.lines) > 0 and self.lines_shape_index < len(
                self.lines):
            the_shape = self.lines[self.lines_shape_index]
            self.lines_shape_index = self.lines_shape_index + 1
        else:
            """
            If we were in auto mode, that means we have now ran out of pieces
            Log the score, and move on to the next game
            """
            if self.auto_mode == True:
                print "Game #" + str(self.game_number) + " " + "Score: " + str(
                    self.score)
                return None  #This will end the game
            """
            Randomly select which tetrominoe will be used next.
            """
            self.shapes = self.status_window.get_shapes()
            the_shape = self.shapes[randint(0, len(self.shapes) - 1)]

        #check_and_create is a factory function
        s = the_shape.check_and_create(self.board)
        self.status_window.new_shape(s)
        self.status_window.log_board(self.board)
        BoardStates.generate_child_states(self.board, the_shape)
        return s