def enter(self, args):
        self.args = args
        self.setting = args["setting"]
        self.setting_text_line = TextLine(self.setting, self.font, (250, 50))
        self.val = args["value"]["Value"]
        self.val_text_line = TextLine(f"Current value : {self.val}", self.font,
                                      (250, 100))

        self.choices = args["value"]["Choices"]
        for e, i in enumerate(args["value"]["Choices"]):
            self.action_manager.add_button(str(i), (250, e * 50 + 150),
                                           (50, 30))
 def __init__(self, fsm):
     super().__init__(fsm)
     self.action_manager.add_button("Retry", (200, 400), (50, 30))
     self.action_manager.add_button("Back to Main Menu", (500, 400),
                                    (50, 30),
                                    ret="Main Menu")
     self.action_manager.add_button("Back to Start", (300, 400), (50, 30),
                                    ret="Start")
     self.action_manager.add_keystroke("Exit", "escape")
     self.high_scores = get_user_data()["Highscores"]
     self.score_font = pygame.font.Font(self.fsm.SYSFONT, 24)
     self.high_score_text = TextLine("High Score achieved!",
                                     self.score_font, (250, 300))
    def __init__(self, fsm):
        super().__init__(fsm)
        self.font = pygame.font.Font(self.fsm.SYSFONT, 24)

        self.text_lines = []
        self.text_lines.append(
            TextLine("Bach to the Future", self.font, (200, 100)))
        self.text_lines.append(
            TextLine("Icon made by Freepik from www.flaticon.com",
                     pygame.font.Font(self.fsm.SYSFONT, 14), (150, 300)))

        self.action_manager.add_button("Back", (50, 50), (50, 30))

        self.action_manager.add_button("Exit", (50, self.fsm.HEIGHT - 100),
                                       (50, 30))
class MainMenuState(BaseState):
    def __init__(self, fsm):
        super().__init__(fsm)
        self.action_manager.add_button("Start (Space)", (50, 50), (50, 30),
                                       ret="Start",
                                       key="space")
        self.action_manager.add_button("Options", (50, 100), (50, 30))
        self.action_manager.add_button("Achievements", (50, 150), (50, 30))
        self.action_manager.add_button("Storyline", (50, 200), (50, 30))
        self.action_manager.add_button("About", (50, self.fsm.HEIGHT - 100),
                                       (50, 30))
        self.action_manager.add_button("Exit (Esc)",
                                       (50, self.fsm.HEIGHT - 50), (50, 30),
                                       ret="Exit",
                                       key="escape")

        self.font = pygame.font.Font(self.fsm.SYSFONT, 24)

        self.text_line = TextLine("~BACH TO THE FUTURE~", self.font, (300, 50))

    def update(self, game_time, lag):
        events = pygame.event.get()
        actions = self.action_manager.chk_actions(events)

        for action in actions:
            if action == "Exit":
                self.fsm.ch_state(ExitState(self.fsm))

            elif action == "Start":
                self.fsm.ch_state(SelectTrackState(self.fsm))

            elif action == "Options":
                self.fsm.ch_state(SettingsState(self.fsm))

            elif action == "Achievements":
                self.fsm.ch_state(AchievementsState(self.fsm))

            elif action == "About":
                self.fsm.ch_state(AboutState(self.fsm))

            elif action == "Storyline":
                from Storyline import StoryState
                self.fsm.ch_state(StoryState(self.fsm),
                                  {"file": "storyline.json"})

    def draw(self):
        super().draw()
        self.text_line.draw(self.fsm.screen)
    def __init__(self, fsm):
        super().__init__(fsm)
        self.action_manager.add_button("Start (Space)", (50, 50), (50, 30),
                                       ret="Start",
                                       key="space")
        self.action_manager.add_button("Options", (50, 100), (50, 30))
        self.action_manager.add_button("Achievements", (50, 150), (50, 30))
        self.action_manager.add_button("Storyline", (50, 200), (50, 30))
        self.action_manager.add_button("About", (50, self.fsm.HEIGHT - 100),
                                       (50, 30))
        self.action_manager.add_button("Exit (Esc)",
                                       (50, self.fsm.HEIGHT - 50), (50, 30),
                                       ret="Exit",
                                       key="escape")

        self.font = pygame.font.Font(self.fsm.SYSFONT, 24)

        self.text_line = TextLine("~BACH TO THE FUTURE~", self.font, (300, 50))
Exemple #6
0
    def advance(self, commands):
        self.curr_frame = 0
        self.max_frame = 0
        self.isDone = False
        self.forceDone = False
        self.scripts = []
        self.curr_text = ""
        for command in commands:
            print(command)
            if command["Type"] == "Title":
                self.title = TextLine(command["Text"], self.font1,
                                      (400, 50)).align_ctr()
            elif command["Type"] == "Speech":
                self.curr_text = command["Text"]
                self.text_len = len(self.curr_text)

            elif command["Type"] == "Audio Start":
                if self.player is not None:
                    self.player.stop()
                self.player = vlc.MediaPlayer("Sheep may safely graze.ogg")
                self.player.play()

            elif command["Type"] == "Audio Stop":
                pygame.mixer.music.stop()

            elif command["Type"] == "Script":

                with open(command["File"]) as script_file:
                    script_code = script_file.read()
                self.scripts.append(script_code)
                exec(command["Init"])
                self.max_frame = max(self.max_frame, command["max_frame"])

            elif command["Type"] == "Background":
                with open("fadein.py") as script_file:
                    script_code = script_file.read()
                self.scripts.append(script_code)
                self.curr_alpha = 0
                self.bg_copy = self.background.copy()
                self.fade_spd = 2
                self.mask = pygame.image.load(command["File"]).convert()
                self.max_frame = max(self.max_frame, 128)

        self.max_frame = max(self.max_frame, self.text_len)
Exemple #7
0
 def __init__(self, fsm):
     super().__init__(fsm)
     #self.action_manager.add_button("Back", (50, 50), (50, 30))
     self.action_manager.add_keystroke("space", "space", ret="Advance")
     self.action_manager.add_keystroke("enter", "return", ret="Advance")
     self.action_manager.add_keystroke("Vol+", "up")
     self.action_manager.add_keystroke("Vol-", "down")
     self.font1 = pygame.font.Font(self.fsm.SYSFONT, 22)
     self.font2 = pygame.font.Font(self.fsm.SYSFONT, 14)
     self.title = TextLine("StoryState", self.font1, (400, 50)).align_ctr()
     self.curr_text = ""
     self.text_len = 0
     self.curr_text_box = TextBox(self.curr_text, self.font2, (50, 350),
                                  (700, 250))
     self.curr_frame = 0
     self.max_frame = 0
     self.scripts = []
     self.isDone = True
     self.forceDone = False
class ChSettingState(BaseState):
    def __init__(self, fsm):
        super().__init__(fsm)
        self.font = pygame.font.Font(self.fsm.SYSFONT, 20)
        self.action_manager.add_button("Back", (50, 50), (50, 30))

    def enter(self, args):
        self.args = args
        self.setting = args["setting"]
        self.setting_text_line = TextLine(self.setting, self.font, (250, 50))
        self.val = args["value"]["Value"]
        self.val_text_line = TextLine(f"Current value : {self.val}", self.font,
                                      (250, 100))

        self.choices = args["value"]["Choices"]
        for e, i in enumerate(args["value"]["Choices"]):
            self.action_manager.add_button(str(i), (250, e * 50 + 150),
                                           (50, 30))

    def update(self, game_time, lag):
        events = pygame.event.get()

        actions = self.action_manager.chk_actions(events)

        for action in actions:
            if action == "Back":
                self.fsm.ch_state(SettingsState(self.fsm))
            elif action == "Exit":
                self.fsm.ch_state(ExitState(self.fsm))

            elif action in self.choices or eval(action) in self.choices:
                print(f"Choice clicked : {eval(action)}")
                ch_config(self.setting, action)
                config2 = get_config()
                self.fsm.__init__(config2)
                self.fsm.curr_state = MainMenuState(self.fsm)
                self.fsm.ch_state(SettingsState(self.fsm))

    def draw(self):
        super().draw()
        self.setting_text_line.draw(self.fsm.screen)
        self.val_text_line.draw(self.fsm.screen)
    def __init__(self, fsm):
        super().__init__(fsm)
        pygame.key.set_repeat(1)
        self.action_manager.add_button("Back", (self.fsm.WIDTH - 100, 50),
                                       (50, 30),
                                       ret="Back",
                                       key="backspace")
        self.action_manager.add_keystroke("Pause", 'p')
        self.action_manager.add_keystroke("Vol+", "up")
        self.action_manager.add_keystroke("Vol-", "down")
        self.isPlaying = True
        self.beatmap = None
        self.orbs = []
        self.image = pygame.image.load(
            f"{self.fsm.ASSETS_DIR}longrectangle.png").convert()

        self.score = 0
        self.score_font = pygame.font.Font(self.fsm.SYSFONT, 24)
        self.score_line = TextLine(str(self.score), self.score_font, (750, 50))

        self.orb_spd = 450
        self.countdown = self.fsm.FPS * 5
    def __init__(self, fsm):
        super().__init__(fsm)
        self.action_manager.add_button("Back", (50, 50), (50, 30))
        self.name_font = pygame.font.Font(self.fsm.SYSFONT, 20)
        self.des_font = pygame.font.Font(self.fsm.SYSFONT, 14)

        self.text_lines = []
        hasAchieved = get_user_data()["Achievements"]
        print(hasAchieved)
        achievements = get_achievements()
        for i, achievement in enumerate(achievements):

            font_col = rgb.GREEN if hasAchieved[
                achievement["name"]] else rgb.WHITE
            self.text_lines.append(
                TextLine(achievement["name"],
                         self.name_font, (200, i * 80 + 50),
                         font_colour=font_col))
            self.text_lines.append(
                TextLine(achievement["description"],
                         self.des_font, (200, i * 80 + 85),
                         font_colour=font_col))
    def enter(self, args):
        self.settings = get_config()
        self.text = []
        self.text_lines = []

        for i, setting in enumerate(self.settings):
            val = self.settings[setting]["Value"]
            self.text_lines.append(
                TextLine(f"{setting} : {val}", self.font,
                         (300, i * 50 + 30, 10, 10)))
            self.action_manager.add_button("Change", (200, i * 50 + 25),
                                           (30, 30),
                                           ret=setting)
    def enter(self, args):
        self.args = args

        self.score = args["score"]
        self.track = args["file_name"].rsplit('.', 1)[0]

        ctr = self.fsm.WIDTH // 2

        self.score_line = TextLine(f"Score : {self.score}", self.score_font,
                                   (ctr, 150)).align_ctr()

        self.track_line = TextLine(self.track, self.score_font,
                                   (ctr, 50)).align_ctr()

        if self.high_scores[self.track] < self.score:
            print("High Score achieved!")
            self.isHighScore = True
            update_user_data(
                ("Highscores", args["file_name"].rsplit('.', 1)[0]),
                args["score"])
        else:
            print("High Score not achieved")
            self.isHighScore = False
class GameOverState(BaseState):
    def __init__(self, fsm):
        super().__init__(fsm)
        self.action_manager.add_button("Retry", (200, 400), (50, 30))
        self.action_manager.add_button("Back to Main Menu", (500, 400),
                                       (50, 30),
                                       ret="Main Menu")
        self.action_manager.add_button("Back to Start", (300, 400), (50, 30),
                                       ret="Start")
        self.action_manager.add_keystroke("Exit", "escape")
        self.high_scores = get_user_data()["Highscores"]
        self.score_font = pygame.font.Font(self.fsm.SYSFONT, 24)
        self.high_score_text = TextLine("High Score achieved!",
                                        self.score_font, (250, 300))

    def enter(self, args):
        self.args = args

        self.score = args["score"]
        self.track = args["file_name"].rsplit('.', 1)[0]

        ctr = self.fsm.WIDTH // 2

        self.score_line = TextLine(f"Score : {self.score}", self.score_font,
                                   (ctr, 150)).align_ctr()

        self.track_line = TextLine(self.track, self.score_font,
                                   (ctr, 50)).align_ctr()

        if self.high_scores[self.track] < self.score:
            print("High Score achieved!")
            self.isHighScore = True
            update_user_data(
                ("Highscores", args["file_name"].rsplit('.', 1)[0]),
                args["score"])
        else:
            print("High Score not achieved")
            self.isHighScore = False

    def update(self, game_time, lag):
        events = pygame.event.get()

        actions = self.action_manager.chk_actions(events)

        for action in actions:
            if action == "Retry":
                self.fsm.ch_state(PlayGameState(self.fsm), self.args)

            elif action == "Main Menu":
                self.fsm.ch_state(MainMenuState(self.fsm))

            elif action == "Start":
                self.fsm.ch_state(SelectTrackState(self.fsm))

            elif action == "Exit":
                self.fsm.ch_state(ExitState(self.fsm))

    def draw(self):
        super().draw()
        self.score_line.draw(self.fsm.screen)
        self.track_line.draw(self.fsm.screen)
        if self.isHighScore:
            self.high_score_text.draw(self.fsm.screen)
    def update(self, game_time, lag):
        actions = self.action_manager.chk_actions(pygame.event.get())

        orbsONSCREEN = [orb for orb in self.orbs if orb.getTail() > 0]

        for action in actions:

            if action == "Exit":
                self.fsm.ch_state(ExitState(self.fsm))

            elif action == "Back":
                self.fsm.ch_state(MainMenuState(self.fsm))

            elif action == "Pause":
                self.isPlaying = not self.isPlaying
                self.player.pause()
                if pygame.key.get_repeat() == 0:
                    pygame.key.set_repeat(1)
                else:
                    pygame.key.set_repeat(0)

            elif action == "Vol+":
                self.volume += 1
                self.player.audio_set_volume(self.volume)
                print(f"Volume : {self.player.audio_get_volume()}")

            elif action == "Vol-":
                self.volume = max(0, self.volume - 1)
                self.player.audio_set_volume(self.volume)
                print(f"Volume : {self.player.audio_get_volume()}")

            elif action == "f (down)":
                for orb in orbsONSCREEN:
                    if abs(orb.getTail() - 500) < 10 and orb.lane == 0:
                        self.score += 1
                        print("Score += 1")
                self.laneIcons[0][1] = True

            elif action == "f (up)":
                for orb in orbsONSCREEN:
                    if orb.lane == 0:
                        penalty = round(0.1 * max(orb.y - 500, 0))
                        self.score -= penalty
                        print(f"Penalty to score : -{penalty}")
                self.laneIcons[0][1] = False

            elif action == "g (down)":
                for orb in orbsONSCREEN:
                    if abs(orb.getTail() - 500) < 10 and orb.lane == 1:
                        self.score += 1
                        print("Score += 1")
                self.laneIcons[1][1] = True

            elif action == "g (up)":
                for orb in orbsONSCREEN:
                    if orb.lane == 1:
                        penalty = round(0.1 * max(orb.y - 500, 0))
                        self.score -= penalty
                        print(f"Penalty to score : -{penalty}")
                self.laneIcons[1][1] = False

            elif action == "h (down)":
                for orb in orbsONSCREEN:
                    if abs(orb.getTail() - 500) < 10 and orb.lane == 2:
                        self.score += 1
                        print("Score += 1")
                self.laneIcons[2][1] = True

            elif action == "h (up)":
                for orb in orbsONSCREEN:
                    if orb.lane == 2:
                        penalty = round(0.1 * max(orb.y - 500, 0))
                        self.score -= penalty
                        print(f"Penalty to score : -{penalty}")
                self.laneIcons[2][1] = False

            elif action == "j (down)":
                for orb in orbsONSCREEN:
                    if abs(orb.getTail() - 500) < 10 and orb.lane == 3:
                        self.score += 1
                        print("Score += 1")
                self.laneIcons[3][1] = True

            elif action == "j (up)":
                for orb in orbsONSCREEN:
                    if orb.lane == 3:
                        penalty = round(0.1 * max(orb.y - 500, 0))
                        self.score -= penalty
                        print(f"Penalty to score : -{penalty}")
                self.laneIcons[3][1] = False

        if self.isPlaying:  # pause handling
            for i in self.orbs:
                i.y += self.orb_spd * (self.fsm.fps_clock.get_time() / 1000)
                if i.y > self.fsm.HEIGHT:
                    self.orbs.remove(i)

        if len(self.orbs) == 0:
            self.countdown -= 1
            if self.countdown <= 0:
                print("Track Completed!")
                self.fsm.ch_state(GameOverState(self.fsm), {
                    "file_name": self.file,
                    "score": self.score
                })

        self.score_line = TextLine(str(self.score), self.score_font, (550, 50))
class PlayGameState(BaseState):
    def __init__(self, fsm):
        super().__init__(fsm)
        pygame.key.set_repeat(1)
        self.action_manager.add_button("Back", (self.fsm.WIDTH - 100, 50),
                                       (50, 30),
                                       ret="Back",
                                       key="backspace")
        self.action_manager.add_keystroke("Pause", 'p')
        self.action_manager.add_keystroke("Vol+", "up")
        self.action_manager.add_keystroke("Vol-", "down")
        self.isPlaying = True
        self.beatmap = None
        self.orbs = []
        self.image = pygame.image.load(
            f"{self.fsm.ASSETS_DIR}longrectangle.png").convert()

        self.score = 0
        self.score_font = pygame.font.Font(self.fsm.SYSFONT, 24)
        self.score_line = TextLine(str(self.score), self.score_font, (750, 50))

        self.orb_spd = 450
        self.countdown = self.fsm.FPS * 5

    def enter(self, args):

        self.file = args["file_name"]
        print(f"File name = {self.file}")
        file_path = f"{self.fsm.TRACKS_DIR}{self.file}"
        with open(file_path, 'r') as file:
            reader = csv.reader(file)
            next(reader)
            self.beatmap = [row for row in reader]
        lanes = 4
        self.positions = [i * 100 for i in range(1, lanes + 1)]

        ############################################################################

        self.lane1 = pygame.image.load(
            f"{self.fsm.ASSETS_DIR}red.png").convert()
        self.lane2 = pygame.image.load(
            f"{self.fsm.ASSETS_DIR}green.png").convert()
        self.lane3 = pygame.image.load(
            f"{self.fsm.ASSETS_DIR}yellow.png").convert()
        self.lane4 = pygame.image.load(
            f"{self.fsm.ASSETS_DIR}purple.png").convert()
        self.laneIcons = [[(self.lane1, (self.positions[0], 490)), False], \
                          [(self.lane2, (self.positions[1], 490)), False], \
                          [(self.lane3, (self.positions[2], 490)), False], \
                          [(self.lane4, (self.positions[3], 490)), False]]

        self.action_manager.add_sp_keystroke('f', 'f')
        self.action_manager.add_sp_keystroke('g', 'g')
        self.action_manager.add_sp_keystroke('h', 'h')
        self.action_manager.add_sp_keystroke('j', 'j')

        ############################################################################

        reference_note = int(self.beatmap[0][2])
        lane = 0

        for beat in self.beatmap:
            diff = int(beat[2]) - reference_note
            lane = (lane + diff) % lanes
            x = self.positions[lane]

            end_time = float(beat[0])
            duration = float(beat[1])
            y = -(end_time) * self.orb_spd + 498 - self.orb_spd * 0.1
            orb = OrbModel(x, y, duration, lane, end_time)
            self.orbs.append(orb)
            reference_note = int(beat[2])

        wav_file = self.file.rsplit('.', 1)[0]
        self.player = self.fsm.wav_files[wav_file]
        self.volume = int(get_config()["Default Volume"]["Value"])
        print(self.volume)
        self.player.audio_set_volume(self.volume)
        self.player.play()

    def update(self, game_time, lag):
        actions = self.action_manager.chk_actions(pygame.event.get())

        orbsONSCREEN = [orb for orb in self.orbs if orb.getTail() > 0]

        for action in actions:

            if action == "Exit":
                self.fsm.ch_state(ExitState(self.fsm))

            elif action == "Back":
                self.fsm.ch_state(MainMenuState(self.fsm))

            elif action == "Pause":
                self.isPlaying = not self.isPlaying
                self.player.pause()
                if pygame.key.get_repeat() == 0:
                    pygame.key.set_repeat(1)
                else:
                    pygame.key.set_repeat(0)

            elif action == "Vol+":
                self.volume += 1
                self.player.audio_set_volume(self.volume)
                print(f"Volume : {self.player.audio_get_volume()}")

            elif action == "Vol-":
                self.volume = max(0, self.volume - 1)
                self.player.audio_set_volume(self.volume)
                print(f"Volume : {self.player.audio_get_volume()}")

            elif action == "f (down)":
                for orb in orbsONSCREEN:
                    if abs(orb.getTail() - 500) < 10 and orb.lane == 0:
                        self.score += 1
                        print("Score += 1")
                self.laneIcons[0][1] = True

            elif action == "f (up)":
                for orb in orbsONSCREEN:
                    if orb.lane == 0:
                        penalty = round(0.1 * max(orb.y - 500, 0))
                        self.score -= penalty
                        print(f"Penalty to score : -{penalty}")
                self.laneIcons[0][1] = False

            elif action == "g (down)":
                for orb in orbsONSCREEN:
                    if abs(orb.getTail() - 500) < 10 and orb.lane == 1:
                        self.score += 1
                        print("Score += 1")
                self.laneIcons[1][1] = True

            elif action == "g (up)":
                for orb in orbsONSCREEN:
                    if orb.lane == 1:
                        penalty = round(0.1 * max(orb.y - 500, 0))
                        self.score -= penalty
                        print(f"Penalty to score : -{penalty}")
                self.laneIcons[1][1] = False

            elif action == "h (down)":
                for orb in orbsONSCREEN:
                    if abs(orb.getTail() - 500) < 10 and orb.lane == 2:
                        self.score += 1
                        print("Score += 1")
                self.laneIcons[2][1] = True

            elif action == "h (up)":
                for orb in orbsONSCREEN:
                    if orb.lane == 2:
                        penalty = round(0.1 * max(orb.y - 500, 0))
                        self.score -= penalty
                        print(f"Penalty to score : -{penalty}")
                self.laneIcons[2][1] = False

            elif action == "j (down)":
                for orb in orbsONSCREEN:
                    if abs(orb.getTail() - 500) < 10 and orb.lane == 3:
                        self.score += 1
                        print("Score += 1")
                self.laneIcons[3][1] = True

            elif action == "j (up)":
                for orb in orbsONSCREEN:
                    if orb.lane == 3:
                        penalty = round(0.1 * max(orb.y - 500, 0))
                        self.score -= penalty
                        print(f"Penalty to score : -{penalty}")
                self.laneIcons[3][1] = False

        if self.isPlaying:  # pause handling
            for i in self.orbs:
                i.y += self.orb_spd * (self.fsm.fps_clock.get_time() / 1000)
                if i.y > self.fsm.HEIGHT:
                    self.orbs.remove(i)

        if len(self.orbs) == 0:
            self.countdown -= 1
            if self.countdown <= 0:
                print("Track Completed!")
                self.fsm.ch_state(GameOverState(self.fsm), {
                    "file_name": self.file,
                    "score": self.score
                })

        self.score_line = TextLine(str(self.score), self.score_font, (550, 50))

    def exit(self):
        self.player.stop()
        pygame.key.set_repeat(0)

    def draw(self):
        super().draw()
        self.score_line.draw(self.fsm.screen)
        pygame.draw.line(self.fsm.screen, rgb.GREY, (0, 500), (800, 500), 5)

        for pos in self.positions:
            x = pos - 35
            pygame.draw.line(self.fsm.screen, rgb.GREEN, (x, 0),
                             (x, self.fsm.HEIGHT), 5)
        pygame.draw.line(self.fsm.screen, rgb.GREEN,
                         (self.positions[-1] + 60, 0),
                         (self.positions[-1] + 60, self.fsm.HEIGHT), 5)

        for i in self.orbs:
            self.fsm.screen.blit(self.image,
                                 (i.x, round(i.y + i.length * 0.1)),
                                 (0, 0, 30, round(i.length * 0.9)))

        for args, boolean in self.laneIcons:
            if boolean:
                self.fsm.screen.blit(*args)
Exemple #16
0
class StoryState(BaseState):
    def __init__(self, fsm):
        super().__init__(fsm)
        #self.action_manager.add_button("Back", (50, 50), (50, 30))
        self.action_manager.add_keystroke("space", "space", ret="Advance")
        self.action_manager.add_keystroke("enter", "return", ret="Advance")
        self.action_manager.add_keystroke("Vol+", "up")
        self.action_manager.add_keystroke("Vol-", "down")
        self.font1 = pygame.font.Font(self.fsm.SYSFONT, 22)
        self.font2 = pygame.font.Font(self.fsm.SYSFONT, 14)
        self.title = TextLine("StoryState", self.font1, (400, 50)).align_ctr()
        self.curr_text = ""
        self.text_len = 0
        self.curr_text_box = TextBox(self.curr_text, self.font2, (50, 350),
                                     (700, 250))
        self.curr_frame = 0
        self.max_frame = 0
        self.scripts = []
        self.isDone = True
        self.forceDone = False

    def enter(self, args):
        self.background.fill(rgb.BLACK)
        with open(args["file"]) as file:
            self.script = json.load(file)
        self.curr_line = 0
        self.max_line = len(self.script)
        self.volume = int(get_config()["Default Volume"]["Value"])
        self.player = None

    def update(self, game_time, lag):
        actions = self.action_manager.chk_actions(pygame.event.get())
        for action in actions:
            if action == "Exit":
                self.fsm.ch_state(ExitState(self.fsm))
            elif action == "Back":
                self.fsm.ch_state(MainMenuState(self.fsm))

            elif action == "Vol+":
                self.volume += 1
                if self.player is not None:
                    self.player.audio_set_volume(self.volume)
                print(f"Volume : {self.player.audio_get_volume()}")

            elif action == "Vol-":
                self.volume = max(0, self.volume - 1)
                if self.player is not None:
                    self.player.audio_set_volume(self.volume)
                print(f"Volume : {self.player.audio_get_volume()}")

            elif action == "Advance":
                if self.isDone:
                    if self.curr_line == self.max_line:
                        print("Scene completed!")
                        self.fsm.ch_state(MainMenuState(self.fsm))
                    else:
                        self.advance(self.script[self.curr_line])
                        self.curr_line += 1
                else:
                    self.forceDone = True
                    self.curr_frame = self.max_frame

        self.curr_text_pos = min(self.curr_frame, self.text_len)
        self.curr_text_box = TextBox(self.curr_text[:self.curr_text_pos],
                                     self.font2, (50, 350), (700, 250))
        self.curr_frame += 1
        if self.curr_frame >= self.max_frame:
            self.isDone = True
        for script_code in self.scripts:
            exec(script_code)

    def advance(self, commands):
        self.curr_frame = 0
        self.max_frame = 0
        self.isDone = False
        self.forceDone = False
        self.scripts = []
        self.curr_text = ""
        for command in commands:
            print(command)
            if command["Type"] == "Title":
                self.title = TextLine(command["Text"], self.font1,
                                      (400, 50)).align_ctr()
            elif command["Type"] == "Speech":
                self.curr_text = command["Text"]
                self.text_len = len(self.curr_text)

            elif command["Type"] == "Audio Start":
                if self.player is not None:
                    self.player.stop()
                self.player = vlc.MediaPlayer("Sheep may safely graze.ogg")
                self.player.play()

            elif command["Type"] == "Audio Stop":
                pygame.mixer.music.stop()

            elif command["Type"] == "Script":

                with open(command["File"]) as script_file:
                    script_code = script_file.read()
                self.scripts.append(script_code)
                exec(command["Init"])
                self.max_frame = max(self.max_frame, command["max_frame"])

            elif command["Type"] == "Background":
                with open("fadein.py") as script_file:
                    script_code = script_file.read()
                self.scripts.append(script_code)
                self.curr_alpha = 0
                self.bg_copy = self.background.copy()
                self.fade_spd = 2
                self.mask = pygame.image.load(command["File"]).convert()
                self.max_frame = max(self.max_frame, 128)

        self.max_frame = max(self.max_frame, self.text_len)

    def draw(self):
        self.fsm.screen.fill(rgb.BLACK)
        self.fsm.screen.blit(self.background, (0, 0))
        self.action_manager.draw_buttons(self.fsm.screen)
        self.title.draw(self.fsm.screen)
        self.curr_text_box.draw(self.fsm.screen)

    def exit(self):
        if self.player is not None:
            self.player.stop()