Esempio n. 1
0
class Ray(Control):
    scale = InterpDesc('_scale')
    alpha = InterpDesc('_alpha')

    def __init__(self, x0, y0, x1, y1, *args, **kwargs):
        Control.__init__(self, *args, **kwargs)
        from math import sqrt, atan2, pi
        self.x, self.y = x0, y0
        dx, dy = x1 - x0, y1 - y0
        scale = sqrt(dx*dx+dy*dy) / L('c-ray').width
        self.angle = atan2(dy, dx) / pi * 180
        self.scale = SineInterp(0.0, scale, 0.4)
        self.alpha = ChainInterp(
            FixedInterp(1.0, 1),
            CosineInterp(1.0, 0.0, 0.5),
            on_done=lambda self, desc: self.delete()
        )

    def draw(self):
        ray = L('c-ray')
        glPushMatrix()
        glRotatef(self.angle, 0., 0., 1.)
        glScalef(self.scale, 1., 1.)
        glTranslatef(0., -ray.height/2, 0.)
        glColor4f(1., 1., 1., self.alpha)
        ray.blit(0, 0)
        glPopMatrix()

    def hit_test(self, x, y):
        return False
Esempio n. 2
0
class SmallCardSprite(Control):
    width, height = 33, 46
    x = InterpDesc('_x')
    y = InterpDesc('_y')

    def __init__(self, card, x=0.0, y=0.0, *args, **kwargs):
        Control.__init__(self, *args, **kwargs)
        self._w, self._h = 33, 46
        self.x, self.y = x, y
        self.selected = False
        self.hover = False
        self.card = card

        self.img = L(card.ui_meta.image_small)
        self.balloon = balloon = BalloonPrompt(self)
        balloon.set_balloon(card.ui_meta.description)

    @staticmethod
    def batch_draw(csl):
        glPushMatrix()
        glLoadIdentity()
        vertices = []
        for cs in csl:
            ax, ay = cs.abs_coords()
            vertices += cs.img.get_t4f_v4f_vertices(ax, ay)

            s = cs.card.suit
            n = cs.card.number

            ssuit = L('thb-smallsuit')
            snum = L('thb-smallnum')

            if n == 10:  # special case
                # g[0].blit(1+g[0].vertices[0], 33+g[0].vertices[1])
                # g[1].blit(5+g[1].vertices[0], 33+g[1].vertices[1])
                vertices += snum[s % 2 * 14 + 10].get_t4f_v4f_vertices(ax - 1, ay + 31)
                vertices += snum[s % 2 * 14 + 0].get_t4f_v4f_vertices(ax + 3, ay + 31)
            else:
                vertices += snum[s % 2 * 14 + n].get_t4f_v4f_vertices(ax + 1, ay + 31)

            vertices += ssuit[s - 1].get_t4f_v4f_vertices(ax + 1, ay + 22)

            if cs.selected:
                vertices += L('thb-card-small-selected').get_t4f_v4f_vertices(ax, ay)
            else:
                vertices += L('thb-card-small-frame').get_t4f_v4f_vertices(ax, ay)

        n = len(vertices)
        buf = (GLfloat*n)()
        buf[:] = vertices
        glColor3f(1., 1., 1.)
        glPushClientAttrib(GL_CLIENT_VERTEX_ARRAY_BIT)
        glInterleavedArrays(GL_T4F_V4F, 0, buf)
        with get_atlas('card').texture:
            glDrawArrays(GL_QUADS, 0, n/8)

        glPopClientAttrib()
        glPopMatrix()
Esempio n. 3
0
class GirlSelector(ImageSelector):
    x = InterpDesc('_x')
    y = InterpDesc('_y')

    def __init__(self, choice, group, x=0, y=0, *a, **k):

        self.choice = choice
        cc = choice.char_cls
        meta = cc.ui_meta
        pimg = L(meta.port_image)

        self.x = x
        self.y = y
        ImageSelector.__init__(self, pimg, group, *a, **k)

        self.balloon.set_balloon(char_desc(cc))
Esempio n. 4
0
class GirlSelector(ImageSelector, BalloonPromptMixin):
    x = InterpDesc('_x')
    y = InterpDesc('_y')

    def __init__(self, choice, group, x=0, y=0, *a, **k):

        self.choice = choice
        cc = choice.char_cls
        meta = cc.ui_meta
        pimg = meta.port_image
        self.char_name = meta.char_name
        self.char_maxlife = cc.maxlife

        self.x = x
        self.y = y

        ImageSelector.__init__(self, pimg, group, *a, **k)

        self.init_balloon(meta.description)
Esempio n. 5
0
        class HighlightLayer(SensorLayer, BalloonPromptMixin):
            zindex = 0
            hl_alpha = InterpDesc('_hl_alpha')

            def __init__(self, *a, **k):
                SensorLayer.__init__(self, *a, **k)
                BalloonPromptMixin.__init__(self)
                from base.baseclasses import main_window
                self.window = main_window
                self.hand_cursor = self.window.get_system_mouse_cursor('hand')
                self.worldmap_shadow = common_res.worldmap_shadow.get()
                self.disable_click = False
                self.highlight = None
                self.hldraw = None
                self.hl_alpha = 0
                self.hlhit = False

            def on_mouse_motion(self, x, y, dx, dy):
                for s in ServerList.values():
                    if inpoly(x, y, s['polygon']):
                        self.hl_alpha = 1
                        if self.highlight is not s:
                            self.highlight = s
                            self.init_balloon(s['description'], polygon=s['polygon'])
                            x, y, w, h = s['box']
                            tex = self.worldmap_shadow.get_region(x, y, w, h)
                            self.hldraw = (x, y, tex)
                            self.window.set_mouse_cursor(self.hand_cursor)

                        break
                else:
                    if self.highlight:
                        self.highlight = None
                        self.hl_alpha = LinearInterp(1.0, 0, 0.3)
                        self.window.set_mouse_cursor(None)

                    self.init_balloon('', (0, 0, 0, 0))

            def on_mouse_release(self, x, y, button, modifiers):
                if self.highlight and not self.disable_click:
                    self.disable_click = True
                    screen.do_connect(self.highlight['address'])

            def enable_click(self):
                self.disable_click = False

            def draw(self):
                hla = self.hl_alpha
                if hla and not self.disable_click:
                    x, y, tex = self.hldraw
                    glColor4f(1, 1, 1, hla)
                    tex.blit(x, y)
Esempio n. 6
0
class CardSprite(Control):
    x                = InterpDesc('_x')
    y                = InterpDesc('_y')
    back_scale       = InterpDesc('_bs')
    question_scale   = InterpDesc('_qs')
    ftanim_alpha     = InterpDesc('_fta')
    ftanim_cardalpha = InterpDesc('_ftca')
    shine_alpha      = InterpDesc('_shine_alpha')
    alpha            = InterpDesc('_alpha')
    width, height    = 91, 125

    def __init__(self, card, x=0.0, y=0.0, *args, **kwargs):
        Control.__init__(self, *args, **kwargs)

        self._w, self._h = 91, 125
        self.shine = False
        self.gray = False
        self.x, self.y = x, y
        self.shine_alpha = 0.0
        self.selected = False
        self.alpha = 1.0
        self.card = card

        self.ft_anim = False
        self.balloon = BalloonPrompt(self)

        self.update()

    @staticmethod
    def batch_draw(csl):
        glPushMatrix()
        glLoadIdentity()

        vertices = []
        for cs in csl:
            ax, ay = cs.abs_coords()
            if cs.ft_anim:
                qs = cs.question_scale
                bs = cs.back_scale
                aa = cs.ftanim_alpha
                ca = cs.ftanim_cardalpha
                if cs.gray:
                    c = (.66, .66, .66, ca)
                else:
                    c = (1., 1., 1., ca)
                vertices += cs.img.get_t2c4n3v3_vertices(c, ax, ay)

                n, s = cs.number, cs.suit
                if n: vertices += L('thb-cardnum')[s % 2 * 13 + n - 1].get_t2c4n3v3_vertices(c, ax + 5, ay + 105)
                if s: vertices += L('thb-suit')[s - 1].get_t2c4n3v3_vertices(c, ax + 6, ay + 94)

                c = (1, 1, 1, aa)

                if qs:
                    vertices += L('thb-card-question').get_t2c4n3v3_vertices(c, ax+(1-qs)*45, ay, 0, qs*91)

                if bs:
                    vertices += L('thb-card-hidden').get_t2c4n3v3_vertices(c, ax+(1-bs)*45, ay, 0, bs*91)
            else:
                a = cs.alpha
                if cs.gray:
                    c = (.66, .66, .66, a)
                else:
                    c = (1., 1., 1., a)
                vertices += cs.img.get_t2c4n3v3_vertices(c, ax, ay)
                resides_in = cs.card.resides_in
                if resides_in and resides_in.type == 'showncards':
                    vertices += L('thb-card-showncardtag').get_t2c4n3v3_vertices(c, ax, ay)

                n, s = cs.number, cs.suit
                if n: vertices += L('thb-cardnum')[s % 2 * 13 + n - 1].get_t2c4n3v3_vertices(c, ax + 5, ay + 105)
                if s: vertices += L('thb-suit')[s-1].get_t2c4n3v3_vertices(c, ax+6, ay+94)

                if cs.selected:
                    c = (0., 0., 2., 1.0)
                else:
                    c = (1., 1., 1., cs.shine_alpha)

                vertices += L('thb-card-shinesoft').get_t2c4n3v3_vertices(c, ax-6, ay-6)

        if vertices:
            n = len(vertices)
            buf = (GLfloat*n)()
            buf[:] = vertices
            glPushClientAttrib(GL_CLIENT_VERTEX_ARRAY_BIT)
            glInterleavedArrays(GL_T2F_C4F_N3F_V3F, 0, buf)
            with get_atlas('card').texture:
                glDrawArrays(GL_QUADS, 0, n/12)
            glPopClientAttrib()

        glPopMatrix()

    def update(self):
        card = self.card
        meta = card.ui_meta

        self.img = L(meta.image)

        self.number, self.suit = card.number, card.suit

        t = getattr(meta, 'description', None)
        t and self.balloon.set_balloon(t)

    def on_mouse_enter(self, x, y):
        self.shine_alpha = 1.0

    def on_mouse_leave(self, x, y):
        self.shine_alpha = SineInterp(1.0, 0.0, 0.3)

    def do_fatetell_anim(self):
        self.ft_anim = True
        self.question_scale = ChainInterp(
            SineInterp(0.0, 1.0, 0.1),
            CosineInterp(1.0, 0.0, 0.1),
            FixedInterp(0.0, 0.2),
            SineInterp(0.0, 1.0, 0.1),
            CosineInterp(1.0, 0.0, 0.1),
            FixedInterp(0.0, 0.2),
            SineInterp(0.0, 1.0, 0.1)
        )
        self.back_scale = ChainInterp(
            FixedInterp(0.0, 0.2),
            SineInterp(0.0, 1.0, 0.1),
            CosineInterp(1.0, 0.0, 0.1),
            FixedInterp(0.0, 0.2),
            SineInterp(0.0, 1.0, 0.1),
            CosineInterp(1.0, 0.0, 0.1),
        )
        self.ftanim_alpha = ChainInterp(
            FixedInterp(1.0, 1.0),
            LinearInterp(1.0, 0.0, 2.0),
            on_done=self._end_ft_anim,
        )
        self.ftanim_cardalpha = ChainInterp(
            FixedInterp(0.0, 1.0),
            FixedInterp(1.0, 0.0),
        )

    def _end_ft_anim(self, _self, desc):
        self.ft_anim = False
Esempio n. 7
0
class GameScreen(Screen):
    flash_alpha = InterpDesc('_flash_alpha')

    class InvitePanel(Panel):
        def __init__(self, game_id, *a, **k):
            Panel.__init__(
                self, width=550, height=340,
                zindex=10000,
                *a, **k
            )
            self.game_id = game_id
            self.x = (self.overlay.width - 550) // 2
            self.y = (self.overlay.height - 340) // 2

            self.btncancel = btncancel = Button(
                u'关闭', parent=self, x=440, y=25, width=90, height=40
            )

            self.labels = pyglet.graphics.Batch()

            Label(
                u'邀请游戏', font_size=12, x=275, y=306,
                anchor_x='center', anchor_y='bottom',
                color=Colors.green.heavy + (255, ),
                shadow=(2, 207, 240, 156, 204),
                batch=self.labels,
            )

            @btncancel.event
            def on_click():
                self.delete()

            Executive.call('get_hallinfo', ui_message, None)

        def draw(self):
            Panel.draw(self)
            self.labels.draw()

        def on_message(self, _type, *args):
            if _type == 'current_users':
                ul = args[0]
                ul = [(uid, uname) for uid, uname, state in ul if state in ('hang', 'observing')]

                for i, (uid, uname) in enumerate(ul):
                    y, x = divmod(i, 5)
                    x, y = 30 + 100*x, 250 - 60*y
                    s = Button(
                        uname,
                        color=Colors.orange,
                        parent=self, x=x, y=y,
                        width=95, height=30,
                    )

                    @s.event
                    def on_click(s=s, uid=uid, un=uname):
                        Executive.call('invite_user', ui_message, uid)
                        self.overlay.chat_box.append(u'|R已经邀请了%s,请等待回应……|r\n' % un)
                        s.state = Button.DISABLED

    class RoomControlPanel(Control):
        def __init__(self, parent=None):
            Control.__init__(self, parent=parent, **r2d((0, 0, 820, 720)))
            self.btn_getready = Button(
                parent=self, caption=u'准备', **r2d((360, 80, 100, 35))
            )

            self.btn_invite = Button(
                parent=self, caption=u'邀请', **r2d((360, 40, 100, 35))
            )

            self.ready = False

            l = []

            class MyPP(PlayerPortrait):
                # this class is INTENTIONALLY put here
                # to make cached avatars get gc'd
                cached_avatar = {}

            for x, y, color in parent.ui_class.portrait_location:
                l.append(MyPP('NONAME', parent=self, x=x, y=y, color=color))
            self.portraits = l

            @self.btn_getready.event
            def on_click():
                if self.ready:
                    Executive.call('cancel_ready', ui_message, [])
                    self.ready = False
                    self.btn_getready.caption = u'准备'
                    self.btn_getready.update()
                else:
                    Executive.call('get_ready', ui_message, [])
                    #self.btn_getready.state = Button.DISABLED
                    self.ready = True
                    self.btn_getready.caption = u'取消准备'
                    self.btn_getready.update()

            @self.btn_invite.event  # noqa
            def on_click():
                GameScreen.InvitePanel(self.parent.game.gameid, parent=self)

        def draw(self):
            self.draw_subcontrols()

        def on_message(self, _type, *args):
            if _type == 'player_change':
                self.update_portrait(args[0])
            elif _type == 'kick_request':
                u1, u2, count = args[0]
                self.parent.chat_box.append(
                    u'|B|R>> |c0000ffff%s|r希望|c0000ffff|B%s|r离开游戏,已有%d人请求\n' % (
                        u1[1], u2[1], count
                    )
                )
            elif _type == 'game_joined':
                self.ready = False
                self.btn_getready.caption = u'准备'
                self.btn_getready.state = Button.NORMAL

        def update_portrait(self, pl):
            def players():
                return {
                    p.account.username
                    for p in self.portraits
                    if p.account
                }

            orig_players = players()
            full = True

            for i, p in enumerate(pl):
                accdata = p['account']
                acc = Account.parse(accdata) if accdata else None
                if not accdata: full = False

                port = self.portraits[i]
                port.account = acc
                port.ready = (p['state'] == 'ready')

                port.update()

            curr_players = players()

            for player in (orig_players - curr_players):
                self.parent.chat_box.append(
                    u'|B|R>> |r玩家|c0000ffff|B%s|r已离开游戏\n' % player
                )

            for player in (curr_players - orig_players):
                self.parent.chat_box.append(
                    u'|B|R>> |r玩家|c0000ffff|B%s|r已进入游戏\n' % player
                )

            if not self.ready and full and orig_players != curr_players:
                from utils import notify
                notify(u'东方符斗祭 - 满员提醒', u'房间已满员,请准备。')

    class EventsBox(Frame):
        def __init__(self, parent):
            Frame.__init__(
                self, parent=parent,
                caption=u'游戏信息',
                x=820, y=350, width=204, height=370,
                bot_reserve=0, bg=common_res.bg_eventsbox.get(),
            )
            self.box = TextArea(
                parent=self, x=2, y=2, width=200, height=370-24-2
            )

        def append(self, v):
            self.box.append(v)

        def clear(self):
            self.box.text = u'\u200b'

    class ChatBox(ChatBoxFrame):
        def __init__(self, parent):
            ChatBoxFrame.__init__(
                self, parent=parent,
                x=820, y=0, width=204, height=352,
                bg=common_res.bg_chatbox.get(),
            )

    def __init__(self, game, *args, **kwargs):
        Screen.__init__(self, *args, **kwargs)

        self.backdrop = common_res.bg_ingame.get()
        self.flash_alpha = 0.0

        self.game = game
        self.ui_class = game.ui_meta.ui_class
        self.gameui = self.ui_class(
            parent=False, game=game,
            **r2d((0, 0, 820, 720))
        )  # add when game starts

        self.events_box = GameScreen.EventsBox(parent=self)
        self.chat_box = GameScreen.ChatBox(parent=self)
        self.panel = GameScreen.RoomControlPanel(parent=self)
        self.btn_exit = Button(
            parent=self, caption=u'退出房间', zindex=1,
            **r2d((730, 670, 75, 25))
        )

        VolumeTuner(parent=self, x=690, y=665)

        @self.btn_exit.event
        def on_click():
            box = ConfirmBox(u'真的要离开吗?', buttons=ConfirmBox.Presets.OKCancel, parent=self)

            @box.event
            def on_confirm(val):
                if val:
                    Executive.call('exit_game', ui_message, [])

    def on_message(self, _type, *args):
        rst = handle_chat(_type, args)
        if rst:
            self.chat_box.append(rst)
            return

        elif _type == 'game_started':
            from utils import notify
            notify(u'东方符斗祭 - 游戏提醒', u'游戏已开始,请注意。')
            self.remove_control(self.panel)
            self.add_control(self.gameui)
            self.gameui.init()
            self.game.start()

        elif _type == 'end_game':
            self.remove_control(self.gameui)
            self.add_control(self.panel)
            g = args[0]

        elif _type == 'client_game_finished':
            g = args[0]
            g.ui_meta.ui_class.show_result(g)

        elif _type in ('game_left', 'fleed'):
            GameHallScreen().switch()

        elif _type == 'game_joined':
            # last game ended, this is the auto
            # created game
            self.game = args[0]
            self.panel.btn_getready.state = Button.NORMAL
            self.gameui = self.ui_class(
                parent=False, game=self.game,
                **r2d((0, 0, 820, 720))
            )
            SoundManager.switch_bgm(common_res.bgm_hall)
            self.backdrop = common_res.bg_ingame.get()
            self.set_color(Colors.green)
            self.events_box.clear()

        elif _type == 'game_crashed':
            ConfirmBox(
                u'游戏逻辑已经崩溃,请退出房间!\n'
                u'这是不正常的状态,你可以报告bug。\n'
                u'游戏ID:%d' % self.game.gameid,
                parent=self
            )
            from __main__ import do_crashreport
            do_crashreport()

        elif _type == 'observe_request':
            uid, uname = args[0]
            box = ConfirmBox(
                u'玩家 %s 希望旁观你的游戏,是否允许?\n'
                u'旁观玩家可以看到你的手牌。' % uname,
                parent=self, buttons=((u'允许', True), (u'不允许', False)), default=False
            )

            @box.event
            def on_confirm(val, uid=uid):
                Executive.call('observe_grant', ui_message, [uid, val])

        elif _type == 'observer_enter':
            obuid, obname, uname = args[0]
            self.chat_box.append(
                u'|B|R>> |r|c0000ffff%s|r[|c9100ffff%d|r]|r趴在了|c0000ffff%s|r身后\n' % (obname, obuid, uname)
            )

        elif _type == 'observer_leave':
            obuid, obname, uname = args[0]
            self.chat_box.append(
                u'|B|R>> |r|c0000ffff%s|r飘走了\n' % obname
            )

        else:
            Screen.on_message(self, _type, *args)

    def draw(self):
        glColor3f(1, 1, 1)
        self.backdrop.blit(0, 0)
        glColor4f(0, 0, 0, .5)
        glRectf(0, 0, 1000, 138)
        glColor3f(0.1922, 0.2706, 0.3882)
        glRectf(0, 138, 1000, 140)
        glColor3f(1, 1, 1)
        self.draw_subcontrols()
        fa = self.flash_alpha
        if fa:
            glColor4f(1, 1, 1, fa)
            glRectf(0, 0, WINDOW_WIDTH, WINDOW_HEIGHT)

    def set_flash(self, duration):
        self.flash_alpha = CosineInterp(1.0, 0.0, duration)

    def set_color(self, color):
        self.events_box.set_color(color)
        self.chat_box.set_color(color)

    def on_switch(self):
        SoundManager.switch_bgm(common_res.bgm_hall)