def start_game(self):
        self.id = 0

        # Define work of timer: choose random a number of head and show them
        def work():
            self.num_head_kill_in_section = 0
            num_head = 7 #random.randint(1, 5)
            positions = range(8)
            random.shuffle(positions)

            self.interval_section = random.random() * 2 + 0.5

            for i in range(num_head):
                self.interval_head = random.random() * 0.1 + 0.2

                self.stick_time = random.random() * 0.05 + 0.05

                self.appear_delay = random.random() * 1.5
                if self.appear_delay < 6 * self.stick_time + 0.01:
                    self.appear_delay = 6 * self.stick_time + 0.01

                # Position of top left corner of bitmap
                original_head_pos = HolePosition.POS[positions[i]]
                head = Head(str(self.id), self, self.stick_time)

                # Actually position
                pos = (original_head_pos[0] - 30, original_head_pos[1] - 40)

                head.show(pos, self.appear_delay)

                self.heads.append(head)
                self.id += 1
                time.sleep(self.interval_head)
        # Finish work() function

        self.head_timer = Timer(self.interval_section, work)

        self.head_timer.start()

        self.timer_counter = TimerCounter(self, 60, 40, (570, 490), (240, 5, 12))
        self.register(self.timer_counter, 'time_up')
        self.timer_counter.run()

        font = pygame.font.Font("resources/font.ttf", 40)
        drawable_object = Drawable(font.render('Score: ', True, (255, 0, 0)), (15, 490), DRAWABLE_INDEX.TIMER_COUNTER)
        self.register_waiter('score_text', drawable_object)

        drawable_object = Drawable(font.render('0', True, (255, 0, 0)), (150, 490), DRAWABLE_INDEX.TIMER_COUNTER)
        self.register_waiter('score', drawable_object)
class MainController(Observer, Waiter):
    """Control common stage of game, include:
    - Init game
    - Load background
    - Load model
    This class has role:
    - Waiter: update screen
    - Observer: listen and resolve special event, such as: QUIT
    """

    def __init__(self, event_controller, env):

        # Init pygame
        pygame.init()
        pygame.mixer.init()

        # Save event_controller to use later
        self.event_controller = event_controller
        self.env = env

        # Set some value for head
        self.number_of_enemy = NUM_SPRITES.NUMBER_OF_ENEMY
        self.time_to_create_new = DURATION.TIME_CREATE_NEW
        self.max_of_current_enemy = NUM_SPRITES.MAX_OF_CURRENT_ENEMY
        self.totalCreatedEnemy = 0

        # Constructor of base class
        Observer.__init__(self)
        # Register to receive some special events
        self.register(event_controller, 'special')

        Waiter.__init__(self)

        # Attribute declare
        self.quit_game = False
        self.player = None

        self.heads = []
        self.head_timer = None
        self.interval_section = 3
        self.appear_delay = 3
        self.stick_time = 0.12
        self.is_first_blood = True

        self.sound_prepare4battle = Factory.get_sound('prepare4battle')
        if self.sound_prepare4battle is None:
            raise NotImplementedError
        self.sound_prepare4battle_playing = False
        self.sound_first_blood = Factory.get_sound('first_blood')
        if self.sound_first_blood is None:
            raise NotImplementedError
        self.sound_double_kill = Factory.get_sound('double_kill')
        if self.sound_double_kill is None:
            raise NotImplementedError
        self.sound_triple_kill = Factory.get_sound('triple_kill')
        if self.sound_triple_kill is None:
            raise NotImplementedError
        self.sound_ultra_kill = Factory.get_sound('ultra_kill')
        if self.sound_ultra_kill is None:
            raise NotImplementedError
        self.sound_rampage_kill = Factory.get_sound('rampage')
        if self.sound_rampage_kill is None:
            raise NotImplementedError

        self.screen = pygame.display.set_mode(self.env.screen_size)
        pygame.mouse.set_visible(False)    # Hide default mouse cursor

        self.timer_counter = None
        self.stage = None
        self.id = 0
        self.finish = False
        self.num_head_kill_in_section = 0

    def update(self, type_key, event):
        """
        Override function of base class: Observer
        This function is called when expected event is happened
        :param event: event is happened
        :return: None
        """
        if type_key == 'special':
            if event.type == pygame.QUIT:
                self.close()
                self.quit_game = True
        elif type_key == 'player_hammer':
            rect_bound_hammer = event
            head = self.__check_collision(rect_bound_hammer)

            if head:
                self.player.increase_score()
                head.die()
                if self.is_first_blood:
                    self.sound_first_blood.play()
                    self.is_first_blood = False

                self.num_head_kill_in_section += 1
                print self.num_head_kill_in_section
                if self.num_head_kill_in_section == 2:
                    self.sound_double_kill.play()
                if self.num_head_kill_in_section == 3:
                    self.sound_triple_kill.play()
                if self.num_head_kill_in_section == 4:
                    self.sound_ultra_kill.play()
                if self.num_head_kill_in_section == 5:
                    self.sound_rampage_kill.play()
            else:
                self.player.decrease_score()
        elif type_key == 'time_up':
            self.finish = True
            self.finish_game()

    def init_game(self):
        """
        Init logically game
        :return: None
        """
        start_time = time.time()
        self.screen.fill((255, 255, 255))
        background = Factory.get_background()
        if background is not None:
            drawable_object = Drawable(background, (0, 20), DRAWABLE_INDEX.BACKGROUND)
            key = str(drawable_object.index) + CUSTOMER_KEY.BACKGROUND      # Insert index as prefix keyword to sort
            self.register_waiter(key, drawable_object)
        else:
            raise 'Can not load background image'

        self.player = Player(self.event_controller, self)
        self.register(self.player, 'player_hammer')

    def start_game(self):
        self.id = 0

        # Define work of timer: choose random a number of head and show them
        def work():
            self.num_head_kill_in_section = 0
            num_head = 7 #random.randint(1, 5)
            positions = range(8)
            random.shuffle(positions)

            self.interval_section = random.random() * 2 + 0.5

            for i in range(num_head):
                self.interval_head = random.random() * 0.1 + 0.2

                self.stick_time = random.random() * 0.05 + 0.05

                self.appear_delay = random.random() * 1.5
                if self.appear_delay < 6 * self.stick_time + 0.01:
                    self.appear_delay = 6 * self.stick_time + 0.01

                # Position of top left corner of bitmap
                original_head_pos = HolePosition.POS[positions[i]]
                head = Head(str(self.id), self, self.stick_time)

                # Actually position
                pos = (original_head_pos[0] - 30, original_head_pos[1] - 40)

                head.show(pos, self.appear_delay)

                self.heads.append(head)
                self.id += 1
                time.sleep(self.interval_head)
        # Finish work() function

        self.head_timer = Timer(self.interval_section, work)

        self.head_timer.start()

        self.timer_counter = TimerCounter(self, 60, 40, (570, 490), (240, 5, 12))
        self.register(self.timer_counter, 'time_up')
        self.timer_counter.run()

        font = pygame.font.Font("resources/font.ttf", 40)
        drawable_object = Drawable(font.render('Score: ', True, (255, 0, 0)), (15, 490), DRAWABLE_INDEX.TIMER_COUNTER)
        self.register_waiter('score_text', drawable_object)

        drawable_object = Drawable(font.render('0', True, (255, 0, 0)), (150, 490), DRAWABLE_INDEX.TIMER_COUNTER)
        self.register_waiter('score', drawable_object)

    def run(self):
        """
        Implement from Waiter. This function clear and then draw whole screen.
        :return: None
        """
        if not self.finish:
            self.screen.fill((0, 0, 0))
            for key in sorted(self.objects.keys()):     # TODO: Need to improve
                if key in self.objects.keys():
                    try:
                        self.screen.blit(self.objects[key].bitmap, self.objects[key].pos)
                    except KeyError:
                        continue

    def __check_collision(self, rect_bound_hammer):
        """
        Check collision between player and head
        :return:
        """
        heads = []
        for head in self.heads:
            if head.alive:
                heads.append(head)
                if rect_bound_hammer.colliderect(head.get_rect_bound()):
                    return head
            # if head.showing:
            #     heads.append(head)
            # self.heads = heads
        return None

    def close(self):
        self.player.close()

        if self.head_timer is not None:
            self.head_timer.stop()
            self.head_timer.close()

        for head in self.heads:
            head.close()
        if self.head_timer is not None:
            self.head_timer.close()
        if self.timer_counter is not None:
            self.timer_counter.close()

    def intro(self, clock):
        logo = pygame.image.load('resources/Logo.png')
        i = 0
        while i < 58:
            self.screen.fill((0, 0, 0))
            img = pygame.image.load('resources/intro/tmp-' + str(i) + '.gif')
            i += 1
            self.screen.blit(img, (30, 150))
            self.screen.blit(logo, (i * 2, 30))
            self.screen.blit(logo, (480 - i * 2, 30))
            Font = pygame.font.Font("resources/HorrorFont.ttf", 64)
            self.screen.blit(Font.render('PUNCH ZOMBIE ', True, (255, 0, 0)), (100, 100))
            pygame.display.flip()
            clock.tick(10)

    def prepare(self):
        self.stage = 'prepare'

        def work():
            if not self.sound_prepare4battle_playing:
                self.sound_prepare4battle.play()
                self.sound_prepare4battle_playing = True
            else:
                time.sleep(4)
                self.prepare_timer.stop()
                self.start_game()

        self.prepare_timer = Timer(0.001, work)
        self.prepare_timer.start()

    def finish_game(self):
        self.close()
        self.screen.fill((0, 0, 0))
        end_background = pygame.image.load('resources/endgame.jpg')
        self.screen.blit(end_background, (20, 10))
        font = pygame.font.Font("resources/HorrorFont.ttf", 64)
        self.screen.blit(font.render('Your score:', True, (255, 0, 0)), (130, 100))
        self.screen.blit(font.render(str(self.player.score), True, (255, 0, 0)), (300, 200))
        pygame.display.flip()
        time.sleep(10)

        self.quit_game = True