Ejemplo n.º 1
0
class Game:
    def __init__(self):
        pygame.mixer.pre_init(44100, -16, 2, 2048)
        pygame.init()

        self.window = pygame.display.set_mode(
            (constants.WIDTH, constants.HEIGHT))
        pygame.display.set_caption(
            "The Legend of Zelda: Trials of the Triforce")

        self.clock = pygame.time.Clock()
        self.dt = 0

        self.scene = Scene(self)

        self.running = False

    def start(self):
        self.running = True

        self.scene.start()

        COUNTER = 0

        while self.running:
            self.scene.update(self.dt)

            self.dt = self.clock.tick(60) / 1000
            if self.dt > 0.33:
                self.dt = 0.33

            COUNTER += self.dt

            if COUNTER > 0.5:
                COUNTER = 0
Ejemplo n.º 2
0
    def __init__(self, app, state=None):

        super().__init__(app, state, self)

        self.scene = Scene(self.app, self)
        self.terminal = self.scene.add(Terminal(self.app, self.scene))
        self.camera = self.scene.add(Camera(app, self.scene, self.app.size))

        self.time = 0
Ejemplo n.º 3
0
    def __init__(self, app, state=None):

        super().__init__(app, state)

        self.scene = Scene(self.app, self)
        self.gui = Scene(self.app, self)
        self.slots = SlotList()
        self.paused = False

        # self.scene.add(ButtaBomber(app, self.scene, vec3(0, 0, -3000)))
        # self.scene.add(Powerup(app, self.scene, 'star', position=vec3(0, 0, -3000)))

        # create terminal first since player init() writes to it
        self.terminal = self.gui.add(Terminal(self.app, self.scene))

        self.app.inputs = self.build_inputs()
        self.camera = self.scene.add(Camera(app, self.scene, self.app.size))
        stats = self.stats = self.app.data["stats"] = self.app.data.get(
            "stats", Stats()
        )
        self.level = stats.level
        self.player = self.scene.add(Player(app, self.scene, level=self.level))

        # self.scripts += self.score_screen

        # self.camera.slots.append(
        #     self.player.on_move.connect(lambda: self.camera.update_pos(self.player))
        # )

        self.debug = False
        self.slots += [
            app.inputs["debug"].on_press(lambda _: self.debug_mode(True)),
            app.inputs["debug"].on_release(lambda _: self.debug_mode(False)),
        ]
        self.slots += [
            app.inputs["pause"].on_press(self.toggle_pause),
        ]

        self.time = 0

        # score backdrop
        backdrop_h = int(24 * 1.8)

        # draw a score backdrop
        rows = 8
        for i in range(rows):
            h = int(backdrop_h) // rows
            y = h * i
            backdrop = pygame.Surface((self.app.size.x, h))
            interp = i / rows
            interp_inv = 1 - i / rows
            backdrop.set_alpha(255 * interp * 0.4)
            # backdrop.fill((0))
            backdrop.fill(pg_color(ncolor("white") * interp_inv))
            self.scene.on_render += lambda _, y=y, backdrop=backdrop: self.app.screen.blit(
                backdrop, (0, y)
            )
Ejemplo n.º 4
0
    def __init__(self, scene, item):
        if 0:
            from game.scene import Scene
            self.scene = Scene()

        self.scene = scene
        self.id = self.scene.get_next_id()
        self.item = item
        self.action = ActionData()
        #item.scene_item = self
        self.scene.items[self.id] = self
Ejemplo n.º 5
0
    def __init__(self):
        pygame.mixer.pre_init(44100, -16, 2, 2048)
        pygame.init()
        self.window = pygame.display.set_mode((1024, 576))
        pygame.display.set_caption("Project Pokemon")

        self.clock = pygame.time.Clock()
        self.delta = 0

        self.scene = Scene(self, 'battle')

        self.running = False
Ejemplo n.º 6
0
    def __init__(self, app, state=None):

        super().__init__(app, state, self)

        self.scene = Scene(self.app, self)
        self.terminal = self.scene.add(Terminal(self.app, self.scene))
        self.bigterm = self.scene.add(Terminal(self.app, self.scene, 32))
        self.camera = self.scene.add(Camera(app, self.scene, self.app.size))
        self.scene.ground_color = "darkgreen"
        self.time = 0

        rows = 8
        backdrop_h = 150
        for i in range(rows):
            h = int(backdrop_h) // rows
            y = h * i
            backdrop = pygame.Surface((self.app.size.x, h))
            interp = i / rows
            interp_inv = 1 - i / rows
            backdrop.set_alpha(255 * interp_inv * 0.2)
            backdrop.fill(pg_color(ncolor("white") * interp_inv))
            self.scene.on_render += lambda _, y=y, backdrop=backdrop: self.app.screen.blit(
                backdrop, (0, y))

        rows = 8
        backdrop_h = 100
        for i in range(rows):
            h = int(backdrop_h) // rows
            y = h * i
            backdrop = pygame.Surface((self.app.size.x, h))
            interp = i / rows
            interp_inv = 1 - i / rows
            backdrop.set_alpha(255 * interp_inv * 0.1)
            backdrop.fill(pg_color(ncolor("white") * interp_inv))
            self.scene.on_render += lambda _, y=y, backdrop=backdrop: self.app.screen.blit(
                backdrop, (0, y))

        backdrop_h = int(24)
        rows = 4
        for i in range(rows, 0, -1):
            h = int(backdrop_h) // rows
            y = h * i
            backdrop = pygame.Surface((self.app.size.x, h))
            interp = i / rows
            interp_inv = 1 - i / rows
            backdrop.set_alpha(200 * interp_inv)
            backdrop.fill((0))
            # backdrop.fill(pg_color(ncolor('black')*interp_inv))
            self.scene.on_render += lambda _, y=y, backdrop=backdrop: self.app.screen.blit(
                backdrop, (0, self.app.size.y - y))
Ejemplo n.º 7
0
    def __init__(self, app, state=None):

        super().__init__(app, state, self)

        self.stats = self.app.data["stats"] = self.app.data.get(
            "stats", Stats())

        self.scene = Scene(self.app, self)

        self.terminal = self.scene.add(Terminal(self.app, self.scene))
        self.camera = self.scene.add(Camera(app, self.scene, self.app.size))
        self.ground = self.scene.add(Ground(app, self.scene, GROUND_HEIGHT))
        self.terminal.position.z -= 10

        self.time = 0
Ejemplo n.º 8
0
    def __init__(self):
        pygame.mixer.pre_init(44100, -16, 2, 2048)
        pygame.init()

        self.window = pygame.display.set_mode(
            (constants.WIDTH, constants.HEIGHT))
        pygame.display.set_caption(
            "The Legend of Zelda: Trials of the Triforce")

        self.clock = pygame.time.Clock()
        self.dt = 0

        self.scene = Scene(self)

        self.running = False
Ejemplo n.º 9
0
class Game:
    def __init__(self):
        pygame.mixer.pre_init(44100, -16, 2, 2048)
        pygame.init()
        self.window = pygame.display.set_mode((1024, 576))
        pygame.display.set_caption("Project Pokemon")

        self.clock = pygame.time.Clock()
        self.delta = 0

        self.scene = Scene(self, 'battle')

        self.running = False

    def run(self):
        self.running = True

        self.scene.start()

        while self.running:
            self.scene.update(self.delta)

            self.delta = self.clock.tick(60)

    def set_scene(self, scene):
        scene.prev = self.scene
        self.scene = scene
        self.scene.start()
Ejemplo n.º 10
0
class Menu(State):
    def __init__(self, app, state=None):

        super().__init__(app, state, self)

        self.scene = Scene(self.app, self)
        self.terminal = self.scene.add(Terminal(self.app, self.scene))
        self.camera = self.scene.add(Camera(app, self.scene, self.app.size))

        self.time = 0

    def pend(self):
        self.app.pend()

    def update(self, dt):
        super().update(dt)  # needed for script

        self.scene.update(dt)
        self.time += dt

    def render(self):

        self.scene.render(self.camera)

    def __call__(self, script):
        while True:
            yield
Ejemplo n.º 11
0
class SceneItem(object):
    __slots__ = ('scene', 'action', 'id', 'item')
    def __init__(self, scene, item):
        if 0:
            from game.scene import Scene
            self.scene = Scene()

        self.scene = scene
        self.id = self.scene.get_next_id()
        self.item = item
        self.action = ActionData()
        #item.scene_item = self
        self.scene.items[self.id] = self
Ejemplo n.º 12
0
class Intermission(State):
    def __init__(self, app, state=None):

        super().__init__(app, state, self)

        self.stats = self.app.data["stats"] = self.app.data.get(
            "stats", Stats())

        self.scene = Scene(self.app, self)

        self.terminal = self.scene.add(Terminal(self.app, self.scene))
        self.camera = self.scene.add(Camera(app, self.scene, self.app.size))
        self.ground = self.scene.add(Ground(app, self.scene, GROUND_HEIGHT))
        self.terminal.position.z -= 10

        self.time = 0
        # self.bg_color = ncolor("darkred")

    def pend(self):
        self.app.pend()

    def update(self, dt):
        super().update(dt)  # needed for script

        self.scene.update(dt)
        self.time += dt
        # self.bg_color = (
        #     ncolor("darkgreen") + math.sin(self.time % 1 * math.tau * 2) * 0.05
        # )

    def render(self):

        # self.app.screen.fill(
        #     pygame.Color(*[int(clamp(x * 255, 0, 255)) for x in self.bg_color])
        # )
        self.scene.render(self.camera)

    def __call__(self, script):
        yield
        scene = self.scene
        terminal = self.terminal
        stats = self.stats
        self.scene.music = "intermission.ogg"
        when = script.when

        # self.scene.sky_color = "#4c0b6b"
        # self.scene.ground_color = "#e08041"
        self.scene.stars()
        self.scene.cloudy()

        textdelay = 0.02

        fade = []
        fades = [
            when.fade(
                10,
                (0, 1),
                lambda t: scene.set_sky_color(
                    glm.mix(ncolor("#4c0b6b"), ncolor("#e08041"), t)),
            ),
            when.fade(
                10,
                (0, 1),
                lambda t: scene.set_ground_color(
                    glm.mix(ncolor("darkgreen"), ncolor("yellow"), t)),
                lambda: fades.append(
                    when.every(
                        0, lambda: scene.set_ground_color(scene.ground_color))
                ),
            ),
        ]
        yield

        msg = [
            ("Level " + str(stats.level), "COMPLETED"),
            ("Damage Done", int(stats.damage_done)),
            ("Damage Taken", int(stats.damage_taken)),
            ("Kills", int(stats.kills)),
            # ("Lives Remaining", stats.lives),
            None,
            ("Score", stats.score),
        ]
        for y, line in enumerate(msg):
            if line:
                scene.ensure_sound("message.wav")
                for x, m in enumerate(line[0]):
                    terminal.write(m, (x + 1, y * 2 + 3), "white")
                    # terminal.write(m[:x], (x + 1, y * 2 + 3), "white")
                    # terminal.write(m[-1], (x + 1 + len(m) - 1, y * 2 + 3), "red")
                    yield script.sleep(0.01)
            else:
                continue
            if isinstance(line[1], int):  # total
                dd = 0
                for val in range(0, line[1] + 1):
                    terminal.write(
                        str(val),
                        (self.terminal.size.x - len(str(val)) - 1, y * 2 + 3),
                        "white",
                    )
                    dd += 0.6 / (val + 2)
                    if dd > 1 / max(self.app.fps, 10):
                        yield script.sleep(dd)
                        dd = 0
            else:
                yield script.sleep(0.1)
                terminal.write(
                    str(line[1]),
                    (self.terminal.size.x - len(str(line[1])) - 1, y * 2 + 3),
                    "green",
                )
                self.scene.play_sound("hit.wav")
                yield script.sleep(0.01)

        yield script.sleep(2)
        # while True:

        #     terminal.write_center("Press any key to continue", 20, "green")
        #     yield script.sleep(0.2)
        #     if script.keys_down:
        #         break
        #     terminal.clear(20)
        #     yield script.sleep(0.2)
        #     if script.keys_down:
        #         break

        self.stats.level += 1
        self.app.state = "game"
Ejemplo n.º 13
0
class Credits(State):
    def __init__(self, app, state=None):

        super().__init__(app, state, self)

        self.scene = Scene(self.app, self)

        self.terminal = self.scene.add(Terminal(self.app, self.scene))
        self.camera = self.scene.add(Camera(app, self.scene, self.app.size))

        self.time = 0
        self.bg_color = ncolor("darkred")

    def pend(self):
        self.app.pend()

    def update(self, dt):
        super().update(dt)  # needed for script

        self.scene.update(dt)
        self.time += dt
        self.bg_color = (ncolor("darkgreen") +
                         math.sin(self.time % 1 * math.tau * 2) * 0.05)

    def render(self):

        self.app.screen.fill(pg_color(self.bg_color))
        self.scene.render(self.camera)

    def __call__(self, script):
        yield
        scene = self.scene
        terminal = self.terminal
        self.scene.music = "butterfly.ogg"
        when = script.when

        # self.scene.sky_color = "#4c0b6b"
        # self.scene.ground_color = "#e08041"
        self.scene.stars()
        self.scene.cloudy()

        textdelay = 0.02

        fades = [
            when.fade(
                10,
                (0, 1),
                lambda t: scene.set_sky_color(
                    glm.mix(ncolor("#4c0b6b"), ncolor("#e08041"), t)),
            ),
            when.fade(
                10,
                (0, 1),
                lambda t: scene.set_ground_color(
                    glm.mix(ncolor("darkgreen"), ncolor("yellow"), t)),
                lambda: fades.append(
                    when.every(
                        0, lambda: scene.set_ground_color(scene.ground_color))
                ),
            ),
        ]
        yield

        pages = [
            [
                "CREDITS",
                "",
                "flipcoder",
                "    " + "Programming, Music, Sounds",
                "ddorn",
                "    " + "Programming, Graphics",
                "MysteryCoder456",
                "    " + "Programming",
                "Tamwile",
                "    " + "Graphics",
                "Jtiai",
                "    " + "Sounds",
                "",
                "Additional Assets: ",
                "    opengameart.org/users/pitrizzo",
            ],
            [
                "This game was created by PythonixCoders",
                "for PyWeek 29, a week-long Python game",
                "jam, where individuals or groups give",
                "themselves only one week to create a",
                "game.",
                "",
                "Participate next time at pyweek.org",
            ],
        ]
        for p, page in enumerate(pages):
            for y, line in enumerate(page):
                if line:
                    scene.ensure_sound("message.wav")
                    if p == 0:
                        if line == "CREDITS":
                            col = "white"
                        elif not line.startswith(" "):
                            col = "green"
                        else:
                            col = "white"
                    else:
                        col = "white"
                    for x, m in enumerate(line):
                        terminal.write(m, (x + 1, y + 1), col)
                        # terminal.write(m[:x], (x + 1, y * 2 + 3), "white")
                        # terminal.write(m[-1], (x + 1 + len(m) - 1, y * 2 + 3), "red")
                        yield script.sleep(0.01)
                        self.scene.play_sound("message.wav")
                else:
                    continue
                delay = 0.1
            yield script.sleep(4)
            self.terminal.clear()

        terminal.write_center("Thanks for Playing!!!", 10)
        while True:
            if script.keys_down:
                break
            yield script.sleep(0.1)

        self.app.state = None
Ejemplo n.º 14
0
class Game(State):
    def __init__(self, app, state=None):

        super().__init__(app, state)

        self.scene = Scene(self.app, self)
        self.gui = Scene(self.app, self)
        self.slots = SlotList()
        self.paused = False

        # self.scene.add(ButtaBomber(app, self.scene, vec3(0, 0, -3000)))
        # self.scene.add(Powerup(app, self.scene, 'star', position=vec3(0, 0, -3000)))

        # create terminal first since player init() writes to it
        self.terminal = self.gui.add(Terminal(self.app, self.scene))

        self.app.inputs = self.build_inputs()
        self.camera = self.scene.add(Camera(app, self.scene, self.app.size))
        stats = self.stats = self.app.data["stats"] = self.app.data.get(
            "stats", Stats())
        self.level = stats.level
        self.player = self.scene.add(Player(app, self.scene, level=self.level))

        # self.scripts += self.score_screen

        # self.camera.slots.append(
        #     self.player.on_move.connect(lambda: self.camera.update_pos(self.player))
        # )

        self.debug = False
        self.slots += [
            app.inputs["debug"].on_press(lambda _: self.debug_mode(True)),
            app.inputs["debug"].on_release(lambda _: self.debug_mode(False)),
        ]
        self.slots += [
            app.inputs["pause"].on_press(self.toggle_pause),
        ]

        self.time = 0

        # score backdrop
        backdrop_h = int(24 * 1.8)

        # draw a score backdrop
        rows = 8
        for i in range(rows):
            h = int(backdrop_h) // rows
            y = h * i
            backdrop = pygame.Surface((self.app.size.x, h))
            interp = i / rows
            interp_inv = 1 - i / rows
            backdrop.set_alpha(255 * interp * 0.4)
            # backdrop.fill((0))
            backdrop.fill(pg_color(ncolor("white") * interp_inv))
            self.scene.on_render += lambda _, y=y, backdrop=backdrop: self.app.screen.blit(
                backdrop, (0, y))

        # backdrop = pygame.Surface((self.app.size.x, h))
        # backdrop.set_alpha(255 * interp)
        # backdrop.fill((0))

        # backdrop_h = int(24)
        # rows = 4
        # for i in range(rows, 0, -1):
        #     h = (int(backdrop_h) // rows)
        #     y = h * i
        #     backdrop = pygame.Surface((self.app.size.x, h))
        #     interp = i/rows
        #     interp_inv = 1 - i/rows
        #     backdrop.set_alpha(200 * interp_inv)
        #     backdrop.fill((0))
        #     # backdrop.fill(pg_color(ncolor('black')*interp_inv))
        #     self.scene.on_render += lambda _, y=y,backdrop=backdrop: self.app.screen.blit(backdrop, (0,self.app.size.y-y))

        # self.scene.on_render += lambda _: self.app.screen.blit(self.backdrop, (0,int(self.app.size.y-backdrop_h)))

        # self.scripts += self.score_screen

    def toggle_pause(self, *args):
        if not self.player or not self.player.alive:
            self.app.state = "game"
            return

        self.paused = not self.paused
        if self.paused:
            self.terminal.write_center(
                "- GAME PAUSED -",
                10,
            )
            # self.scene.play_sound('pause.wav')
        else:
            self.terminal.clear(10)
            # self.scene.play_sound('pause.wav')

    @staticmethod
    # @lru_cache(maxsize=1)
    def level_count():
        level_regex = re.compile("level(\\d+).py")
        count = 0
        for path in os.listdir(SCRIPTS_DIR):
            if re.match(level_regex, path):
                count += 1
        return count + 1

    @property
    def level(self):
        return self._level

    @level.setter
    def level(self, value):
        self._level = value % self.level_count()
        self.scene.script = f"level{self.level}"

    def debug_mode(self, b):
        self.debug = b
        for i in range(9):
            self.terminal.clear(13 + i)
        if not b:
            self.player.write_weapon_stats()

    def pend(self):

        # self.dirty = True
        self.app.pend()  # tell app we need to update

    def update(self, dt):
        """
        Called every frame by App as long as Game is the current app.state
        :param dt: time since last frame in seconds
        """
        if self.paused:
            return

        super().update(dt)  # needed for state script (unused)

        if self.scene.script and self.scene.script.done():
            self.app.state = "intermission"
            return

        self.scene.update(dt)
        self.gui.update(dt)

        # Update the camera according to the player position
        # And movement
        self.camera.position = self.player.position + CAMERA_OFFSET
        self.camera.up = vec3(0, 1, 0)
        d = self.player.velocity.x / self.player.speed.x
        if d:
            self.camera.rotate_around_direction(-d * 0.05)
        self.time += dt

        assert self.scene.blocked == 0

    def render(self):
        """
        Clears screen and draws our scene to the screen
        Called every frame by App as long as Game is the current app.state
        """

        # Render Player's Position
        # pos_display = "Position: {}".format(self.player.position)
        # pos_pos = (self.terminal.size.x - len(pos_display), 0)
        # self.terminal.write(pos_display, pos_pos)

        # self.debug = True
        if self.debug:
            self.terminal.write(
                "Sc/when:  " + str(len(self.scene.script.when)) + "     ", 14)
            self.terminal.write(
                "S/when:  " + str(len(self.scene.when)) + "     ", 15)
            self.terminal.write(
                "SL:  " + str(len(self.scene.slotlist)) + "     ", 16)
            self.terminal.write("Res:  " + str(len(self.app.cache)) + "     ",
                                17)
            self.terminal.write(f"FPS low:  {self.scene.lowest_fps}    ", 18)
            self.terminal.write(f"Pmax:     {self.scene.max_particles}    ",
                                19)
            self.terminal.write(f"Entities: {len(self.scene.slots)}   ", 20)
            self.terminal.write(f"FPS:      {self.app.fps}    ", 21)

        self.scene.render(self.camera)
        self.gui.render(self.camera)

        assert self.scene.blocked == 0

    def build_inputs(self):
        pg = pygame

        pg.joystick.quit()  # Reload
        pg.joystick.init()
        for j in range(pg.joystick.get_count()):
            j = pg.joystick.Joystick(j)
            j.init()

        inputs = Inputs()
        inputs["hmove"] = Axis(
            (pg.K_LEFT, pg.K_a),
            (pg.K_RIGHT, pg.K_d),
            JoyAxis(0, 0),
        )
        inputs["vmove"] = Axis((pg.K_DOWN, pg.K_s), (pg.K_UP, pg.K_w),
                               JoyAxis(0, 1, True))
        inputs["fire"] = Button(
            pg.K_SPACE,
            pg.K_RETURN,
            JoyButton(0, 1),
            JoyButton(0, 0),
            JoyAxisTrigger(0, 2, 0),
            JoyAxisTrigger(0, 5, 0),
        )
        inputs["debug"] = Button(pg.K_TAB)
        inputs["switch-gun"] = Button(pg.K_RSHIFT, pg.K_LSHIFT,
                                      JoyButton(0, 3), JoyButton(0, 2))
        # inputs["test"] = Button(pg.K_p)
        inputs["pause"] = Button(pg.K_ESCAPE, JoyButton(0, 6), JoyButton(0, 7))
        return inputs

    def restart(self):
        """
        Called by player when() event after death
        """
        # clear terminal
        self.scene.clear_type(Enemy)
        self.scene.clear_type(Powerup)

        for x in range(2, 20):
            self.terminal.clear()
        self.level = self._level  # retriggers
Ejemplo n.º 15
0
from gui import Gui
from gui.widget.factory import Factory as WidgetFactory
from game.dispatcher import Dispatcher
from game.scene import Scene
from game.console import Console
from physics.position import Position

dispatcher = Dispatcher()
gui = Gui(dispatcher)

console = Console(dispatcher)
scene = Scene(dispatcher)
shape = (Position(0, 0),
         Position(1, 0),
         Position(0, -1))
player = scene.createPlayer(shape, Position(3, 3))
gui.addWidget(WidgetFactory.createChar(player, 'H'))

wallPathExtern = (Position(0, 0),
                    Position(80, 0),
                    Position(80, 15),
                    Position(12, 15),
                    Position(12, 10),
                    Position(0, 10),
                    Position(0, 0))
gui.addWidget(
  WidgetFactory.createChar(
    scene.createWall(
      wallPathExtern, Position(1, 1)), '#'))

wallPathIntern = (Position(40, 0),
Ejemplo n.º 16
0
class Intro(State):
    def __init__(self, app, state=None):

        super().__init__(app, state, self)

        self.scene = Scene(self.app, self)
        self.terminal = self.scene.add(Terminal(self.app, self.scene))
        self.bigterm = self.scene.add(Terminal(self.app, self.scene, 32))
        self.camera = self.scene.add(Camera(app, self.scene, self.app.size))
        self.scene.ground_color = "darkgreen"
        self.time = 0

        rows = 8
        backdrop_h = 150
        for i in range(rows):
            h = int(backdrop_h) // rows
            y = h * i
            backdrop = pygame.Surface((self.app.size.x, h))
            interp = i / rows
            interp_inv = 1 - i / rows
            backdrop.set_alpha(255 * interp_inv * 0.2)
            backdrop.fill(pg_color(ncolor("white") * interp_inv))
            self.scene.on_render += lambda _, y=y, backdrop=backdrop: self.app.screen.blit(
                backdrop, (0, y))

        rows = 8
        backdrop_h = 100
        for i in range(rows):
            h = int(backdrop_h) // rows
            y = h * i
            backdrop = pygame.Surface((self.app.size.x, h))
            interp = i / rows
            interp_inv = 1 - i / rows
            backdrop.set_alpha(255 * interp_inv * 0.1)
            backdrop.fill(pg_color(ncolor("white") * interp_inv))
            self.scene.on_render += lambda _, y=y, backdrop=backdrop: self.app.screen.blit(
                backdrop, (0, y))

        backdrop_h = int(24)
        rows = 4
        for i in range(rows, 0, -1):
            h = int(backdrop_h) // rows
            y = h * i
            backdrop = pygame.Surface((self.app.size.x, h))
            interp = i / rows
            interp_inv = 1 - i / rows
            backdrop.set_alpha(200 * interp_inv)
            backdrop.fill((0))
            # backdrop.fill(pg_color(ncolor('black')*interp_inv))
            self.scene.on_render += lambda _, y=y, backdrop=backdrop: self.app.screen.blit(
                backdrop, (0, self.app.size.y - y))

    def pend(self):

        self.app.pend()  # tell app we need to update

    def update(self, dt):
        """
        Called every frame by App as long as Game is the current app.state
        :param dt: time since last frame in seconds
        """

        super().update(dt)  # needed for script

        self.scene.update(dt)
        self.time += dt

    def render(self):

        self.scene.render(self.camera)

    def change_logo_color(self, script):
        yield
        bigterm = self.bigterm

        while True:
            if self.scene.ground_color:
                break
            yield
        c = glm.mix(
            self.scene.ground_color,
            glm.mix(ncolor("white"), random_rgb(), random.random()),
            0.2,
        )

        r = 0
        # rc = vec4()
        self.scene.play_sound("explosion.wav")
        while True:
            if r % 30 == 0:
                rc = random_rgb()
            s = "BUTTERFLY     "
            for i in range(len(s)):
                # c = ncolor('purple') * i/len(s) + math.sin(r / 200 + i+r) ** 2 + .6
                c = (ncolor("purple") * i / len(s) +
                     ((math.sin(i + r) + 0.4) * script.dt) + 0.3)
                bigterm.write(s[i], (i - len(s) - 8, 1), c)
            if r > 15:
                s = "DESTROYERS     "
                for i in range(len(s)):
                    c = (self.scene.ground_color * i / len(s) +
                         ((math.sin(i + r) + 4) * script.dt) + 0.3)
                    bigterm.write(s[i], (i - len(s) - 3, 2), c)
                if r == 15:
                    self.scene.play_sound("explosion.wav")
            yield script.sleep(0.1)
            r += 1

    def __call__(self, script):
        yield

        self.scene.scripts += self.change_logo_color

        when = script.when
        scene = self.scene
        terminal = self.terminal

        self.scene.music = "butterfly2.ogg"
        # self.scene.sky_color = "#4c0b6b"
        # self.scene.ground_color = "#e08041"
        # self.scene.stars()
        self.scene.cloudy()

        textdelay = 0.03

        fades = [
            when.fade(
                10,
                (0, 1),
                lambda t: scene.set_sky_color_opt(
                    glm.mix(ncolor("#4c0b6b"), ncolor("#e08041"), t)),
            ),
            when.fade(
                10,
                (0, 1),
                lambda t: scene.set_ground_color_opt(
                    glm.mix(ncolor("darkgreen"), ncolor("yellow"), t)),
                lambda: fades.append(
                    when.every(
                        0, lambda: scene.set_ground_color_opt(scene.
                                                              ground_color))),
            ),
        ]
        yield

        # self.scene.set_ground_color = "#e08041"

        # scene.sky_color = "black"
        self.scene.music = "butterfly2.ogg"

        # for i in range(len(msg)):
        #     terminal.write(msg[i], (len(msg) / 2 - 1 + i, 1), self.scene.ground_color)
        #     # scene.ensure_sound("type.wav")
        # yield script.sleep(0.002)

        # script.push(self.logo_color)

        # yield from self.change_logo_color(script)

        yield script.sleep(3)

        msg = [
            "In the year 20XX, the butterfly",
            "overpopulation problem has",
            "obviously reached critical mass.",
            "The military has decided to intervene.",
            "Your mission is simple: defeat all the",
            "butterflies before the world ends.",
            "But look out for Big Butta, king of",
            "the butterflies.",
        ]
        for y, line in enumerate(msg):
            ty = y * 2 + 5
            for x, m in enumerate(line):
                terminal.write(random_char(), (x + 2, ty), random_rgb())
                cursor = (x + 2, ty)
                terminal.write(m, (x + 1, ty), "white")
                # scene.ensure_sound("type.wav")
                self.change_logo_color(script)
                # if not script.keys_down:
                #     yield
                # else:
                yield script.sleep(textdelay)
            terminal.clear(cursor)

        when = script.when
        scene = self.scene
        terminal = self.terminal

        yield script.sleep(3)

        # while True:
        #     terminal.write_center("Press any key to continue", 20, "green")
        #     self.change_logo_color(script)
        #     yield script.sleep(0.1)
        #     if script.keys_down:
        #         break
        #     terminal.clear(20)
        #     self.change_logo_color(script)
        #     yield script.sleep(0.1)
        #     if script.keys_down:
        #         break

        terminal.clear()
        terminal.write_center("Loading...", 10)

        self.app.state = "game"