Example #1
0
    def on_transition_in(self) -> None:
        from bastd.actor.controlsguide import ControlsGuide
        from ba import DualTeamSession
        super().on_transition_in()
        ControlsGuide(delay=1.0).autoretain()

        session = self.session
        assert isinstance(session, ba.MultiTeamSession)

        # Show info about the next up game.
        self._next_up_text = Text(ba.Lstr(
            value='${1} ${2}',
            subs=[('${1}', ba.Lstr(resource='upFirstText')),
                  ('${2}', session.get_next_game_description())]),
                                  h_attach=Text.HAttach.CENTER,
                                  scale=0.7,
                                  v_attach=Text.VAttach.TOP,
                                  h_align=Text.HAlign.CENTER,
                                  position=(0, -70),
                                  flash=False,
                                  color=(0.5, 0.5, 0.5, 1.0),
                                  transition=Text.Transition.FADE_IN,
                                  transition_delay=5.0)

        # In teams mode, show our two team names.
        # FIXME: Lobby should handle this.
        if isinstance(ba.getsession(), DualTeamSession):
            team_names = [team.name for team in ba.getsession().sessionteams]
            team_colors = [
                tuple(team.color) + (0.5, )
                for team in ba.getsession().sessionteams
            ]
            if len(team_names) == 2:
                for i in range(2):
                    Text(team_names[i],
                         scale=0.7,
                         h_attach=Text.HAttach.CENTER,
                         v_attach=Text.VAttach.TOP,
                         h_align=Text.HAlign.CENTER,
                         position=(-200 + 350 * i, -100),
                         color=team_colors[i],
                         transition=Text.Transition.FADE_IN).autoretain()

        Text(ba.Lstr(resource='mustInviteFriendsText',
                     subs=[('${GATHER}',
                            ba.Lstr(resource='gatherWindow.titleText'))]),
             h_attach=Text.HAttach.CENTER,
             scale=0.8,
             host_only=True,
             v_attach=Text.VAttach.CENTER,
             h_align=Text.HAlign.CENTER,
             position=(0, 0),
             flash=False,
             color=(0, 1, 0, 1.0),
             transition=Text.Transition.FADE_IN,
             transition_delay=2.0,
             transition_out_delay=7.0).autoretain()
Example #2
0
    def _get_context(self, player: ba.Player) -> Tuple[bool, float, Dict]:
        """Return info on where we should be shown and stored."""
        activity = ba.getactivity()

        if isinstance(ba.getsession(), ba.DualTeamSession):
            on_right = player.team.id % 2 == 1

            # Store a list of icons in the team.
            icons = player.team.gamedata.get('_spaz_respawn_icons')
            if icons is None:
                player.team.gamedata['_spaz_respawn_icons'] = icons = {}
            assert isinstance(icons, dict)

            offs_extra = -20
        else:
            on_right = False

            # Store a list of icons in the activity.
            icons = activity.gamedata.get('_spaz_respawn_icons')
            if icons is None:
                activity.gamedata['_spaz_respawn_icons'] = icons = {}
            assert isinstance(icons, dict)

            if isinstance(activity.session, ba.FreeForAllSession):
                offs_extra = -150
            else:
                offs_extra = -20
        return on_right, offs_extra, icons
    def __init__(self, label: ba.Lstr = None, score_split: float = 0.7):
        """Instantiate a scoreboard.

        Label can be something like 'points' and will
        show up on boards if provided.
        """
        self._flat_tex = ba.gettexture('null')
        self._entries: Dict[int, _Entry] = {}
        self._label = label
        self.score_split = score_split

        # For free-for-all we go simpler since we have one per player.
        self._pos: Sequence[float]
        if isinstance(ba.getsession(), ba.FreeForAllSession):
            self._do_cover = False
            self._spacing = 35.0
            self._pos = (17.0, -65.0)
            self._scale = 0.8
            self._flash_length = 0.5
        else:
            self._do_cover = True
            self._spacing = 50.0
            self._pos = (20.0, -70.0)
            self._scale = 1.0
            self._flash_length = 1.0
Example #4
0
    def _get_context(self, player: ba.Player) -> Tuple[bool, float, Dict]:
        """Return info on where we should be shown and stored."""
        activity = ba.getactivity()
        if isinstance(ba.getsession(), ba.DualTeamSession):
            on_right = player.team.get_id() % 2 == 1

            # Store a list of icons in the team.
            try:
                respawn_icons = (
                    player.team.gamedata['_spaz_respawn_icons_right'])
            except Exception:
                respawn_icons = (
                    player.team.gamedata['_spaz_respawn_icons_right']) = {}
            offs_extra = -20
        else:
            on_right = False

            # Store a list of icons in the activity.
            # FIXME: Need an elegant way to store our shared stuff with
            # the activity.
            try:
                respawn_icons = activity.spaz_respawn_icons_right
            except Exception:
                respawn_icons = activity.spaz_respawn_icons_right = {}
            if isinstance(activity.session, ba.FreeForAllSession):
                offs_extra = -150
            else:
                offs_extra = -20
        return on_right, offs_extra, respawn_icons
Example #5
0
    def __init__(self, settings: Dict[str, Any]):
        super().__init__(settings)
        session = ba.getsession()

        # Let's show a list of scores-to-beat for 1 player at least.
        assert session.campaign is not None
        level_name_full = (session.campaign.name + ':' +
                           session.campaign_state['level'])
        config_str = (
            '1p' + session.campaign.get_level(session.campaign_state['level']).
            get_score_version_string().replace(' ', '_'))
        _ba.get_scores_to_beat(level_name_full, config_str,
                               ba.WeakCall(self._on_got_scores_to_beat))
Example #6
0
    def _check_fade_in(self) -> None:
        from ba.internal import get_device_value

        # If we have a touchscreen, we only fade in if we have a player with
        # an input device that is *not* the touchscreen.
        # (otherwise it is confusing to see the touchscreen buttons right
        # next to our display buttons)
        touchscreen: Optional[ba.InputDevice] = _ba.getinputdevice(
            'TouchScreen', '#1', doraise=False)

        if touchscreen is not None:
            # We look at the session's players; not the activity's.
            # We want to get ones who are still in the process of
            # selecting a character, etc.
            input_devices = [
                p.inputdevice for p in ba.getsession().sessionplayers
            ]
            input_devices = [
                i for i in input_devices if i and i is not touchscreen
            ]
            fade_in = False
            if input_devices:
                # Only count this one if it has non-empty button names
                # (filters out wiimotes, the remote-app, etc).
                for device in input_devices:
                    for name in ('buttonPunch', 'buttonJump', 'buttonBomb',
                                 'buttonPickUp'):
                        if self._meaningful_button_name(
                                device, get_device_value(device, name)) != '':
                            fade_in = True
                            break
                    if fade_in:
                        break  # No need to keep looking.
        else:
            # No touch-screen; fade in immediately.
            fade_in = True
        if fade_in:
            self._cancel_timer = None  # Didn't need this.
            self._fade_in_timer = None  # Done with this.
            self._fade_in()
Example #7
0
 def __init__(self,
              fade_time: float = 0.5,
              start_faded: bool = False,
              show_logo: bool = False):
     super().__init__()
     self._dying = False
     self.fade_time = fade_time
     # We're special in that we create our node in the session
     # scene instead of the activity scene.
     # This way we can overlap multiple activities for fades
     # and whatnot.
     session = ba.getsession()
     self._session = weakref.ref(session)
     with ba.Context(session):
         self.node = ba.newnode('image',
                                delegate=self,
                                attrs={
                                    'fill_screen': True,
                                    'texture': ba.gettexture('bg'),
                                    'tilt_translate': -0.3,
                                    'has_alpha_channel': False,
                                    'color': (1, 1, 1)
                                })
         if not start_faded:
             ba.animate(self.node,
                        'opacity', {
                            0.0: 0.0,
                            self.fade_time: 1.0
                        },
                        loop=False)
         if show_logo:
             logo_texture = ba.gettexture('logo')
             logo_model = ba.getmodel('logo')
             logo_model_transparent = ba.getmodel('logoTransparent')
             self.logo = ba.newnode('image',
                                    owner=self.node,
                                    attrs={
                                        'texture': logo_texture,
                                        'model_opaque': logo_model,
                                        'model_transparent':
                                        logo_model_transparent,
                                        'scale': (0.7, 0.7),
                                        'vr_depth': -250,
                                        'color': (0.15, 0.15, 0.15),
                                        'position': (0, 0),
                                        'tilt_translate': -0.05,
                                        'absolute_scale': False
                                    })
             self.node.connectattr('opacity', self.logo, 'opacity')
             # add jitter/pulse for a stop-motion-y look unless we're in VR
             # in which case stillness is better
             if not ba.app.vr_mode:
                 self.cmb = ba.newnode('combine',
                                       owner=self.node,
                                       attrs={'size': 2})
                 for attr in ['input0', 'input1']:
                     ba.animate(self.cmb,
                                attr, {
                                    0.0: 0.693,
                                    0.05: 0.7,
                                    0.5: 0.693
                                },
                                loop=True)
                 self.cmb.connectattr('output', self.logo, 'scale')
                 cmb = ba.newnode('combine',
                                  owner=self.node,
                                  attrs={'size': 2})
                 cmb.connectattr('output', self.logo, 'position')
                 # Gen some random keys for that stop-motion-y look.
                 keys = {}
                 timeval = 0.0
                 for _i in range(10):
                     keys[timeval] = (random.random() - 0.5) * 0.0015
                     timeval += random.random() * 0.1
                 ba.animate(cmb, 'input0', keys, loop=True)
                 keys = {}
                 timeval = 0.0
                 for _i in range(10):
                     keys[timeval] = (random.random() - 0.5) * 0.0015 + 0.05
                     timeval += random.random() * 0.1
                 ba.animate(cmb, 'input1', keys, loop=True)
Example #8
0
    def _update(self) -> None:
        # pylint: disable=too-many-statements
        # pylint: disable=too-many-branches
        # pylint: disable=too-many-locals
        from ba.internal import get_device_value, get_remote_app_name
        if self._dead:
            return
        punch_button_names = set()
        jump_button_names = set()
        pickup_button_names = set()
        bomb_button_names = set()

        # We look at the session's players; not the activity's - we want to
        # get ones who are still in the process of selecting a character, etc.
        input_devices = [p.get_input_device() for p in ba.getsession().players]
        input_devices = [i for i in input_devices if i]

        # If there's no players with input devices yet, try to default to
        # showing keyboard controls.
        if not input_devices:
            kbd = _ba.get_input_device('Keyboard', '#1', doraise=False)
            if kbd is not None:
                input_devices.append(kbd)

        # We word things specially if we have nothing but keyboards.
        all_keyboards = (input_devices
                         and all(i.name == 'Keyboard' for i in input_devices))
        only_remote = (len(input_devices) == 1
                       and all(i.name == 'Amazon Fire TV Remote'
                               for i in input_devices))

        right_button_names = set()
        left_button_names = set()
        up_button_names = set()
        down_button_names = set()

        # For each player in the game with an input device,
        # get the name of the button for each of these 4 actions.
        # If any of them are uniform across all devices, display the name.
        for device in input_devices:
            # We only care about movement buttons in the case of keyboards.
            if all_keyboards:
                right_button_names.add(
                    device.get_button_name(
                        get_device_value(device, 'buttonRight')))
                left_button_names.add(
                    device.get_button_name(
                        get_device_value(device, 'buttonLeft')))
                down_button_names.add(
                    device.get_button_name(
                        get_device_value(device, 'buttonDown')))
                up_button_names.add(
                    device.get_button_name(get_device_value(
                        device, 'buttonUp')))

            # Ignore empty values; things like the remote app or
            # wiimotes can return these.
            bname = device.get_button_name(
                get_device_value(device, 'buttonPunch'))
            if bname != '':
                punch_button_names.add(bname)
            bname = device.get_button_name(
                get_device_value(device, 'buttonJump'))
            if bname != '':
                jump_button_names.add(bname)
            bname = device.get_button_name(
                get_device_value(device, 'buttonBomb'))
            if bname != '':
                bomb_button_names.add(bname)
            bname = device.get_button_name(
                get_device_value(device, 'buttonPickUp'))
            if bname != '':
                pickup_button_names.add(bname)

        # If we have no values yet, we may want to throw out some sane
        # defaults.
        if all(not lst for lst in (punch_button_names, jump_button_names,
                                   bomb_button_names, pickup_button_names)):
            # Otherwise on android show standard buttons.
            if ba.app.platform == 'android':
                punch_button_names.add('X')
                jump_button_names.add('A')
                bomb_button_names.add('B')
                pickup_button_names.add('Y')

        run_text = ba.Lstr(
            value='${R}: ${B}',
            subs=[('${R}', ba.Lstr(resource='runText')),
                  ('${B}',
                   ba.Lstr(resource='holdAnyKeyText'
                           if all_keyboards else 'holdAnyButtonText'))])

        # If we're all keyboards, lets show move keys too.
        if (all_keyboards and len(up_button_names) == 1
                and len(down_button_names) == 1 and len(left_button_names) == 1
                and len(right_button_names) == 1):
            up_text = list(up_button_names)[0]
            down_text = list(down_button_names)[0]
            left_text = list(left_button_names)[0]
            right_text = list(right_button_names)[0]
            run_text = ba.Lstr(value='${M}: ${U}, ${L}, ${D}, ${R}\n${RUN}',
                               subs=[('${M}', ba.Lstr(resource='moveText')),
                                     ('${U}', up_text), ('${L}', left_text),
                                     ('${D}', down_text), ('${R}', right_text),
                                     ('${RUN}', run_text)])

        self._run_text.text = run_text
        w_text: Union[ba.Lstr, str]
        if only_remote and self._lifespan is None:
            w_text = ba.Lstr(resource='fireTVRemoteWarningText',
                             subs=[('${REMOTE_APP_NAME}',
                                    get_remote_app_name())])
        else:
            w_text = ''
        self._extra_text.text = w_text
        if len(punch_button_names) == 1:
            self._punch_text.text = list(punch_button_names)[0]
        else:
            self._punch_text.text = ''

        if len(jump_button_names) == 1:
            tval = list(jump_button_names)[0]
        else:
            tval = ''
        self._jump_text.text = tval
        if tval == '':
            self._run_text.position = self._run_text_pos_top
            self._extra_text.position = (self._run_text_pos_top[0],
                                         self._run_text_pos_top[1] - 50)
        else:
            self._run_text.position = self._run_text_pos_bottom
            self._extra_text.position = (self._run_text_pos_bottom[0],
                                         self._run_text_pos_bottom[1] - 50)
        if len(bomb_button_names) == 1:
            self._bomb_text.text = list(bomb_button_names)[0]
        else:
            self._bomb_text.text = ''

        # Also move our title up/down depending on if this is shown.
        if len(pickup_button_names) == 1:
            self._pick_up_text.text = list(pickup_button_names)[0]
            if self._title_text is not None:
                self._title_text.position = self._title_text_pos_top
        else:
            self._pick_up_text.text = ''
            if self._title_text is not None:
                self._title_text.position = self._title_text_pos_bottom