Example #1
0
class Game:
    """
    The actual game and rendering related functions
    """

    _refresh_time = 1 / FRAME_RATE

    # DECLARING EVERYTHING
    def __init__(self):
        coloroma_init(autoreset=False)
        self.__score = 0
        self.__last_level_score = 0
        self.__ticks = 0
        self.__level_ticks = 0
        self.__level = 1
        self.__lives_used = 0
        self.__paddle = Paddle()
        self.__bricks_broken = 0
        self.__balls = [Ball(paddle=self.__paddle)]
        self.__cnt_active_balls = 0
        self.__cnt_active_bricks = 100
        self.__game_status = GAME_END
        self.__powerups = []
        self.__kb = KBHit()
        self.__explode_ids = [x for x in range(8, 14)]
        self.__explode_nbrs_ids = [7, 14, 28, 29, 30, 31, 32, 33]
        self.__brick_structure_y_fall = 0
        self.__fall_bricks = 0
        self.__bullets = []
        self.__ufo = Ufo()
        self.__ufo_bombs = []
        self.__ufo_bricks = []
        self.__map_position_to_bricks = []

        clear_terminal_screen()
        self._draw_bricks()
        self._loop()

    # DRAW THE OBJECT IN GIVEN RANGE
    def _draw_obj(self, coord, obj):
        y1 = 0
        for y in range(coord[1], coord[1] + coord[3]):
            x1 = 0
            for x in range(coord[0], coord[0] + coord[2]):
                # (x, y) wrt frame (x1, y1) wrt obj
                if 0 <= x < FRAME_WIDTH and 0 <= y < FRAME_HEIGHT:
                    self.__frame[y][x] = obj[y1][x1]
                x1 += 1
            y1 += 1

    # TOP INFO BAR
    def _top_info_print(self):
        s = f"SCORE:{self.__score}       "[:13]
        s += f"LIVES REMAINING:{LIVES - self.__lives_used}       "[:24]
        s += f"TIME: {self.__level_ticks//10}       "[:14]
        s += f"LEVEL: {self.__level}        "
        if self.__paddle.check_have_bullet_powerup():
            # (self.__ticks - self.__paddle.get_powerup_start_time())//10 >= POWERUP_LIFE
            # (X - S) // 10 = POWERUP_LIFE
            # X = S + 10*POWERUP_LIFE
            # ANSWER = X - NOW.
            x = self.__paddle.get_powerup_start_time() + 10 * POWERUP_LIFE
            s += f"POWERUP TIME LEFT: {x - self.__ticks}        "

        if self.__level == UFO_LEVEL:
            s += f"UFO HEALTH: {self.__ufo.get_health()}        "
            s += f"Press q to quit."
        else:
            s += f"Press q to quit."
        self.__frame[1][2:2 + len(s)] = [
            Style.BRIGHT + Fore.WHITE + Back.LIGHTBLACK_EX + x for x in s
        ]

    # DRAW THE BRICK STRUCTURE
    def _draw_bricks(self):
        self.__bricks = []
        y = BRICK_STRUCTURE_Y

        if self.__level == UFO_LEVEL:
            y += 7

        dummy_row = [
            "X" for i in range(len(BRICK_STRUCTURE[self.__level - 1][0]) + 2)
        ]

        self.__map_position_to_bricks = [dummy_row]

        for i, row in enumerate(BRICK_STRUCTURE[self.__level - 1]):
            x = BRICK_STRUCTURE_X
            row_bricks = ["X"]
            for j, brick_type in enumerate(row):
                if brick_type == " ":
                    row_bricks.append("X")
                    x += BRICK_WIDTH
                    continue
                if int(brick_type) == WEAK_BRICK_ID:
                    self.__bricks.append(WeakBrick(x, y, i + 1, j + 1))
                elif int(brick_type) == NORMAL_BRICK_ID:
                    self.__bricks.append(NormalBrick(x, y, i + 1, j + 1))
                elif int(brick_type) == STRONG_BRICK_ID:
                    self.__bricks.append(StrongBrick(x, y, i + 1, j + 1))
                elif int(brick_type) == UNBREAKABLE_BRICK_ID:
                    self.__bricks.append(UnbreakableBrick(x, y, i + 1, j + 1))
                elif int(brick_type) == EXPLODING_BRICK_ID:
                    self.__bricks.append(ExplodingBrick(x, y, i + 1, j + 1))
                elif int(brick_type) == RAINBOW_BRICK_ID:
                    self.__bricks.append(RainbowBrick(x, y, i + 1, j + 1))

                row_bricks.append(self.__bricks[-1])
                x += BRICK_WIDTH

            row_bricks.append("X")
            self.__map_position_to_bricks.append(row_bricks)
            y += BRICK_HEIGHT

        self.__map_position_to_bricks.append(dummy_row)
        # print(len(self.__map_position_to_bricks), len(self.__map_position_to_bricks[0]), len(B))
        # input()

    # HOLD SCREEN. BETWEEN LIFE LOSTS
    def _draw_hold_screen(self, message=""):
        self.__frame = np.array([[
            Style.BRIGHT + Fore.WHITE + Back.LIGHTBLACK_EX + " "
            for _ in range(FRAME_WIDTH)
        ] for _ in range(FRAME_HEIGHT)])
        self._top_info_print()
        s = message + " Press ENTER to continue."
        self.__frame[FRAME_HEIGHT // 2][50:50 + len(s)] = [x for x in s]
        sra = str(Style.RESET_ALL)
        # get the grid string
        grid_str = "\n".join(
            [sra + " " * 4 + "".join(row) + sra for row in self.__frame])
        # displaying the grid
        os.write(1, str.encode(grid_str))

    # DRAW ONE FRAME
    def _draw(self):
        # drawing the grid
        self.__frame = np.array([[
            Style.BRIGHT + Fore.WHITE + Back.LIGHTBLACK_EX + " "
            for _ in range(FRAME_WIDTH)
        ] for _ in range(FRAME_HEIGHT)])
        self.__bricks_broken = 0

        # TOP INFO BAR
        self._top_info_print()

        # PADDLE
        self._draw_obj(self.__paddle.get_box(), self.__paddle.get_obj())

        # UFO
        if self.__level == UFO_LEVEL:
            if self.__ufo.check_active():
                self._draw_obj(self.__ufo.get_box(), self.__ufo.get_obj())

        # UFO BRICKS
        for ufo_brick in self.__ufo_bricks:
            if not ufo_brick.check_active():
                continue
            self._draw_obj(ufo_brick.get_box(), ufo_brick.get_obj())

        # BRICKS
        for brick in self.__bricks:
            if brick.check_active():
                self._draw_obj(brick.get_box(), brick.get_obj())
            else:
                self.__bricks_broken += 1

        #BULLETS
        for bullet in self.__bullets:
            if bullet.check_active():
                self._draw_obj(bullet.get_box(), bullet.get_obj())

        #BOMBS
        for bomb in self.__ufo_bombs:
            if bomb.check_active():
                self._draw_obj(bomb.get_box(), bomb.get_obj())

        # BALLS
        for ball in self.__balls:
            if ball.check_active():
                self._draw_obj(ball.get_box(), ball.get_obj())

        # POWERUPS
        for powerup in self.__powerups:
            if powerup.check_active():
                self._draw_obj(powerup.get_box(), powerup.get_obj())

        sra = str(Style.RESET_ALL)
        grid_str = "\n".join(
            [sra + " " * 4 + "".join(row) + sra for row in self.__frame])
        os.write(1, str.encode(grid_str))

    # TAKE INPUT FROM KBHIT
    def _get_input(self):
        c = ""
        if self.__kb.kbhit():
            c = self.__kb.getch()
        self.__kb.flush()
        return c

    # HANDLE THE INPUT TAKEN
    def _handle_input(self, key):
        key = key.lower()
        if key == 'q':
            self.Quit()
        if key in "ad":
            if self.__level == UFO_LEVEL:
                self.__paddle.handle_key_press(key, self.__ufo)
                for idx, brick in enumerate(self.__ufo_bricks):
                    brick.set_x(self.__ufo.get_x() + idx * BRICK_WIDTH)
            else:
                self.__paddle.handle_key_press(key)
        if key in " ad":
            for ball in self.__balls:
                ball.handle_key_press(self.__paddle, key)
        if key == 'l':
            self.change_level()

    # DIVIDE THE BALL INTO TWO
    def divide_ball(self, ball):
        new_ball = Ball()
        x, y = ball.get_position()
        vx, vy = ball.get_velocity()
        if vx != 0:
            new_ball.set_velocity(vx * -1, vy)
        else:
            new_ball.set_velocity(-1, vy)
        new_ball.set_position(x, y)
        new_ball.set_state(BALL_RELEASED)
        return new_ball

    # DIFFRENT COLLISIONS
    def _ball_and_wall(self):
        for ball in self.__balls:
            if ball.check_active():
                ball.check_wall_collission()

    def _ball_and_paddle(self):
        for ball in self.__balls:
            if ball.check_active():
                if ball.check_paddle_collission(
                        self.__paddle) and self.__fall_bricks:
                    self.__brick_structure_y_fall += 1
                    if self.__brick_structure_y_fall + BRICK_STRUCTURE_Y + len(
                            BRICK_STRUCTURE[self.__level -
                                            1]) * BRICK_HEIGHT == PADDLE_Y:
                        self.Quit()

    def _bomb_and_paddle(self):
        for bomb in self.__ufo_bombs:
            if bomb.check_active():
                if bomb.check_paddle_collission(self.__paddle):
                    self.__cnt_active_balls = 0

    def _ball_and_ufo(self):
        for ball in self.__balls:
            if ball.check_active():
                if ball.check_ufo_collission(self.__ufo):
                    self.Quit()

    def _powerup_and_paddle(self):
        for powerup in self.__powerups:
            if not powerup.check_active():
                continue
            if check_intersection(powerup, self.__paddle):
                if powerup.get_type() == POWERUP_EXPAND_PADDLE:
                    self.__paddle.change_width(INC_PADDLE_WIDTH)

                elif powerup.get_type() == POWERUP_SHRINK_PADDLE:
                    self.__paddle.change_width(-1 * SHRINK_PADDLE_WIDTH)

                elif powerup.get_type() == POWERUP_FAST_BALL:
                    for ball in self.__balls:
                        ball.inc_speed(2)

                elif powerup.get_type() == POWERUP_BALL_MULITIPLIER:
                    new_balls = []
                    for ball in self.__balls:
                        if ball.check_active():
                            new_balls.append(self.divide_ball(ball))
                    for new_ball in new_balls:
                        self.__balls.append(new_ball)

                elif powerup.get_type() == POWERUP_THRU_BALL:
                    for ball in self.__balls:
                        ball.set_type(THRU_BALL)
                elif powerup.get_type() == POWERUP_GRAB_BALL:
                    for ball in self.__balls:
                        ball.set_grabbable()
                elif powerup.get_type() == POWERUP_SHOOTING_BULLET:
                    self.__paddle.set_have_bullet_powerup(1)
                    self.__paddle.set_powerup_start_time(self.__ticks)
                elif powerup.get_type() == POWERUP_FIREBALL:
                    for ball in self.__balls:
                        ball.set_fire()
                else:
                    continue
                powerup.deactivate()

    def _update(self):

        # ball moved
        self.__cnt_active_balls = 0
        for ball in self.__balls:
            if ball.check_active():
                ball.update()
                self.__cnt_active_balls += 1

        # Powerup moved
        powerup_remove = []
        for id, powerup in enumerate(self.__powerups):
            if powerup.check_active():
                powerup.update()
            else:
                powerup_remove.append(id)
        for id in sorted(powerup_remove, reverse=True):
            del self.__powerups[id]

        # Bullet moved
        bullet_remove = []
        for id, bullet in enumerate(self.__bullets):
            if bullet.check_active():
                bullet.update()
            else:
                bullet_remove.append(id)
        for id in sorted(bullet_remove, reverse=True):
            del self.__bullets[id]

        # Bomb moved
        bomb_remove = []
        for id, bomb in enumerate(self.__ufo_bombs):
            if bomb.check_active():
                bomb.update()
            else:
                bomb_remove.append(id)
        for id in sorted(bomb_remove, reverse=True):
            del self.__ufo_bombs[id]

        # Bullet powerup done
        if self.__paddle.check_have_bullet_powerup(
        ) and (self.__ticks -
               self.__paddle.get_powerup_start_time()) // 10 >= POWERUP_LIFE:
            self.__paddle.set_have_bullet_powerup(0)

        # Generate Bullet
        if self.__paddle.check_have_bullet_powerup() and self.__ticks % 8 == 0:
            x, y = self.__paddle.get_position()
            self.__bullets.append(Bullet(x + PADDLE_WIDTH // 2, y, -1))

        # Generate Bomb
        if self.__level == UFO_LEVEL and self.__ufo.can_drop_bomb():
            u_x, u_y, u_width, u_height = self.__ufo.get_box()
            self.__ufo_bombs.append(Bomb(u_x + u_width // 2, u_y + u_height))

        # ball and wall collissins
        self._ball_and_wall()
        # ball and paddle collissions
        self._ball_and_paddle()
        # bomb and paddle
        if self.__level == UFO_LEVEL:
            self._bomb_and_paddle()
        # powerup and paddle collissions
        self._powerup_and_paddle()

        # ufo bricks and ball
        if self.__level == UFO_LEVEL:
            for brick in self.__ufo_bricks:
                if not brick.check_active():
                    continue
                for ball in self.__balls:
                    if not ball.check_active():
                        continue
                    is_destroyed = brick.handle_collission(ball)

        # ufo and ball
        if self.__level == UFO_LEVEL:
            got_critical = True
            if self.__ufo.check_critical():
                got_critical = False

            self._ball_and_ufo()

            if not self.__ufo.check_critical():
                got_critical = False

            if got_critical:
                u_x, u_y, u_width, u_height = self.__ufo.get_box()
                for i in range(UFO_WIDTH // BRICK_WIDTH):
                    b_x = u_x + i * BRICK_WIDTH
                    b_y = u_y + u_height
                    self.__ufo_bricks.append(WeakBrick(b_x, b_y))

        for powerup in self.__powerups:
            if powerup.check_active():
                powerup.check_wall_collission()

        for brick in self.__bricks:
            if brick.check_active():
                for bullet in self.__bullets:
                    if bullet.check_active():
                        vx, vy = bullet.get_velocity()
                        is_destroyed = brick.handle_collission_bullet(bullet)
                        if not is_destroyed:
                            continue
                        if is_destroyed and brick.id == EXPLODING_BRICK_ID:
                            os.system('aplay -q ./sounds/explosions.wav&')
                            for i in self.__explode_ids:
                                if self.__bricks[i].check_active():
                                    self.__bricks[i].destroy()
                            for i in self.__explode_nbrs_ids:
                                if self.__bricks[i].check_active():
                                    self.__bricks[i].destroy()
                        if is_destroyed and random.random(
                        ) > POWERUP_PROBABILITY:
                            # generate power_up
                            (x, y, _, _) = brick.get_box()
                            powerup_type = random.randint(0, 7)
                            self.__powerups.append(
                                PowerUp(x, y, vx, vy, powerup_type))

        self.__cnt_active_bricks = 0
        for brick in self.__bricks:
            if brick.check_active():
                if brick.get_type() != UNBREAKABLE_BRICK_ID:
                    self.__cnt_active_bricks += 1
                for ball in self.__balls:
                    if ball.check_active():
                        vx, vy = ball.get_velocity()
                        is_destroyed = brick.handle_collission(
                            ball, self.__map_position_to_bricks)
                        if is_destroyed and brick.id == EXPLODING_BRICK_ID:
                            for i in self.__explode_ids:
                                if self.__bricks[i].check_active():
                                    self.__bricks[i].destroy()
                            for i in self.__explode_nbrs_ids:
                                if self.__bricks[i].check_active():
                                    self.__bricks[i].destroy()
                        if is_destroyed and random.random(
                        ) > POWERUP_PROBABILITY:
                            # generate power_up
                            (x, y, _, _) = brick.get_box()
                            powerup_type = random.randint(0, 7)
                            # powerup_type = POWERUP_FIREBALL
                            self.__powerups.append(
                                PowerUp(x, y, vx, vy, powerup_type))

        for brick in self.__bricks:
            if brick.check_active():
                brick.set_y_fall(self.__brick_structure_y_fall)

        if (self.__level_ticks // 10) == LEVEL_TIME[self.__level - 1]:
            self.__fall_bricks = 1

    def _get_score(self):
        self.__score = max(
            0, 100 * self.__bricks_broken - (self.__ticks // 100) * 10)

        if self.__level == UFO_LEVEL:
            self.__score += (max(0, 1000 *
                                 (UFO_HEALTH - self.__ufo.get_health())))

        return self.__score + self.__last_level_score

    def refresh(self):
        self.__powerups = []
        self.__paddle.set_default()
        self.__balls = [Ball(paddle=self.__paddle)]
        self.__bullets = []

    def change_level(self):
        if self.__level == MAX_LEVEL:
            self.Quit()

        self.__level += 1

        while True:
            print("\033[0;0H")
            self._draw_hold_screen(f"Moving to level {self.__level}.")
            last_key_pressed = self._get_input().lower()
            if last_key_pressed == "\n":
                print("\033[0;0H")
                break
            elif last_key_pressed == "q":
                self.Quit()
                break

        if self.__level == UFO_LEVEL:
            os.system('aplay -q ./sounds/ufo.wav& 2>/dev/null')

        self._draw_bricks()
        self.__brick_structure_y_fall = 0
        self.__fall_bricks = 0
        self.__level_ticks = 0
        self.__last_level_score = self.__score
        self.refresh()

    # loop over frames
    def _loop(self):
        self.__game_status = GAME_START
        clear_terminal_screen()

        while self.__game_status == GAME_START:

            # 1. Clear Screen
            # 2. update positions and handle collisions
            # 3. update info
            # 4. draw
            # 5. handle input

            # clear screen and reposition cursor.
            print("\033[0;0H")

            self._update()

            if self.__cnt_active_bricks == 0 and self.__level != UFO_LEVEL:
                self.change_level()

            if self.__cnt_active_balls == 0:
                self.refresh()
                self.__lives_used += 1
                self.__game_status = GAME_HOLD
                while self.__game_status == GAME_HOLD:
                    print("\033[0;0H")
                    self._draw_hold_screen("Life lost. Game Paused.")
                    last_key_pressed = self._get_input().lower()
                    if last_key_pressed == "\n":
                        print("\033[0;0H")
                        self.__game_status = GAME_START
                    elif last_key_pressed == "q":
                        self.Quit()
                        break

            if LIVES - self.__lives_used == 0:
                self.Quit()
                break

            self._draw()
            last = time.time()

            last_key_pressed = self._get_input()
            self._handle_input(last_key_pressed)

            self.__score = self._get_score()
            self.__ticks += 1
            self.__level_ticks += 1

            while time.time() - last < self._refresh_time:
                pass

    def Quit(self):
        clear_terminal_screen()
        self.__game_status = GAME_END
        s = " " * 5
        s = "GAME OVER!\n"
        s += f"SCORE:{self.__score}\n"[:13]
        s += f"LIVES USED:{self.__lives_used}\n"[:24]
        s += f"TIME: {self.__ticks//10}\n"
        os.write(1, str.encode(s))
        os.system('setterm -cursor on')
        os._exit(0)
Example #2
0
    level = Easy()
    level.placeBricks()
    while True:
        level.screen.time += level.ball.waitTime
        time.sleep(level.ball.waitTime)
        if keyboard.kbhit():
            inp = keyboard.getch()
            if inp == 'q':
                sys.exit()
            elif inp == 'a' or inp == 'd':
                level.paddle.move(inp)
            elif inp == ' ':
                level.ball.launch()
            elif inp == 't':
                break
            keyboard.flush()
        level.ball.move()

        if level.ball.gameOver == True:
            break
        os.system("clear")
        level.screen.display()
        print("Level 1")
        print("Score:", level.screen.score + score, "  ", "Time elapsed:",
              int(level.screen.time))
        print("Lives left:", lives - 1)
    score += level.screen.score

    # level 2
    level = Moderate()
    level.placeBricks()
Example #3
0
def main():
    def setup_logging():
        print("setup_logging")

        logging.basicConfig(
            format=
            "%(asctime)s [%(threadName)-12.12s] [%(levelname)-5.5s]  %(message)s",
            handlers=[
                logging.FileHandler("./zero_one.log"),
                logging.StreamHandler(sys.stdout)
            ],
            level=logging.INFO)

    def destroy_logging():
        print("destroy_logging")

    # Start the main program here

    print('Testing UI ...')
    setup_logging()

    st = 0
    tick = 0

    try:
        app_ui = ui.get_ui_instance()
        command = None

        app_ui.led_flash(ui.Led.LED_RED, 0.1)

        this_directory = os.path.dirname(os.path.realpath(__file__))
        binary_path = os.path.join(this_directory,
                                   "fadecandy/bin/fcserver-osx")
        config_path = os.path.join(this_directory,
                                   "fadecandy/bin/test-rig_config.json")

        fcserver = display.FCServer(binary_path, config_path)
        print(fcserver)

        d1 = display.Display()
        print(d1)

        while command != ui.Commands.Quit:
            print('. ')
            time.sleep(0.1)
            command = app_ui.get_command()
            button = app_ui.get_button()

            if button != None:
                if button == Button.BUTTON_1:
                    print('BUTTON_1')
                    print('fcserver setup', fcserver.setup())
                elif button == Button.BUTTON_2:
                    print('BUTTON_2')
                    fcserver.test()
                elif button == Button.BUTTON_3:
                    print('BUTTON_3')
                    raise ZeroOneException('Critical failure - user bored', 4)

            # if _ui.test_button(Button.BUTTON_3):
            #     _ui.led_on(ui.Led.LED_AMBER)
            # else:
            #     _ui.led_off(ui.Led.LED_AMBER)

            # tick = tick+1
            # if tick > 20:
            #     print('Queue:', _ui.get_button())
            #     tick = 0

            if command == ui.Commands.Test:
                print('TEST')

                if st == 0:
                    pass

                if st == 1:
                    pass

                print(app_ui)

                st = st + 1
                if st == 2:
                    st = 0

        app_ui.shutdown()

        # Flush the keyboard here
        # TODO : is this even needed anymore
        kb = KBHit()
        kb.flush()

    except KeyboardInterrupt as ex:
        print("Aborted")

    except ZeroOneException as ex:
        print("\n>>> EXCEPTION : {} <<<\n".format(ex.message))
        logging.error(ex.message, exc_info=True)
        app_ui.display_exception(ex.error_code)

    finally:
        app_ui.shutdown()
        fcserver.shutdown()
        destroy_logging()
        print('Done!')
def main(argv):
    print('ZeroOneController running ...')

    # Set up the logging
    setup_logging()
    logging.info('ZeroOneController running ...')

    # Get the UI instance
    app_ui = ui.get_ui_instance()
    command = None

    app_ui.led_flash(ui.Led.LED_AMBER, 0.2)

    # Read the config file
    config_file = './config.ini'
    try:
        opts, args = getopt.getopt(argv, "hc:", ["config="])
    except getopt.GetoptError:
        print('ZeroOneController.py --config <configfile>')
        raise ZeroOneException()

    for opt, arg in opts:
        if opt in ('-c', '--config'):
            config_file = arg

    this_directory = os.path.dirname(os.path.realpath(__file__))

    # Test the config file exists
    print('Using config from', config_file)
    # TODO : This should check absolute path
    # os.path.isabs()
    if os.path.exists(config_file) == False:
        raise ZeroOneException(
            "Config file {0} does not exist".format(config_file))
    else:
        # TODO : This should catch the json.decoder.JSONDecodeError exception
        with open(config_file) as cf:
            data = json.load(cf)

            config_fadecandy = data['Fadecandy']
            config_emulator = data['DisplayEmulator']
            config_options = data['Options']

            ide_mode = False
            if 'Ide_mode' in config_options:
                if config_options['Ide_mode'] != 0:
                    ide_mode = True

            this_directory = os.path.dirname(os.path.realpath(__file__))

    # Now create a display object
    app_display = display.Display(config_fadecandy, config_emulator)
    app_display.setup()

    app_effects = effect.EffectController()
    image_cycler = effect.ImageCycler(config_options['ImagePath'])

    try:
        if ide_mode == True:

            image_filename = '/Users/colind/Documents/Projects/ZeroOne/ZeroOne/Controller/images/RGBW.png'
            print(image_filename)

            zo_image = ZO_Image()
            zo_image.load_from_file(image_filename)
            print(zo_image)

            # zo_image.image.show()
            app_display.update_display(zo_image.test_image())

        else:
            while command != ui.Commands.Quit:
                print('. ')
                time.sleep(0.05)

                # Check if we're running in the IDE mode or not
                if ide_mode == False:
                    command = app_ui.get_command()
                    button = app_ui.get_button()
                else:
                    command, button = get_ide_mode_command_and_button()

                # Process the incoming commands
                if button != None:
                    if button == Button.BUTTON_1:
                        print('BUTTON_1')
                        app_display.clear_display()
                    elif button == Button.BUTTON_2:
                        print('BUTTON_2')
                        image_file = image_cycler.get_next_file()

                        print('Processing ', image_file)
                        img = ZO_Image()
                        img.load_from_file(image_file)
                        app_display.update_display(img.image)
                    elif button == Button.BUTTON_3:
                        print('BUTTON_3')

        try:
            kb = KBHit()
            kb.flush()
        except:
            pass

    except KeyboardInterrupt:
        print('Exiting ...')

    except ZeroOneException as ex:
        print("\n>>> EXCEPTION : {} <<<\n".format(ex.message))
        logging.error(ex.message, exc_info=True)
        app_ui.display_exception(ex.error_code)

    finally:
        app_ui.shutdown()
        app_display.shutdown()

        logging.info('Done!')
        destroy_logging()
        print('Done!')