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

Various common components for use in games.

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

@classmethod
def get(cls) -> SharedObjects:
42    @classmethod
43    def get(cls) -> SharedObjects:
44        """Fetch/create the instance of this class for the current activity."""
45        activity = bs.getactivity()
46        shobs = activity.customdata.get(cls._STORENAME)
47        if shobs is None:
48            shobs = SharedObjects()
49            activity.customdata[cls._STORENAME] = shobs
50        assert isinstance(shobs, SharedObjects)
51        return shobs

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

player_material: _bascenev1.Material
53    @property
54    def player_material(self) -> bs.Material:
55        """a bascenev1.Material to be applied to player parts. Generally,
56        materials related to the process of scoring when reaching a goal, etc
57        will look for the presence of this material on things that hit them.
58        """
59        if self._player_material is None:
60            self._player_material = bs.Material()
61        return self._player_material

a bascenev1.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: _bascenev1.Material
63    @property
64    def object_material(self) -> bs.Material:
65        """A bascenev1.Material that should be applied to any small,
66        normal, physical objects such as bombs, boxes, players, etc. Other
67        materials often check for the  presence of this material as a
68        prerequisite for performing certain actions (such as disabling
69        collisions between initially-overlapping objects)
70        """
71        if self._object_material is None:
72            self._object_material = bs.Material()
73        return self._object_material

A bascenev1.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: _bascenev1.Material
75    @property
76    def pickup_material(self) -> bs.Material:
77        """A bascenev1.Material; collision shapes used for picking things
78        up will have this material applied. To prevent an object from being
79        picked up, you can add a material that disables collisions against
80        things containing this material.
81        """
82        if self._pickup_material is None:
83            self._pickup_material = bs.Material()
84        return self._pickup_material

A bascenev1.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: _bascenev1.Material
86    @property
87    def footing_material(self) -> bs.Material:
88        """Anything that can be 'walked on' should have this
89        bascenev1.Material applied; generally just terrain and whatnot.
90        A character will snap upright whenever touching something with this
91        material so it should not be applied to props, etc.
92        """
93        if self._footing_material is None:
94            self._footing_material = bs.Material()
95        return self._footing_material

Anything that can be 'walked on' should have this bascenev1.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: _bascenev1.Material
 97    @property
 98    def attack_material(self) -> bs.Material:
 99        """A bascenev1.Material applied to explosion shapes, punch
100        shapes, etc.  An object not wanting to receive impulse/etc messages can
101        disable collisions against this material.
102        """
103        if self._attack_material is None:
104            self._attack_material = bs.Material()
105        return self._attack_material

A bascenev1.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: _bascenev1.Material
107    @property
108    def death_material(self) -> bs.Material:
109        """A bascenev1.Material that sends a ba.DieMessage() to anything
110        that touches it; handy for terrain below a cliff, etc.
111        """
112        if self._death_material is None:
113            mat = self._death_material = bs.Material()
114            mat.add_actions(
115                ('message', 'their_node', 'at_connect', bs.DieMessage())
116            )
117        return self._death_material

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

region_material: _bascenev1.Material
119    @property
120    def region_material(self) -> bs.Material:
121        """A bascenev1.Material used for non-physical collision shapes
122        (regions); collisions can generally be allowed with this material even
123        when initially overlapping since it is not physical.
124        """
125        if self._region_material is None:
126            self._region_material = bs.Material()
127        return self._region_material

A bascenev1.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: _bascenev1.Material
129    @property
130    def railing_material(self) -> bs.Material:
131        """A bascenev1.Material with a very low friction/stiffness/etc
132        that can be applied to invisible 'railings' useful for gently keeping
133        characters from falling off of cliffs.
134        """
135        if self._railing_material is None:
136            mat = self._railing_material = bs.Material()
137            mat.add_actions(('modify_part_collision', 'collide', False))
138            mat.add_actions(('modify_part_collision', 'stiffness', 0.003))
139            mat.add_actions(('modify_part_collision', 'damping', 0.00001))
140            mat.add_actions(
141                conditions=('they_have_material', self.player_material),
142                actions=(
143                    ('modify_part_collision', 'collide', True),
144                    ('modify_part_collision', 'friction', 0.0),
145                ),
146            )
147        return self._railing_material

A bascenev1.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.