bastd.gameutils

Various utilities useful for gameplay.

  1# Released under the MIT License. See LICENSE for details.
  2#
  3"""Various utilities useful for gameplay."""
  4
  5from __future__ import annotations
  6
  7from typing import TYPE_CHECKING
  8
  9import ba
 10
 11if TYPE_CHECKING:
 12    pass
 13
 14
 15class SharedObjects:
 16    """Various common components for use in games.
 17
 18    Category: Gameplay Classes
 19
 20    Objects contained here are created on-demand as accessed and shared
 21    by everything in the current activity. This includes things such as
 22    standard materials.
 23    """
 24
 25    _STORENAME = ba.storagename()
 26
 27    def __init__(self) -> None:
 28        activity = ba.getactivity()
 29        if self._STORENAME in activity.customdata:
 30            raise RuntimeError(
 31                'Use SharedObjects.get() to fetch the'
 32                ' shared instance for this activity.'
 33            )
 34        self._object_material: ba.Material | None = None
 35        self._player_material: ba.Material | None = None
 36        self._pickup_material: ba.Material | None = None
 37        self._footing_material: ba.Material | None = None
 38        self._attack_material: ba.Material | None = None
 39        self._death_material: ba.Material | None = None
 40        self._region_material: ba.Material | None = None
 41        self._railing_material: ba.Material | None = None
 42
 43    @classmethod
 44    def get(cls) -> SharedObjects:
 45        """Fetch/create the instance of this class for the current activity."""
 46        activity = ba.getactivity()
 47        shobs = activity.customdata.get(cls._STORENAME)
 48        if shobs is None:
 49            shobs = SharedObjects()
 50            activity.customdata[cls._STORENAME] = shobs
 51        assert isinstance(shobs, SharedObjects)
 52        return shobs
 53
 54    @property
 55    def player_material(self) -> ba.Material:
 56        """a ba.Material to be applied to player parts. Generally,
 57        materials related to the process of scoring when reaching a goal, etc
 58        will look for the presence of this material on things that hit them.
 59        """
 60        if self._player_material is None:
 61            self._player_material = ba.Material()
 62        return self._player_material
 63
 64    @property
 65    def object_material(self) -> ba.Material:
 66        """A ba.Material that should be applied to any small,
 67        normal, physical objects such as bombs, boxes, players, etc. Other
 68        materials often check for the  presence of this material as a
 69        prerequisite for performing certain actions (such as disabling
 70        collisions between initially-overlapping objects)
 71        """
 72        if self._object_material is None:
 73            self._object_material = ba.Material()
 74        return self._object_material
 75
 76    @property
 77    def pickup_material(self) -> ba.Material:
 78        """A ba.Material; collision shapes used for picking things
 79        up will have this material applied. To prevent an object from being
 80        picked up, you can add a material that disables collisions against
 81        things containing this material.
 82        """
 83        if self._pickup_material is None:
 84            self._pickup_material = ba.Material()
 85        return self._pickup_material
 86
 87    @property
 88    def footing_material(self) -> ba.Material:
 89        """Anything that can be 'walked on' should have this
 90        ba.Material applied; generally just terrain and whatnot. A character
 91        will snap upright whenever touching something with this material so it
 92        should not be applied to props, etc.
 93        """
 94        if self._footing_material is None:
 95            self._footing_material = ba.Material()
 96        return self._footing_material
 97
 98    @property
 99    def attack_material(self) -> ba.Material:
100        """A ba.Material applied to explosion shapes, punch
101        shapes, etc.  An object not wanting to receive impulse/etc messages can
102        disable collisions against this material.
103        """
104        if self._attack_material is None:
105            self._attack_material = ba.Material()
106        return self._attack_material
107
108    @property
109    def death_material(self) -> ba.Material:
110        """A ba.Material that sends a ba.DieMessage() to anything
111        that touches it; handy for terrain below a cliff, etc.
112        """
113        if self._death_material is None:
114            mat = self._death_material = ba.Material()
115            mat.add_actions(
116                ('message', 'their_node', 'at_connect', ba.DieMessage())
117            )
118        return self._death_material
119
120    @property
121    def region_material(self) -> ba.Material:
122        """A ba.Material used for non-physical collision shapes
123        (regions); collisions can generally be allowed with this material even
124        when initially overlapping since it is not physical.
125        """
126        if self._region_material is None:
127            self._region_material = ba.Material()
128        return self._region_material
129
130    @property
131    def railing_material(self) -> ba.Material:
132        """A ba.Material with a very low friction/stiffness/etc
133        that can be applied to invisible 'railings' useful for gently keeping
134        characters from falling off of cliffs.
135        """
136        if self._railing_material is None:
137            mat = self._railing_material = ba.Material()
138            mat.add_actions(('modify_part_collision', 'collide', False))
139            mat.add_actions(('modify_part_collision', 'stiffness', 0.003))
140            mat.add_actions(('modify_part_collision', 'damping', 0.00001))
141            mat.add_actions(
142                conditions=('they_have_material', self.player_material),
143                actions=(
144                    ('modify_part_collision', 'collide', True),
145                    ('modify_part_collision', 'friction', 0.0),
146                ),
147            )
148        return self._railing_material
class SharedObjects:
 16class SharedObjects:
 17    """Various common components for use in games.
 18
 19    Category: Gameplay Classes
 20
 21    Objects contained here are created on-demand as accessed and shared
 22    by everything in the current activity. This includes things such as
 23    standard materials.
 24    """
 25
 26    _STORENAME = ba.storagename()
 27
 28    def __init__(self) -> None:
 29        activity = ba.getactivity()
 30        if self._STORENAME in activity.customdata:
 31            raise RuntimeError(
 32                'Use SharedObjects.get() to fetch the'
 33                ' shared instance for this activity.'
 34            )
 35        self._object_material: ba.Material | None = None
 36        self._player_material: ba.Material | None = None
 37        self._pickup_material: ba.Material | None = None
 38        self._footing_material: ba.Material | None = None
 39        self._attack_material: ba.Material | None = None
 40        self._death_material: ba.Material | None = None
 41        self._region_material: ba.Material | None = None
 42        self._railing_material: ba.Material | None = None
 43
 44    @classmethod
 45    def get(cls) -> SharedObjects:
 46        """Fetch/create the instance of this class for the current activity."""
 47        activity = ba.getactivity()
 48        shobs = activity.customdata.get(cls._STORENAME)
 49        if shobs is None:
 50            shobs = SharedObjects()
 51            activity.customdata[cls._STORENAME] = shobs
 52        assert isinstance(shobs, SharedObjects)
 53        return shobs
 54
 55    @property
 56    def player_material(self) -> ba.Material:
 57        """a ba.Material to be applied to player parts. Generally,
 58        materials related to the process of scoring when reaching a goal, etc
 59        will look for the presence of this material on things that hit them.
 60        """
 61        if self._player_material is None:
 62            self._player_material = ba.Material()
 63        return self._player_material
 64
 65    @property
 66    def object_material(self) -> ba.Material:
 67        """A ba.Material that should be applied to any small,
 68        normal, physical objects such as bombs, boxes, players, etc. Other
 69        materials often check for the  presence of this material as a
 70        prerequisite for performing certain actions (such as disabling
 71        collisions between initially-overlapping objects)
 72        """
 73        if self._object_material is None:
 74            self._object_material = ba.Material()
 75        return self._object_material
 76
 77    @property
 78    def pickup_material(self) -> ba.Material:
 79        """A ba.Material; collision shapes used for picking things
 80        up will have this material applied. To prevent an object from being
 81        picked up, you can add a material that disables collisions against
 82        things containing this material.
 83        """
 84        if self._pickup_material is None:
 85            self._pickup_material = ba.Material()
 86        return self._pickup_material
 87
 88    @property
 89    def footing_material(self) -> ba.Material:
 90        """Anything that can be 'walked on' should have this
 91        ba.Material applied; generally just terrain and whatnot. A character
 92        will snap upright whenever touching something with this material so it
 93        should not be applied to props, etc.
 94        """
 95        if self._footing_material is None:
 96            self._footing_material = ba.Material()
 97        return self._footing_material
 98
 99    @property
100    def attack_material(self) -> ba.Material:
101        """A ba.Material applied to explosion shapes, punch
102        shapes, etc.  An object not wanting to receive impulse/etc messages can
103        disable collisions against this material.
104        """
105        if self._attack_material is None:
106            self._attack_material = ba.Material()
107        return self._attack_material
108
109    @property
110    def death_material(self) -> ba.Material:
111        """A ba.Material that sends a ba.DieMessage() to anything
112        that touches it; handy for terrain below a cliff, etc.
113        """
114        if self._death_material is None:
115            mat = self._death_material = ba.Material()
116            mat.add_actions(
117                ('message', 'their_node', 'at_connect', ba.DieMessage())
118            )
119        return self._death_material
120
121    @property
122    def region_material(self) -> ba.Material:
123        """A ba.Material used for non-physical collision shapes
124        (regions); collisions can generally be allowed with this material even
125        when initially overlapping since it is not physical.
126        """
127        if self._region_material is None:
128            self._region_material = ba.Material()
129        return self._region_material
130
131    @property
132    def railing_material(self) -> ba.Material:
133        """A ba.Material with a very low friction/stiffness/etc
134        that can be applied to invisible 'railings' useful for gently keeping
135        characters from falling off of cliffs.
136        """
137        if self._railing_material is None:
138            mat = self._railing_material = ba.Material()
139            mat.add_actions(('modify_part_collision', 'collide', False))
140            mat.add_actions(('modify_part_collision', 'stiffness', 0.003))
141            mat.add_actions(('modify_part_collision', 'damping', 0.00001))
142            mat.add_actions(
143                conditions=('they_have_material', self.player_material),
144                actions=(
145                    ('modify_part_collision', 'collide', True),
146                    ('modify_part_collision', 'friction', 0.0),
147                ),
148            )
149        return self._railing_material

Various common components for use in games.

Category: Gameplay Classes

Objects contained here are created on-demand as accessed and shared by everything in the current activity. This includes things such as standard materials.

SharedObjects()
28    def __init__(self) -> None:
29        activity = ba.getactivity()
30        if self._STORENAME in activity.customdata:
31            raise RuntimeError(
32                'Use SharedObjects.get() to fetch the'
33                ' shared instance for this activity.'
34            )
35        self._object_material: ba.Material | None = None
36        self._player_material: ba.Material | None = None
37        self._pickup_material: ba.Material | None = None
38        self._footing_material: ba.Material | None = None
39        self._attack_material: ba.Material | None = None
40        self._death_material: ba.Material | None = None
41        self._region_material: ba.Material | None = None
42        self._railing_material: ba.Material | None = None
@classmethod
def get(cls) -> bastd.gameutils.SharedObjects:
44    @classmethod
45    def get(cls) -> SharedObjects:
46        """Fetch/create the instance of this class for the current activity."""
47        activity = ba.getactivity()
48        shobs = activity.customdata.get(cls._STORENAME)
49        if shobs is None:
50            shobs = SharedObjects()
51            activity.customdata[cls._STORENAME] = shobs
52        assert isinstance(shobs, SharedObjects)
53        return shobs

Fetch/create the instance of this class for the current activity.

player_material: _ba.Material

a ba.Material to be applied to player parts. Generally, materials related to the process of scoring when reaching a goal, etc will look for the presence of this material on things that hit them.

object_material: _ba.Material

A ba.Material that should be applied to any small, normal, physical objects such as bombs, boxes, players, etc. Other materials often check for the presence of this material as a prerequisite for performing certain actions (such as disabling collisions between initially-overlapping objects)

pickup_material: _ba.Material

A ba.Material; collision shapes used for picking things up will have this material applied. To prevent an object from being picked up, you can add a material that disables collisions against things containing this material.

footing_material: _ba.Material

Anything that can be 'walked on' should have this ba.Material applied; generally just terrain and whatnot. A character will snap upright whenever touching something with this material so it should not be applied to props, etc.

attack_material: _ba.Material

A ba.Material applied to explosion shapes, punch shapes, etc. An object not wanting to receive impulse/etc messages can disable collisions against this material.

death_material: _ba.Material

A ba.Material that sends a ba.DieMessage() to anything that touches it; handy for terrain below a cliff, etc.

region_material: _ba.Material

A ba.Material used for non-physical collision shapes (regions); collisions can generally be allowed with this material even when initially overlapping since it is not physical.

railing_material: _ba.Material

A ba.Material with a very low friction/stiffness/etc that can be applied to invisible 'railings' useful for gently keeping characters from falling off of cliffs.