bastd.actor.zoomtext
Defined Actor(s).
1# Released under the MIT License. See LICENSE for details. 2# 3"""Defined Actor(s).""" 4 5from __future__ import annotations 6 7import random 8from typing import TYPE_CHECKING 9 10import ba 11 12if TYPE_CHECKING: 13 from typing import Any, Sequence 14 15 16class ZoomText(ba.Actor): 17 """Big Zooming Text. 18 19 Category: Gameplay Classes 20 21 Used for things such as the 'BOB WINS' victory messages. 22 """ 23 24 def __init__(self, 25 text: str | ba.Lstr, 26 position: tuple[float, float] = (0.0, 0.0), 27 shiftposition: tuple[float, float] | None = None, 28 shiftdelay: float | None = None, 29 lifespan: float | None = None, 30 flash: bool = True, 31 trail: bool = True, 32 h_align: str = 'center', 33 color: Sequence[float] = (0.9, 0.4, 0.0), 34 jitter: float = 0.0, 35 trailcolor: Sequence[float] = (1.0, 0.35, 0.1, 0.0), 36 scale: float = 1.0, 37 project_scale: float = 1.0, 38 tilt_translate: float = 0.0, 39 maxwidth: float | None = None): 40 # pylint: disable=too-many-locals 41 super().__init__() 42 self._dying = False 43 positionadjusted = (position[0], position[1] - 100) 44 if shiftdelay is None: 45 shiftdelay = 2.500 46 if shiftdelay < 0.0: 47 ba.print_error('got shiftdelay < 0') 48 shiftdelay = 0.0 49 self._project_scale = project_scale 50 self.node = ba.newnode( 51 'text', 52 delegate=self, 53 attrs={ 54 'position': positionadjusted, 55 'big': True, 56 'text': text, 57 'trail': trail, 58 'vr_depth': 0, 59 'shadow': 0.0 if trail else 0.3, 60 'scale': scale, 61 'maxwidth': maxwidth if maxwidth is not None else 0.0, 62 'tilt_translate': tilt_translate, 63 'h_align': h_align, 64 'v_align': 'center' 65 }) 66 67 # we never jitter in vr mode.. 68 if ba.app.vr_mode: 69 jitter = 0.0 70 71 # if they want jitter, animate its position slightly... 72 if jitter > 0.0: 73 self._jitter(positionadjusted, jitter * scale) 74 75 # if they want shifting, move to the shift position and 76 # then resume jittering 77 if shiftposition is not None: 78 positionadjusted2 = (shiftposition[0], shiftposition[1] - 100) 79 ba.timer( 80 shiftdelay, 81 ba.WeakCall(self._shift, positionadjusted, positionadjusted2)) 82 if jitter > 0.0: 83 ba.timer( 84 shiftdelay + 0.25, 85 ba.WeakCall(self._jitter, positionadjusted2, 86 jitter * scale)) 87 color_combine = ba.newnode('combine', 88 owner=self.node, 89 attrs={ 90 'input2': color[2], 91 'input3': 1.0, 92 'size': 4 93 }) 94 if trail: 95 trailcolor_n = ba.newnode('combine', 96 owner=self.node, 97 attrs={ 98 'size': 3, 99 'input0': trailcolor[0], 100 'input1': trailcolor[1], 101 'input2': trailcolor[2] 102 }) 103 trailcolor_n.connectattr('output', self.node, 'trailcolor') 104 basemult = 0.85 105 ba.animate( 106 self.node, 'trail_project_scale', { 107 0: 0 * project_scale, 108 basemult * 0.201: 0.6 * project_scale, 109 basemult * 0.347: 0.8 * project_scale, 110 basemult * 0.478: 0.9 * project_scale, 111 basemult * 0.595: 0.93 * project_scale, 112 basemult * 0.748: 0.95 * project_scale, 113 basemult * 0.941: 0.95 * project_scale 114 }) 115 if flash: 116 mult = 2.0 117 tm1 = 0.15 118 tm2 = 0.3 119 ba.animate(color_combine, 120 'input0', { 121 0: color[0] * mult, 122 tm1: color[0], 123 tm2: color[0] * mult 124 }, 125 loop=True) 126 ba.animate(color_combine, 127 'input1', { 128 0: color[1] * mult, 129 tm1: color[1], 130 tm2: color[1] * mult 131 }, 132 loop=True) 133 ba.animate(color_combine, 134 'input2', { 135 0: color[2] * mult, 136 tm1: color[2], 137 tm2: color[2] * mult 138 }, 139 loop=True) 140 else: 141 color_combine.input0 = color[0] 142 color_combine.input1 = color[1] 143 color_combine.connectattr('output', self.node, 'color') 144 ba.animate(self.node, 'project_scale', { 145 0: 0, 146 0.27: 1.05 * project_scale, 147 0.3: 1 * project_scale 148 }) 149 150 # if they give us a lifespan, kill ourself down the line 151 if lifespan is not None: 152 ba.timer(lifespan, ba.WeakCall(self.handlemessage, 153 ba.DieMessage())) 154 155 def handlemessage(self, msg: Any) -> Any: 156 assert not self.expired 157 if isinstance(msg, ba.DieMessage): 158 if not self._dying and self.node: 159 self._dying = True 160 if msg.immediate: 161 self.node.delete() 162 else: 163 ba.animate( 164 self.node, 'project_scale', { 165 0.0: 1 * self._project_scale, 166 0.6: 1.2 * self._project_scale 167 }) 168 ba.animate(self.node, 'opacity', {0.0: 1, 0.3: 0}) 169 ba.animate(self.node, 'trail_opacity', {0.0: 1, 0.6: 0}) 170 ba.timer(0.7, self.node.delete) 171 return None 172 return super().handlemessage(msg) 173 174 def _jitter(self, position: tuple[float, float], 175 jitter_amount: float) -> None: 176 if not self.node: 177 return 178 cmb = ba.newnode('combine', owner=self.node, attrs={'size': 2}) 179 for index, attr in enumerate(['input0', 'input1']): 180 keys = {} 181 timeval = 0.0 182 # gen some random keys for that stop-motion-y look 183 for _i in range(10): 184 keys[timeval] = (position[index] + 185 (random.random() - 0.5) * jitter_amount * 1.6) 186 timeval += random.random() * 0.1 187 ba.animate(cmb, attr, keys, loop=True) 188 cmb.connectattr('output', self.node, 'position') 189 190 def _shift(self, position1: tuple[float, float], 191 position2: tuple[float, float]) -> None: 192 if not self.node: 193 return 194 cmb = ba.newnode('combine', owner=self.node, attrs={'size': 2}) 195 ba.animate(cmb, 'input0', {0.0: position1[0], 0.25: position2[0]}) 196 ba.animate(cmb, 'input1', {0.0: position1[1], 0.25: position2[1]}) 197 cmb.connectattr('output', self.node, 'position')
class
ZoomText(ba._actor.Actor):
17class ZoomText(ba.Actor): 18 """Big Zooming Text. 19 20 Category: Gameplay Classes 21 22 Used for things such as the 'BOB WINS' victory messages. 23 """ 24 25 def __init__(self, 26 text: str | ba.Lstr, 27 position: tuple[float, float] = (0.0, 0.0), 28 shiftposition: tuple[float, float] | None = None, 29 shiftdelay: float | None = None, 30 lifespan: float | None = None, 31 flash: bool = True, 32 trail: bool = True, 33 h_align: str = 'center', 34 color: Sequence[float] = (0.9, 0.4, 0.0), 35 jitter: float = 0.0, 36 trailcolor: Sequence[float] = (1.0, 0.35, 0.1, 0.0), 37 scale: float = 1.0, 38 project_scale: float = 1.0, 39 tilt_translate: float = 0.0, 40 maxwidth: float | None = None): 41 # pylint: disable=too-many-locals 42 super().__init__() 43 self._dying = False 44 positionadjusted = (position[0], position[1] - 100) 45 if shiftdelay is None: 46 shiftdelay = 2.500 47 if shiftdelay < 0.0: 48 ba.print_error('got shiftdelay < 0') 49 shiftdelay = 0.0 50 self._project_scale = project_scale 51 self.node = ba.newnode( 52 'text', 53 delegate=self, 54 attrs={ 55 'position': positionadjusted, 56 'big': True, 57 'text': text, 58 'trail': trail, 59 'vr_depth': 0, 60 'shadow': 0.0 if trail else 0.3, 61 'scale': scale, 62 'maxwidth': maxwidth if maxwidth is not None else 0.0, 63 'tilt_translate': tilt_translate, 64 'h_align': h_align, 65 'v_align': 'center' 66 }) 67 68 # we never jitter in vr mode.. 69 if ba.app.vr_mode: 70 jitter = 0.0 71 72 # if they want jitter, animate its position slightly... 73 if jitter > 0.0: 74 self._jitter(positionadjusted, jitter * scale) 75 76 # if they want shifting, move to the shift position and 77 # then resume jittering 78 if shiftposition is not None: 79 positionadjusted2 = (shiftposition[0], shiftposition[1] - 100) 80 ba.timer( 81 shiftdelay, 82 ba.WeakCall(self._shift, positionadjusted, positionadjusted2)) 83 if jitter > 0.0: 84 ba.timer( 85 shiftdelay + 0.25, 86 ba.WeakCall(self._jitter, positionadjusted2, 87 jitter * scale)) 88 color_combine = ba.newnode('combine', 89 owner=self.node, 90 attrs={ 91 'input2': color[2], 92 'input3': 1.0, 93 'size': 4 94 }) 95 if trail: 96 trailcolor_n = ba.newnode('combine', 97 owner=self.node, 98 attrs={ 99 'size': 3, 100 'input0': trailcolor[0], 101 'input1': trailcolor[1], 102 'input2': trailcolor[2] 103 }) 104 trailcolor_n.connectattr('output', self.node, 'trailcolor') 105 basemult = 0.85 106 ba.animate( 107 self.node, 'trail_project_scale', { 108 0: 0 * project_scale, 109 basemult * 0.201: 0.6 * project_scale, 110 basemult * 0.347: 0.8 * project_scale, 111 basemult * 0.478: 0.9 * project_scale, 112 basemult * 0.595: 0.93 * project_scale, 113 basemult * 0.748: 0.95 * project_scale, 114 basemult * 0.941: 0.95 * project_scale 115 }) 116 if flash: 117 mult = 2.0 118 tm1 = 0.15 119 tm2 = 0.3 120 ba.animate(color_combine, 121 'input0', { 122 0: color[0] * mult, 123 tm1: color[0], 124 tm2: color[0] * mult 125 }, 126 loop=True) 127 ba.animate(color_combine, 128 'input1', { 129 0: color[1] * mult, 130 tm1: color[1], 131 tm2: color[1] * mult 132 }, 133 loop=True) 134 ba.animate(color_combine, 135 'input2', { 136 0: color[2] * mult, 137 tm1: color[2], 138 tm2: color[2] * mult 139 }, 140 loop=True) 141 else: 142 color_combine.input0 = color[0] 143 color_combine.input1 = color[1] 144 color_combine.connectattr('output', self.node, 'color') 145 ba.animate(self.node, 'project_scale', { 146 0: 0, 147 0.27: 1.05 * project_scale, 148 0.3: 1 * project_scale 149 }) 150 151 # if they give us a lifespan, kill ourself down the line 152 if lifespan is not None: 153 ba.timer(lifespan, ba.WeakCall(self.handlemessage, 154 ba.DieMessage())) 155 156 def handlemessage(self, msg: Any) -> Any: 157 assert not self.expired 158 if isinstance(msg, ba.DieMessage): 159 if not self._dying and self.node: 160 self._dying = True 161 if msg.immediate: 162 self.node.delete() 163 else: 164 ba.animate( 165 self.node, 'project_scale', { 166 0.0: 1 * self._project_scale, 167 0.6: 1.2 * self._project_scale 168 }) 169 ba.animate(self.node, 'opacity', {0.0: 1, 0.3: 0}) 170 ba.animate(self.node, 'trail_opacity', {0.0: 1, 0.6: 0}) 171 ba.timer(0.7, self.node.delete) 172 return None 173 return super().handlemessage(msg) 174 175 def _jitter(self, position: tuple[float, float], 176 jitter_amount: float) -> None: 177 if not self.node: 178 return 179 cmb = ba.newnode('combine', owner=self.node, attrs={'size': 2}) 180 for index, attr in enumerate(['input0', 'input1']): 181 keys = {} 182 timeval = 0.0 183 # gen some random keys for that stop-motion-y look 184 for _i in range(10): 185 keys[timeval] = (position[index] + 186 (random.random() - 0.5) * jitter_amount * 1.6) 187 timeval += random.random() * 0.1 188 ba.animate(cmb, attr, keys, loop=True) 189 cmb.connectattr('output', self.node, 'position') 190 191 def _shift(self, position1: tuple[float, float], 192 position2: tuple[float, float]) -> None: 193 if not self.node: 194 return 195 cmb = ba.newnode('combine', owner=self.node, attrs={'size': 2}) 196 ba.animate(cmb, 'input0', {0.0: position1[0], 0.25: position2[0]}) 197 ba.animate(cmb, 'input1', {0.0: position1[1], 0.25: position2[1]}) 198 cmb.connectattr('output', self.node, 'position')
Big Zooming Text.
Category: Gameplay Classes
Used for things such as the 'BOB WINS' victory messages.
ZoomText( text: str | ba._language.Lstr, position: tuple[float, float] = (0.0, 0.0), shiftposition: tuple[float, float] | None = None, shiftdelay: float | None = None, lifespan: float | None = None, flash: bool = True, trail: bool = True, h_align: str = 'center', color: Sequence[float] = (0.9, 0.4, 0.0), jitter: float = 0.0, trailcolor: Sequence[float] = (1.0, 0.35, 0.1, 0.0), scale: float = 1.0, project_scale: float = 1.0, tilt_translate: float = 0.0, maxwidth: float | None = None)
25 def __init__(self, 26 text: str | ba.Lstr, 27 position: tuple[float, float] = (0.0, 0.0), 28 shiftposition: tuple[float, float] | None = None, 29 shiftdelay: float | None = None, 30 lifespan: float | None = None, 31 flash: bool = True, 32 trail: bool = True, 33 h_align: str = 'center', 34 color: Sequence[float] = (0.9, 0.4, 0.0), 35 jitter: float = 0.0, 36 trailcolor: Sequence[float] = (1.0, 0.35, 0.1, 0.0), 37 scale: float = 1.0, 38 project_scale: float = 1.0, 39 tilt_translate: float = 0.0, 40 maxwidth: float | None = None): 41 # pylint: disable=too-many-locals 42 super().__init__() 43 self._dying = False 44 positionadjusted = (position[0], position[1] - 100) 45 if shiftdelay is None: 46 shiftdelay = 2.500 47 if shiftdelay < 0.0: 48 ba.print_error('got shiftdelay < 0') 49 shiftdelay = 0.0 50 self._project_scale = project_scale 51 self.node = ba.newnode( 52 'text', 53 delegate=self, 54 attrs={ 55 'position': positionadjusted, 56 'big': True, 57 'text': text, 58 'trail': trail, 59 'vr_depth': 0, 60 'shadow': 0.0 if trail else 0.3, 61 'scale': scale, 62 'maxwidth': maxwidth if maxwidth is not None else 0.0, 63 'tilt_translate': tilt_translate, 64 'h_align': h_align, 65 'v_align': 'center' 66 }) 67 68 # we never jitter in vr mode.. 69 if ba.app.vr_mode: 70 jitter = 0.0 71 72 # if they want jitter, animate its position slightly... 73 if jitter > 0.0: 74 self._jitter(positionadjusted, jitter * scale) 75 76 # if they want shifting, move to the shift position and 77 # then resume jittering 78 if shiftposition is not None: 79 positionadjusted2 = (shiftposition[0], shiftposition[1] - 100) 80 ba.timer( 81 shiftdelay, 82 ba.WeakCall(self._shift, positionadjusted, positionadjusted2)) 83 if jitter > 0.0: 84 ba.timer( 85 shiftdelay + 0.25, 86 ba.WeakCall(self._jitter, positionadjusted2, 87 jitter * scale)) 88 color_combine = ba.newnode('combine', 89 owner=self.node, 90 attrs={ 91 'input2': color[2], 92 'input3': 1.0, 93 'size': 4 94 }) 95 if trail: 96 trailcolor_n = ba.newnode('combine', 97 owner=self.node, 98 attrs={ 99 'size': 3, 100 'input0': trailcolor[0], 101 'input1': trailcolor[1], 102 'input2': trailcolor[2] 103 }) 104 trailcolor_n.connectattr('output', self.node, 'trailcolor') 105 basemult = 0.85 106 ba.animate( 107 self.node, 'trail_project_scale', { 108 0: 0 * project_scale, 109 basemult * 0.201: 0.6 * project_scale, 110 basemult * 0.347: 0.8 * project_scale, 111 basemult * 0.478: 0.9 * project_scale, 112 basemult * 0.595: 0.93 * project_scale, 113 basemult * 0.748: 0.95 * project_scale, 114 basemult * 0.941: 0.95 * project_scale 115 }) 116 if flash: 117 mult = 2.0 118 tm1 = 0.15 119 tm2 = 0.3 120 ba.animate(color_combine, 121 'input0', { 122 0: color[0] * mult, 123 tm1: color[0], 124 tm2: color[0] * mult 125 }, 126 loop=True) 127 ba.animate(color_combine, 128 'input1', { 129 0: color[1] * mult, 130 tm1: color[1], 131 tm2: color[1] * mult 132 }, 133 loop=True) 134 ba.animate(color_combine, 135 'input2', { 136 0: color[2] * mult, 137 tm1: color[2], 138 tm2: color[2] * mult 139 }, 140 loop=True) 141 else: 142 color_combine.input0 = color[0] 143 color_combine.input1 = color[1] 144 color_combine.connectattr('output', self.node, 'color') 145 ba.animate(self.node, 'project_scale', { 146 0: 0, 147 0.27: 1.05 * project_scale, 148 0.3: 1 * project_scale 149 }) 150 151 # if they give us a lifespan, kill ourself down the line 152 if lifespan is not None: 153 ba.timer(lifespan, ba.WeakCall(self.handlemessage, 154 ba.DieMessage()))
Instantiates an Actor in the current ba.Activity.
def
handlemessage(self, msg: Any) -> Any:
156 def handlemessage(self, msg: Any) -> Any: 157 assert not self.expired 158 if isinstance(msg, ba.DieMessage): 159 if not self._dying and self.node: 160 self._dying = True 161 if msg.immediate: 162 self.node.delete() 163 else: 164 ba.animate( 165 self.node, 'project_scale', { 166 0.0: 1 * self._project_scale, 167 0.6: 1.2 * self._project_scale 168 }) 169 ba.animate(self.node, 'opacity', {0.0: 1, 0.3: 0}) 170 ba.animate(self.node, 'trail_opacity', {0.0: 1, 0.6: 0}) 171 ba.timer(0.7, self.node.delete) 172 return None 173 return super().handlemessage(msg)
General message handling; can be passed any message object.
Inherited Members
- ba._actor.Actor
- autoretain
- on_expire
- expired
- exists
- is_alive
- activity
- getactivity