Exemple #1
0
class Outro(State):
    def __init__(self):
        State.__init__(self)
        self.fps = 40

        #animation checkpoints and flags
        self.opening = 0
        self.closing = 0
        self.door_timer = Timer(15)  #open slowly, then faster
        self.maelstrom_timer = Timer(30)  #open doors a bit.. then pull
        self.nanji_command = None

        #generate pseudo-map
        screen_size = GLOBALS["screen_size"]
        self.bg_image = pygame.Surface(screen_size)
        self.top_layer = pygame.Surface(screen_size)
        self.top_layer.set_colorkey((255, 0, 255))
        self.top_layer.fill((255, 0, 255))

        #draw map background
        bg = GLOBALS["backgrounds"]["fuji.png"]
        self.bg_image.blit(bg, (0, 0))

        #draw grass
        tsize = GLOBALS["tile_size"]
        grass_tile = GLOBALS["ts_tileset"][1, 0]
        x = -tsize
        y = screen_size[1] - tsize
        for i in xrange(22):
            self.top_layer.blit(grass_tile, (x, y))
            x += tsize

        #draw mysterious
        myst = GLOBALS["ui_stuff"]["mysterious.png"]

        #draw full signet board on mysterious
        board = GLOBALS["ui_stuff"]["board_filled.png"]
        x, y = 66, 197
        myst.blit(board, (x, y))

        x = 5 * tsize
        y = screen_size[1] - myst.get_size()[1] - tsize
        self.myst = StaticWidget(myst.get_size())
        self.myst.set_colorkey((255, 0, 255))
        self.myst.fill((255, 0, 255))
        self.myst.blit(myst, (0, 0))
        self.myst.set_pos((x, y))
        self.myst.pos = (x, y)
        self.myst.draw(self.top_layer)
        myst_centerx = x + myst.get_size()[0] / 2
        myst_top = y + 30

        #init doors
        self.door_speed = 1
        door_left_image = GLOBALS["ui_stuff"]["door_left.png"]
        door_right_image = GLOBALS["ui_stuff"]["door_right.png"]
        self.door_left = StaticWidget(door_left_image.get_size())
        self.door_left.blit(door_left_image, (0, 0))
        self.door_left.set_pos((self.myst.pos[0] + 99, self.myst.pos[1] + 63))
        self.door_right = StaticWidget(door_right_image.get_size())
        self.door_right.blit(door_right_image, (0, 0))
        self.door_right.set_pos(
            (self.myst.pos[0] + 177, self.myst.pos[1] + 63))

        #init whirling vortex
        self.vortex = Vortex(centerpos=(myst_centerx, myst_top))

        #init Nanji
        self.nanji = Nanji(cam=None)
        self.nanji.status = 0
        self.nanji.set_pos((205, 401))
        self.nanji_angle = 0
        self.nanji_fly_img = self.nanji.all_images["landing"][0]
        self.nanji_shrink = 1
        self.sprites.add(self.nanji)

        self.nanji_do("throw")

    def main_start(self):
        pygame.mouse.set_visible(0)
        State.main_start(self)

    def update_doors(self):
        if self.opening:
            lx, ly = self.door_left.get_pos()
            rx, ry = self.door_right.get_pos()
            self.door_left.set_pos((lx - self.door_speed, ly))
            self.door_right.set_pos((rx + self.door_speed, ry))
            if self.door_timer.update():
                self.door_speed = 2
            self.opening = lx > 165
        elif self.closing:
            self.door_speed = 1
            lx, ly = self.door_left.get_pos()
            rx, ry = self.door_right.get_pos()
            self.door_left.set_pos((lx + 1, ly))
            self.door_right.set_pos((rx - 1, ry))
            self.closing = lx < 258
            if not self.closing:
                self.maelstrom_timer.set_interval(50)
                self.nanji_do("waitquit")

        self.door_left.draw(self.background)
        self.door_right.draw(self.background)

    def nanji_do(self, do="throw"):
        self.nanji_command = do

        if do == "throw":  #lift paw
            self.nanji.change_images("throwing")
            self.nanji.anim_timer.set_interval(5)
            self.nanji.play()
        elif do == "unthrow":  #put paw down
            images = self.nanji.images[:]
            images.reverse()
            self.nanji.set_images(images)
            self.nanji.play()
        elif do == "wait_door":
            self.nanji.change_images("idle")
            self.opening = 1
            self.nanji.pause()
        elif do == "walk" or do == "walk2":
            self.nanji.look = -1
            self.nanji.change_images("walking")
            self.nanji.anim_timer.set_interval(8)
            self.nanji.play()
        elif do == "sprint" or do == "sprint2":
            self.nanji.change_images("sprinting")
            self.nanji.anim_timer.set_interval(8)
            self.nanji.play()
        elif do == "duck":
            self.nanji.change_images("ducking")
            self.nanji.pause()
        elif do == "lift":
            self.nanji.change_images("landing")
            self.nanji.pause()

    def update_nanji(self):
        if self.nanji_command is None:
            return

        #update old command
        cmd = self.nanji_command
        x, y = self.nanji.pos  #get pulled
        if cmd == "throw" and self.nanji.cur_image >= 3:  #paw up
            self.nanji_do("unthrow")
        elif cmd == "unthrow" and self.nanji.cur_image >= 3:  #paw down
            self.nanji_do("wait_door")
        elif cmd == "wait_door" and self.maelstrom_timer.update():  #wait
            self.nanji_do("walk")
        elif cmd == "walk":
            if x > 150:  #walk left
                self.nanji.set_pos((x - 1, y))
            else:
                self.nanji_do("walk2")
        elif cmd == "walk2":
            if x < 190:
                self.nanji.set_pos((x + 1, y))
            else:
                self.nanji_do("sprint")
        elif cmd == "sprint":  #try to sprint
            if x > 170:
                self.nanji.set_pos((x - 1, y))
            else:
                self.nanji_do("sprint2")
        elif cmd == "sprint2":
            self.nanji.set_pos((x + 1, y))
            if self.maelstrom_timer.update():
                self.nanji_do("duck")
        elif cmd == "duck" and self.maelstrom_timer.update():
            self.nanji_do("duckpull")
        elif cmd == "duckpull":
            if x < 250:
                self.nanji.set_pos((x + 1, y))
            else:
                self.nanji_do("lift")
        elif cmd == "lift":
            if x < 280:
                self.nanji.set_pos((x + 1, y))
            else:
                self.nanji_do("liftoff")
                self.maelstrom_timer.set_interval(10)
        elif cmd == "liftoff":
            self.nanji.set_pos((x, y - 1))
            if self.maelstrom_timer.update():
                self.nanji_do("whirl")
        elif cmd == "whirl":
            img = self.nanji_fly_img.copy()
            sx, sy = img.get_size()
            img = pygame.transform.scale(
                img, (sx - self.nanji_shrink, sy - self.nanji_shrink))
            self.nanji_shrink += 1
            if sx - self.nanji_shrink < 0 or sy - self.nanji_shrink < 0:
                self.nanji_do("done")

            self.nanji_angle += 10
            if self.nanji_angle > 360:
                self.nanji_angle = self.nanji_angle - 360
            img = pygame.transform.rotate(img, self.nanji_angle)

            center = self.nanji.rect.center
            self.nanji.set_image(img)
            self.nanji.rect.center = center

            if y > 350:
                y -= 1
            if x < 350:
                x += 1
            self.nanji.set_pos((x, y))
        elif cmd == "done":
            self.nanji_do(None)
            self.closing = 1
        elif cmd == "waitquit" and self.maelstrom_timer.update():
            self.next = TheEnd()
            self.quit()

    def update_screen(self):
        self.background.blit(self.bg_image, (0, 0))

        #update and draw vortex
        self.vortex.update()
        self.background.blit(self.vortex.image, self.vortex.pos)

        #update and draw doors
        self.update_doors()

        #draw grass, building
        self.background.blit(self.top_layer, (0, 0))

        #draw nanji
        self.update_nanji()
        State.update_screen(self)
class LevelSelection(State):
    def __init__(self, new=True):
        State.__init__(self)
        self.success = False
        self.new = new  #start tutorial before showing level selection!

        self.signet_pos = {
            "wood": (83, 181),
            "day": (158, 75),
            "fire": (284, 34),
            "life": (410, 75),
            "earth": (485, 181),
            "night": (456, 307),
            "metal": (348, 368),
            "water": (220, 368),
            "death": (112, 307)
        }

        self.light_pos = {
            "wood": (239, 225),
            "day": (261, 173),
            "fire": (315, 155),
            "life": (369, 173),
            "earth": (391, 225),
            "night": (383, 271),
            "metal": (345, 307),
            "water": (285, 307),
            "death": (247, 271)
        }

        self.cur_blinking = None
        self.cur_blending = None
        self.cur_clan = None
        self.blink_timer = Timer(50)
        self.blink_count = 0
        self.blink_max = 10
        self.light = GLOBALS["ui_stuff"]["green_light"]

        r = pygame.Rect([281, 203, 78, 77])
        r.inflate(-10, -10)
        bigredbutton = ClickArea(r, self.bigred_pressed)
        self.widgets.append(bigredbutton)
        self.donotpress = pygame.Rect([267, 188, 106, 95])
        self.signets = GLOBALS["signets"]
        self.bg_image = GLOBALS["backgrounds"]["gameboard.png"].copy()
        self.ui_layer = pygame.Surface(GLOBALS["screen_size"])
        self.ui_layer.fill((255, 0, 255))
        self.ui_layer.set_colorkey((255, 0, 255))

        self.tooltip_layer = pygame.Surface(GLOBALS["screen_size"])
        self.tooltip_layer.fill((255, 0, 255))
        self.tooltip_layer.set_colorkey((255, 0, 255))
        self.tooltip = StaticWidget((80, 20))
        self.dnp_tooltip = GLOBALS["ui_stuff"]["donotpress"]

        #level selection buttons
        self.signet_buttons = []
        levels = GLOBALS["clan_levels"]
        for k in self.signet_pos.keys():
            if self.signets.has_key(k) and levels.has_key(k):
                btn = ImgButton(self.signets[k][0], self.start_level, \
                    clan=k, level=levels[k])
                btn.set_pos(self.signet_pos[k])
                btn.rect = pygame.Rect([self.signet_pos[k], btn.get_size()])
                btn.rect.inflate(-20, -20)
                btn.clan = k
                self.widgets.append(btn)
                self.signet_buttons.append(btn)

        #show savegame progress
        self.show_signet(player_data["unlocked"])

        #keyboard events
        self.add_kbevent(KEYDOWN, K_ESCAPE, self.quit)

        self.background.blit(self.bg_image, (0, 0))
        self.background.blit(self.tooltip_layer, (0, 0))
        self.background.blit(self.ui_layer, (0, 0))
        self.tooltip_layer.fill((255, 0, 255))

    def main_start(self):
        if pygame.mixer.music.get_busy():
            pygame.mixer.music.fadeout(300)

        pygame.mouse.set_visible(1)
        if self.new is True:
            self.new = "somewhere in between"
            self.cur_clan = None
            self.next = Level("tutorial.map", prev=self)
            self.pause()
            self.quit()
        elif self.new == "somewhere in between":
            self.new = False
            self.update_screen()
            self.next = ShowDialog("donotpress", self.screen)
            self.pause()
            self.quit()

    def start_level(self, clan, level):
        if clan in player_data[
                "unlocked"] or self.cur_blending or self.cur_blinking:
            #do not start finished maps and wait while blending new signet in
            return
        self.success = False
        self.cur_clan = clan
        self.next = Level(level, prev=self)
        self.pause()
        self.quit()

    def unpause(self):
        if self.success:
            if self.cur_clan:
                self.show_signet([self.cur_clan])
                player_data["unlocked"].append(self.cur_clan)  #track progress
            self.cur_clan = None
            self.autosave()  #save progress
        State.unpause(self)

    def autosave(self):
        try:
            save_object(player_data, "save.dat")
        except:
            print "Autosave failed. Uh.. guess you need to keep playing?"

    def show_signet(self, clans):
        #show recently gained signet(s)
        self.cur_blending = []
        self.cur_blinking = []
        for clan in clans:
            #signet
            signet = self.signets[clan][0]
            blend = StaticWidget(signet.get_size())
            blend.fill((255, 0, 255))
            blend.set_colorkey((255, 0, 255))
            blend.blit(signet, (0, 0))
            blend.set_pos(self.signet_pos[clan])
            blend.set_alpha(0)
            self.cur_blending.append(blend)

            #green light
            img = self.light
            blink = StaticWidget(img.get_size())
            blink.fill((255, 0, 255))
            blink.set_colorkey((255, 0, 255))
            blink.blit(img, (0, 0))
            blink.set_pos(self.light_pos[clan])
            self.cur_blinking.append(blink)
            self.blink_timer.set_interval(3)

    def update_other(self):
        if self.cur_blending:
            #fancy alpha blending effect for new signet
            alpha = self.cur_blending[0].get_alpha() + 5

            if alpha > 100:  #stop blending
                for blend in self.cur_blending:
                    blend.set_alpha(None)
                    blend.draw(self.bg_image)
                self.cur_blending = None
            else:  #keep blending
                for blend in self.cur_blending:
                    blend.set_alpha(alpha)
                    blend.draw(self.bg_image)

        elif self.cur_blinking:
            if not self.blink_timer.update():
                return

            #fancy blinking light o/
            self.blink_count += 1
            b = self.blink_count

            #simulate irregular flickering
            if b == 1:
                self.blink_timer.set_interval(2)
            elif b == 3:
                self.blink_timer.set_interval(3)
            elif b == 6:
                self.blink_timer.set_interval(1)

            #to draw or not to draw...
            if self.blink_count % 2:
                for blink in self.cur_blinking:
                    blink.draw(self.ui_layer)
            else:
                self.ui_layer.fill((255, 0, 255))

            #ok, stop flickering.
            if self.blink_count > self.blink_max:
                for blink in self.cur_blinking:
                    blink.draw(self.bg_image)
                self.ui_layer.fill((255, 0, 255))
                self.blink_count = 0
                self.cur_blinking = None
        else:
            self.check_mouseover()

    def check_mouseover(self):
        #check if mouse hovers signet and show tooltip
        mpos = pygame.mouse.get_pos()
        for b in self.signet_buttons:
            if b.rect.collidepoint(mpos):
                self.tooltip.fill((255, 255, 255))
                self.tooltip.draw_border((0, 0, 0))
                self.tooltip.blit(GLOBALS["kanji"]["clan"], (10, 3))
                self.tooltip.blit(GLOBALS["kanji"][b.clan], (60, 4))
                pos = (mpos[0] + 10, mpos[1] + 20)
                x = (b.rect.centerx - self.tooltip.get_size()[0] / 2)
                y = b.rect.top
                pos = (x, y)
                self.tooltip_layer.blit(self.tooltip, pos)
                break

        dnp = self.donotpress
        if dnp.collidepoint(mpos):
            pos = (dnp.left - 60, dnp.top - 22)
            self.tooltip_layer.blit(self.dnp_tooltip, pos)

    def bigred_pressed(self):
        if self.cur_blending or self.cur_blinking:
            return

        if len(player_data["unlocked"]) < 9:
            self.next = ShowDialog("nothinghappened", self.screen)
            self.pause()
            self.quit()
        else:
            self.next = Outro()
            self.quit()

    def update_screen(self):
        self.background.blit(self.bg_image, (0, 0))
        self.background.blit(self.tooltip_layer, (0, 0))
        self.background.blit(self.ui_layer, (0, 0))
        self.tooltip_layer.fill((255, 0, 255))
        State.update_screen(self)