class TetrisGame(object):

    #one-time initialization for gui etc
    def __init__(self):
        print "initialize tetris"
        self.gui = [PygameGoodRenderer(), LedRenderer()]
        self.input = DdrInput()
        while True:
            self.init_game()

    #initializes each game
    def init_game(self):
        print "init next game"
        self.boards = [Board(MAXX,MAXY), Board(MAXX,MAXY)]
        self.players = [None,None]
        self.gameState = GameState()
        self.board_animation(0,"up_arrow")
        self.board_animation(1,"up_arrow")
        self.start_time = None
        self.input.reset()
        self.update_gui()
        self.handle_input() #this calls all other functions, such as add_player, start_game
       
    def add_player(self,num): # 0=left, 1=right
        print "adding player",num
        if self.players[num]==None:
            self.boards[num].clear()
            p = Player(num, self.gameState, self.boards[num], self.boards[(num+1)%2])
            self.players[num] = p
            self.board_animation(num,"down_arrow")
            self.gameState.num_players+=1
            self.update_gui()
        
    def start_game(self):
        print "start game"
        self.boards[0].clear()
        self.boards[1].clear()
        self.gameState.state = "playing"
        self.update_gui()
        self.start_time = time()
        self.drop_time = time()
        self.gravity()

    def handle_input(self):
        
        game_on = True
        t = 0
        while game_on:
            t+=1
            
            if (self.gameState.state=="ending") or (self.gameState.state=="playing" and time()-self.start_time > TIME_LIMIT):
                self.end_game()
                game_on = False
                return
            if self.gameState.state=="playing" and time()-self.drop_time > self.gameState.delay/1000.0:
                self.gravity()
                self.drop_time = time()
                if self.gameState.state != "ending":
                    self.update_gui()
                
            ev = self.input.poll()
            if ev:
                player,direction = ev
                #print "Player",player,direction
                if direction == DIE: #Exit instruction
                    game_on = False
                    pygame.quit()
                    sys.exit()
                if self.gameState.state=="playing":
                    if self.players[player]!=None:
                        #DROP is only for debugging purposes for now, to make the game end.
                        if direction == DROP:
                            while self.players[player].handle_move( DOWN ):
                                pass
                        else:
                            self.players[player].handle_move(direction)
                elif self.gameState.state == "waiting":
                    if direction==UP:
                        self.add_player(player)
                    elif direction==DOWN:
                        if self.players[player]!=None:
                            self.start_game()
                
                self.update_gui()
         
            elif t%10000==0:
                t=0
                self.update_gui()
                
                
                
    def gravity(self):
        for p in self.players:
            if p:
                p.handle_move(DOWN)
            
    def update_gui(self):
        [gui.render_game(self.to_dict()) for gui in self.gui]
        #self.gui[0].render_game(self.to_gui_dict())

    def end_game(self):
        if self.gameState.winner!=None:
            winner_id = self.gameState.winner
            print "GAME OVER: layer",winner_id,"wins"
        else:
            if self.gameState.num_players == 2:
                if self.players[0].score > self.players[1].score:
                    winner_id = 0
                elif self.players[1].score > self.players[0].score:
                    winner_id = 1
                else:
                    winner_id = 2 #tie, show both as winners.
            elif self.players[0]!=None:
                winner_id = 0
            else:
                winner_id = 1
        self.animate_ending(winner_id)

    def board_animation(self, board_id, design, color="green"):
        b = self.boards[board_id]
        d = self.create_shapes(design)
        for coord in d:
            b.landed[coord]=color
                        
    def animate_ending(self,winner_board):
        if winner_board == 2:
            self.board_animation(0,"outline")
            self.board_animation(1,"outline")
        else:
            self.board_animation(winner_board,"outline","yellow")
        self.update_gui()
        sleep(3)

    def create_shapes(self,design): #in progress.....
        shapes = {}
        y = 4
        up_diags = [(1,y+4),(1,y+3),(2,y+3),(2,y+2),(3,y+2),(3,y+1),
                 (8,y+4),(8,y+3),(7,y+3),(7,y+2),(6,y+2),(6,y+1)]
        down_diags = [(x0,10-y0+2*y) for (x0,y0) in up_diags]
        line = [(i,j) for i in [4,5] for j in range(y,y+11)]
        up_arrow = line[:]
        for xy in up_diags:
            up_arrow.append(xy)
        down_arrow = line[:]
        for xy in down_diags:
            down_arrow.append(xy)
        sides = [(i,j) for i in [0,9] for j in range(18)]
        tb = [(i,j) for i in range(10) for j in [0,17]]
        outline = tb + sides
            
        shapes["down_arrow"] = down_arrow
        shapes["up_arrow"] = up_arrow
        shapes["outline"] = outline
        shapes["test"] = [(5,5)]
        
        return shapes[design]

    def to_dict(self):
        d = {}
        for n in range(2):
            board = self.boards[n]
            offset = n*MAXX
            
            #blocks
            for (x,y) in board.landed:
                d[(x+offset,y)] = board.landed[(x,y)]

            if self.players[n]!=None:
                p = self.players[n]

                #shapes
                if p.shape:
                    blocks = p.shape.blocks
                    for b in blocks:
                        if b.y >= 0:
                            d[(b.x+offset*n,b.y)] = b.color
            
                #score  
                score = p.score
                for i in range(10):
                    bit = score%2
                    score = score>>1
                    coord = (MAXX-1-i + offset, MAXY+1)
                    if bit:
                        d[coord] = "yellow"

                #level
                level = self.gameState.level
                d[(level+offset,MAXY)] = LEVEL_COLORS[level]

                #time
                if self.start_time!=None:
                    time_left = (self.start_time + TIME_LIMIT - time()) #seconds left
                    for i in range(TIME_LIMIT/60): #0,1,2,3 (minutes)
                        if time_left/60 >= i:
                            seconds = time_left - 60*i # is in .5-1 secs, etc
                            if not (.5<seconds<1.0 or 1.5<seconds<2.0 or 2.5<seconds<3.0):
                                coord = (MAXX-1-i + offset, MAXY)
                                d[coord] = "white"
                        
        return d

    def to_gui_dict(self):
        d = {}
        if self.start_time!=None:
            d[(2,"level")] = self.gameState.level
            d[(2,"time_left")] = self.start_time + TIME_LIMIT - time()
                
        for n in range(2):
            board = self.boards[n]
            offset = n*MAXX
            
            #blocks
            for (x,y) in board.landed:
                d[(x+offset,y)] = board.landed[(x,y)]

            if self.players[n]!=None:
                p = self.players[n]
                #score
                d[(n,"score")] = p.score

                #shapes
                if p.shape:
                    blocks = p.shape.blocks
                    for b in blocks:
                        if b.y >= 0:
                            d[(b.x+offset*n,b.y)] = b.color
         
        return d
예제 #2
0
class TetrisGame(object):

    #one-time initialization for gui etc
    def __init__(self):
        print "initialize tetris"
        #self.DISPLAY_SIZE = (1920, 1080) #Manually set screensize
        self.gui = PygameGoodRenderer()
        self.input = DdrInput()
        self.num_players = self.input.totaljoy
        self.gui.SetupScreen()
        self.gameState = GameState(self.num_players)
        if self.num_players is 0: # If no joypad connected then 4 players on keyboard.
            self.num_players = 4
            
        while True:
            self.init_game()
            

    #initializes each game
    def init_game(self):
        print "init next game"
        self.boards = [] #reset boards
        self.players = [] #reset players
        for player in range(self.num_players):
            self.boards.append(Board(MAXX,MAXY))
            self.players.append(None)
            self.board_animation(player,"up_arrow")
        self.shapes = GenerateShapes(self.gameState)
        self.input.reset()
        self.gui.load_theme(MAXY, theme = "RussianTheme")
        self.gui.render_game_init(self.to_gui_dict_init())
        self.instruction = True
        self.update_gui()
        self.handle_input() #this calls all other functions, such as add_player, start_game
        

    def add_player(self,num, controller): # num is player number
        print "adding player",num
        if self.players[num]==None:
            self.boards[num].clear()
            other_players = range(self.num_players)
            other_players.pop(num) #all other players
            p = Player(num, self.gameState, self.boards, other_players, self.shapes)
            print "Player" + str(num) + "added"
            self.players[num] = p
            self.players[num].controller = controller
            self.board_animation(num,"down_arrow")
            self.gameState.num_players+=1
            self.gameState.active_players.append(num)
            self.update_gui()
        
    def start_game(self):
        print "start game"
        for n in range(self.num_players):
            self.boards[n].clear()
        self.gameState.state = "playing"
        self.instruction = False
        self.gui.render_game_init(self.to_gui_dict_init())
        self.update_gui()
        self.drop_time = time()
        self.gravity()
        pygame.mixer.music.load('./Themes/RussianTheme/session.mp3')
        pygame.mixer.music.play(-1)
        
        

    def handle_input(self):
        game_on = True
        t = 0
        while game_on:
            t+=1    
            if (self.gameState.state=="ending"):
                self.end_game()
                game_on = False
            
            if self.gameState.state=="playing" and time()-self.drop_time > self.gameState.delay/1000.0:
                self.gravity()
                self.drop_time = time()
                if self.gameState.state != "ending":
                    self.update_gui()
            
            
            player, button = self.input.poll() #If keyboard event UP, DOWN... directions will work, with joypad we get: button.
            if player is None or button is None:
                pass #Do not do anything if None
            elif self.gameState.state=="playing":
                #print "Player " + str(player) + ", Controller " + self.players[player].controller + "Button " + button
                if self.players[player]!=None:
                    if self.players[player].controller == 'Lefthanded':
                        if button is 'arrowLeft':
                            player_move = LEFT
                        elif button is 'arrowRight':
                            player_move = RIGHT
                        elif button is 'arrowUp':
                            player_move = UP
                        elif button is 'arrowDown':
                            player_move = DOWN
                        elif button is 'roundDown':
                            player_move = DROP
                        elif button is 'release':
                            player_move = RELEASE
                        
                    elif self.players[player].controller == 'Righthanded':
                        if button is 'roundLeft':
                            player_move = LEFT
                        elif button is 'roundRight':
                            player_move = RIGHT
                        elif button is 'roundUp':
                            player_move = UP
                        elif button is 'roundDown':
                            player_move = DOWN
                        elif button is 'arrowDown':
                            player_move = DROP
                        elif button is 'release':
                            player_move = RELEASE
                        
                        
                    elif self.players[player].controller == 'Keyboard':
                        player_move = button

                    if player_move == DROP:
                            while self.players[player].handle_move(DOWN):
                                pass
                    else:
                        self.players[player].handle_move(player_move)

                self.update_gui()
                
            elif self.gameState.state == "waiting":
                if button is 'roundUp':
                    self.add_player(player,'Righthanded')
                elif button is 'arrowUp':
                    self.add_player(player,'Lefthanded')
                elif button is UP:
                    self.add_player(player,'Keyboard')
                    
                elif button is 'roundDown' or button is 'arrowDown' or button is DOWN:
                    if self.players[player]!=None:
                        self.start_game()
                self.update_gui()
            
            #sleep(0.01)
            if t%10000==0:
                t=0
                self.update_gui()
                
                
                
    def gravity(self):
        for p in self.players:
            if p:
                p.handle_move(DOWN)
            
    def update_gui(self):
        if self.instruction:
            self.gui.render_game_init(self.to_gui_dict_init())
            self.gui.render_game(self.to_gui_dict())
            self.gui.render_instruction()
        else:
            self.gui.render_game_init(self.to_gui_dict_init())
            self.gui.render_game(self.to_gui_dict())
        self.gui.update()
        
    def end_game(self):
        print "end-game"
        if self.gameState.winner!=None:
            winner_id = self.gameState.winner
            print "GAME OVER: player",winner_id,"wins"
        del self.gameState
        self.gameState = GameState(self.num_players)
        self.animate_ending(winner_id)
        pygame.mixer.music.stop()
        
        # Up date number of players (loypads)
        self.num_players = self.input.totaljoy
        if self.num_players is 0: # If no joypad connected then 4 players on keyboard.
            self.num_players = 4
        

    def board_animation(self, board_id, design, color="green"):
        b = self.boards[board_id]
        d = self.create_shapes(design)
        for coord in d:
            #sleep(0.005)
            b.landed[coord]=color
            #self.update_gui()
                        
    def animate_ending(self,winner_board):
        self.board_animation(winner_board,"outline","yellow")
        self.update_gui()
        sleep(2)
        
        #escape = True
        #while escape:
        #    ev = self.input.poll()
        #    if ev:
        #        player,direction = ev
        #        #print "Player",player,direction            
        #        if direction == UP:
        #            escape = False
        #        else:
        #            escape = True
        #    else:
        #        sleep(0.2)
	sleep(2)
	
    def create_shapes(self,design): #in progress.....
        shapes = {}
        y = 4
        up_diags = [(1,y+4),(1,y+3),(2,y+3),(2,y+2),(3,y+2),(3,y+1),
                 (8,y+4),(8,y+3),(7,y+3),(7,y+2),(6,y+2),(6,y+1)]
        down_diags = [(x0,10-y0+2*y) for (x0,y0) in up_diags]
        line = [(i,j) for i in [4,5] for j in range(y,y+11)]
        up_arrow = line[:]
        for xy in up_diags:
            up_arrow.append(xy)
        down_arrow = line[:]
        for xy in down_diags:
            down_arrow.append(xy)
        sides = [(i,j) for i in [0,9] for j in range(MAXY)]
        tb = [(i,j) for i in range(10) for j in [0,MAXY-1]]
        outline = tb + sides
            
        shapes["down_arrow"] = down_arrow
        shapes["up_arrow"] = up_arrow
        shapes["outline"] = outline
        shapes["test"] = [(5,5)]
        
        return shapes[design]

    def to_gui_dict_init(self):
        d = {}
        d["max_y"] = MAXY
        d["max_x"] = MAXX
        d["nr_players"] = self.num_players
        d["level"] = self.gameState.level
        
        return d
        


    def to_gui_dict(self):
        d = {}                
        for n in range(self.num_players):
            #blocks
            d["board_landed_player" + str(n)] = self.boards[n].landed

            if self.players[n]!=None:
                p = self.players[n]
                #score
                d["score_player" + str(n)] = p.score
                d["lines_player" + str(n)] = p.lines
                
                #shapes
                if p.shape:
                    d["blocks_player" + str(n)] = p.shape.blocks
                            
                #next shape
                if p.nextshape:
                    d["nextshape_player" + str(n)] = p.nextshape.blocks
                   
        return d
class TetrisGame(object):

    #one-time initialization for gui etc
    def __init__(self):
        print "initialize tetris"
        self.gui = [PygameGoodRenderer(), LedRenderer()]
        self.input = DdrInput()
        while True:
            self.init_game()

    #initializes each game
    def init_game(self):
        print "init next game"
        self.boards = [Board(MAXX, MAXY), Board(MAXX, MAXY)]
        self.players = [None, None]
        self.gameState = GameState()
        self.board_animation(0, "up_arrow")
        self.board_animation(1, "up_arrow")
        self.start_time = None
        self.input.reset()
        self.update_gui()
        self.handle_input(
        )  #this calls all other functions, such as add_player, start_game

    def add_player(self, num):  # 0=left, 1=right
        print "adding player", num
        if self.players[num] == None:
            self.boards[num].clear()
            p = Player(num, self.gameState, self.boards[num],
                       self.boards[(num + 1) % 2])
            self.players[num] = p
            self.board_animation(num, "down_arrow")
            self.gameState.num_players += 1
            self.update_gui()

    def start_game(self):
        print "start game"
        self.boards[0].clear()
        self.boards[1].clear()
        self.gameState.state = "playing"
        self.update_gui()
        self.start_time = time()
        self.drop_time = time()
        self.gravity()

    def handle_input(self):

        game_on = True
        t = 0
        while game_on:
            t += 1

            if (self.gameState.state
                    == "ending") or (self.gameState.state == "playing" and
                                     time() - self.start_time > TIME_LIMIT):
                self.end_game()
                game_on = False
                return
            if self.gameState.state == "playing" and time(
            ) - self.drop_time > self.gameState.delay / 1000.0:
                self.gravity()
                self.drop_time = time()
                if self.gameState.state != "ending":
                    self.update_gui()

            ev = self.input.poll()
            if ev:
                player, direction = ev
                #print "Player",player,direction
                if direction == DIE:  #Exit instruction
                    game_on = False
                    pygame.quit()
                    sys.exit()
                if self.gameState.state == "playing":
                    if self.players[player] != None:
                        #DROP is only for debugging purposes for now, to make the game end.
                        if direction == DROP:
                            while self.players[player].handle_move(DOWN):
                                pass
                        else:
                            self.players[player].handle_move(direction)
                elif self.gameState.state == "waiting":
                    if direction == UP:
                        self.add_player(player)
                    elif direction == DOWN:
                        if self.players[player] != None:
                            self.start_game()

                self.update_gui()

            elif t % 10000 == 0:
                t = 0
                self.update_gui()

    def gravity(self):
        for p in self.players:
            if p:
                p.handle_move(DOWN)

    def update_gui(self):
        d = self.to_dict()
        [gui.render_game(d) for gui in self.gui]
        #self.gui[0].render_game(self.to_gui_dict())

    def end_game(self):
        if self.gameState.winner != None:
            winner_id = self.gameState.winner
            print "GAME OVER: layer", winner_id, "wins"
        else:
            if self.gameState.num_players == 2:
                if self.players[0].score > self.players[1].score:
                    winner_id = 0
                elif self.players[1].score > self.players[0].score:
                    winner_id = 1
                else:
                    winner_id = 2  #tie, show both as winners.
            elif self.players[0] != None:
                winner_id = 0
            else:
                winner_id = 1
        self.animate_ending(winner_id)

    def board_animation(self, board_id, design, color="green"):
        b = self.boards[board_id]
        d = self.create_shapes(design)
        for coord in d:
            b.landed[coord] = color

    def animate_ending(self, winner_board):
        if winner_board == 2:
            self.board_animation(0, "outline")
            self.board_animation(1, "outline")
        else:
            self.board_animation(winner_board, "outline", "yellow")
        self.update_gui()
        sleep(3)

    def create_shapes(self, design):  #in progress.....
        shapes = {}
        y = 4
        up_diags = [(1, y + 4), (1, y + 3), (2, y + 3), (2, y + 2), (3, y + 2),
                    (3, y + 1), (8, y + 4), (8, y + 3), (7, y + 3), (7, y + 2),
                    (6, y + 2), (6, y + 1)]
        down_diags = [(x0, 10 - y0 + 2 * y) for (x0, y0) in up_diags]
        line = [(i, j) for i in [4, 5] for j in range(y, y + 11)]
        up_arrow = line[:]
        for xy in up_diags:
            up_arrow.append(xy)
        down_arrow = line[:]
        for xy in down_diags:
            down_arrow.append(xy)
        sides = [(i, j) for i in [0, 9] for j in range(18)]
        tb = [(i, j) for i in range(10) for j in [0, 17]]
        outline = tb + sides

        shapes["down_arrow"] = down_arrow
        shapes["up_arrow"] = up_arrow
        shapes["outline"] = outline
        shapes["test"] = [(5, 5)]

        return shapes[design]

    def to_dict(self):
        d = {}
        for n in range(2):
            board = self.boards[n]
            offset = n * MAXX

            #blocks
            for (x, y) in board.landed:
                d[(x + offset, y)] = board.landed[(x, y)]

            if self.players[n] != None:
                p = self.players[n]

                #shapes
                if p.shape:
                    blocks = p.shape.blocks
                    for b in blocks:
                        if b.y >= 0:
                            d[(b.x + offset * n, b.y)] = b.color

                #score
                score = p.score
                for i in range(10):
                    bit = score % 2
                    score = score >> 1
                    coord = (MAXX - 1 - i + offset, MAXY + 1)
                    if bit:
                        d[coord] = "yellow"

                #level
                level = self.gameState.level
                d[(level + offset, MAXY)] = LEVEL_COLORS[level]

                #time
                if self.start_time != None:
                    time_left = (self.start_time + TIME_LIMIT - time()
                                 )  #seconds left
                    for i in range(TIME_LIMIT / 60):  #0,1,2,3 (minutes)
                        if time_left / 60 >= i:
                            seconds = time_left - 60 * i  # is in .5-1 secs, etc
                            if not (.5 < seconds < 1.0 or 1.5 < seconds < 2.0
                                    or 2.5 < seconds < 3.0):
                                coord = (MAXX - 1 - i + offset, MAXY)
                                d[coord] = "white"

        return d

    def to_gui_dict(self):
        d = {}
        if self.start_time != None:
            d[(2, "level")] = self.gameState.level
            d[(2, "time_left")] = self.start_time + TIME_LIMIT - time()

        for n in range(2):
            board = self.boards[n]
            offset = n * MAXX

            #blocks
            for (x, y) in board.landed:
                d[(x + offset, y)] = board.landed[(x, y)]

            if self.players[n] != None:
                p = self.players[n]
                #score
                d[(n, "score")] = p.score

                #shapes
                if p.shape:
                    blocks = p.shape.blocks
                    for b in blocks:
                        if b.y >= 0:
                            d[(b.x + offset * n, b.y)] = b.color

        return d