earwax.mapping package¶
Submodules¶
Module contents¶
Mapping functions and classes for Earwax.
This module is inspired by Camlorn’s post at this link.
All credit goes to him for the idea.
-
class
earwax.mapping.
Box
(game: Game, start: earwax.point.Point, end: earwax.point.Point, name: Optional[str] = None, surface_sound: Optional[pathlib.Path] = None, wall_sound: Optional[pathlib.Path] = None, type: earwax.mapping.box.BoxTypes = NOTHING, data: Optional[T] = None, stationary: bool = NOTHING, reverb: Optional[object] = NOTHING, box_level: Optional[BoxLevel] = None)¶ Bases:
typing.Generic
,earwax.mixins.RegisterEventMixin
A box on a map.
You can create instances of this class either singly, or by using the
earwax.Box.create_row()
method.If you already have a list of boxes, you can fit them all onto one map with the
earwax.Box.create_fitted()
method.Boxes can be assigned arbitrary user data:
b: Box[Enemy] = Box(start, end, data=Enemy()) b.data.do_something()
In addition to the coordinates supplied to this class’s constructor, a
earwax.BoxBounds
instance is created asearwax.Box.bounds
.This class uses the pyglet.event framework, so you can register and dispatch events in the same way you would with
pyglet.window.Window
, or any otherEventDispatcher
subclass.Variables: - game – The game that this box will work with.
- start – The coordinates at the bottom rear left corner of this box.
- end – The coordinates at the top front right corner of this box.
- name – An optional name for this box.
- surface_sound – The sound that should be heard when walking in this box.
- wall_sound – The sound that should be heard when colliding with walls in this box.
- type – The type of this box.
- data – Arbitrary data for this box.
- bounds – The bounds of this box.
- centre – The point that lies at the centre of this box.
- reverb – The reverb that is assigned to this box.
-
close
() → None¶ Close the attached door.
If this box is a door, set the
open
attribute of itsdata
toFalse
, and play the appropriate sound. Otherwise, raiseearwax.NotADoor
.Parameters: door – The door to close.
-
contains_point
(coordinates: earwax.point.Point) → bool¶ Return whether or not this box contains the given point.
Returns
True
if this box spans the given coordinates,False
otherwise.Parameters: coordinates – The coordinates to check.
-
could_fit
(box: earwax.mapping.box.Box) → bool¶ Return whether or not the given box could be contained by this one.
Returns
True
if the given box could be contained by this box,False
otherwise.This method behaves like the
contains_point()
method, except that it works withBox
instances, rather thanPoint
instances.This method simply checks that the
start
andend
points would fit inside this box.Parameters: box – The box whose bounds will be checked.
-
classmethod
create_fitted
(game: Game, children: List[Box], pad_start: Optional[earwax.point.Point] = None, pad_end: Optional[earwax.point.Point] = None, **kwargs) → BoxType¶ Return a box that fits all of
children
inside itself.Pass a list of
Box
instances, and you’ll get a box with itsstart
, andend
attributes set to match the outer bounds of the provided children.You can use
pad_start
, andpad_end
to add or subtract from the calculated start and end coordinates.Parameters: - children – The list of
Box
instances to encapsulate. - pad_start – A point to add to the calculated start coordinates.
- pad_end – A point to add to the calculated end coordinates.
- kwargs – The extra keyword arguments to pass to
Box.__init__
.
- children – The list of
-
classmethod
create_row
(game: Game, start: earwax.point.Point, size: earwax.point.Point, count: int, offset: earwax.point.Point, get_name: Optional[Callable[[int], str]] = None, on_create: Optional[Callable[[Box], None]] = None, **kwargs) → List[BoxType]¶ Generate a list of boxes.
This method is useful for creating rows of buildings, or rooms on a corridor to name a couple of examples.
It can be used like so:
offices = Box.create_row( game, # Every Box instance needs a game. Point(0, 0), # The bottom_left corner of the first box. Point(3, 2, 0), # The size of each box. 3, # The number of boxes to build. # The next argument is how far to move from the top right # corner of each created box: Point(1, 0, 0), # We want to name each room. For that, there is a function! get_name=lambda i: f'Room {i + 1}', # Let's make them all rooms. type=RoomTypes.room )
This will result in a list containing 3 rooms:
- The first from (0, 0, 0) to (2, 1, 0)
- The second from (3, 0, 0) to (5, 1, 0)
- And the third from (6, 0, 0) to (8, 1, 0)
PLEASE NOTE: If none of the size coordinates are
>= 1
, the top right coordinate will be less than the bottom left, soget_containing_box()
won’t ever find it.Parameters: - start – The
start
coordinate of the first box. - size – The size of each box.
- count – The number of boxes to build.
- offset –
The distance between the boxes.
If no coordinate of the given value is
>= 1
, overlaps will occur. - get_name –
A function which should return an appropriate name.
This function will be called with the current position in the loop.
0 for the first room, 1 for the second, and so on.
- on_create –
A function which will be called after each box is created.
The only provided argument will be the box that was just created.
- kwargs – Extra keyword arguments to be passed to
Box.__init__
.
-
get_nearest_point
(point: earwax.point.Point) → earwax.point.Point¶ Return the point on this box nearest to the provided point.
Parameters: point – The point to start from.
-
handle_door
() → None¶ Open or close the door attached to this box.
-
handle_portal
() → None¶ Activate a portal attached to this box.
-
is_door
¶ Return
True
if this box is a door.
-
is_portal
¶ Return
True
if this box is a portal.
-
is_wall
(p: earwax.point.Point) → bool¶ Return
True
if the provided point is inside a wall.Parameters: p – The point to interrogate.
-
classmethod
maze
(game: Game, grid: ndarray, box_height: int = 3) → Generator[Box, None, None]¶ Return a generator containing a list of boxes.
This constructor supports mazes generated by mazelib for example.
-
on_activate
() → None¶ Handle the enter key.
This event is dispatched when the player presses the enter key.
It is guaranteed that the instance this event is dispatched on is the one the player is stood on.
-
on_close
() → None¶ Handle this box being closed.
-
on_collide
(coordinates: earwax.point.Point) → None¶ Play an appropriate wall sound.
This function will be called by the Pyglet event framework, and should be called when a player collides with this box.
-
on_footstep
(bearing: float, coordinates: earwax.point.Point) → None¶ Play an appropriate surface sound.
This function will be called by the Pyglet event framework, and should be called when a player is walking on this box.
This event is dispatched by
earwax.BoxLevel.move
upon a successful move.Parameters: coordinates – The coordinates the player has just moved to.
-
on_open
() → None¶ Handle this box being opened.
-
open
() → None¶ Open the attached door.
If this box is a door, set the
open
attribute of itsdata
toTrue
, and play the appropriate sound. Otherwise, raiseearwax.NotADoor
.Parameters: box – The box to open.
-
scheduled_close
(dt: float) → None¶ Call
close()
.This method will be called by
pyglet.clock.schedule_once
.Parameters: dt – The dt
parameter expected by Pyglet’s schedule functions.
-
sound_manager
¶ Return a suitable sound manager.
-
class
earwax.mapping.
BoxBounds
(bottom_back_left: earwax.point.Point, top_front_right: earwax.point.Point)¶ Bases:
object
Bounds for a
earwax.Box
instance.Variables: - bottom_back_left – The bottom back left point.
- top_front_right – The top front right point.
- bottom_front_left – The bottom front left point.
- bottom_front_right – The bottom front right point.
- bottom_back_right – The bottom back right point.
- top_back_left – The top back left point.
- top_front_left – The top front left point.
- top_back_right – The top back right point.
-
area
¶ Return the area of the box.
-
depth
¶ Get the depth of this box (front to back).
-
height
¶ Return the height of this box.
-
is_edge
(p: earwax.point.Point) → bool¶ Return
True
ifp
represents an edge.Parameters: p – The point to interrogate.
-
volume
¶ Return the volume of this box.
-
width
¶ Return the width of this box.
-
class
earwax.mapping.
BoxTypes
¶ Bases:
enum.Enum
The type of a box.
Variables: - empty –
Empty space.
Boxes of this type can be traversed wit no barriers.
- room –
An open room with walls around the edge.
Boxes of this type can be entered by means of a door. The programmer must provide some means of exit.
- solid –
Signifies a solid, impassible barrier.
Boxes of this type cannot be traversed.
-
empty
= 0¶
-
room
= 1¶
-
solid
= 2¶
- empty –
-
exception
earwax.mapping.
NotADoor
¶ Bases:
earwax.mapping.box.BoxError
The current box is not a door.
-
exception
earwax.mapping.
NotAPortal
¶ Bases:
earwax.mapping.box.BoxError
The current box is not a portal.
-
class
earwax.mapping.
BoxLevel
(game: Game, boxes: List[earwax.mapping.box.Box[typing.Any][Any]] = NOTHING, coordinates: earwax.point.Point = NOTHING, bearing: int = 0, current_box: Optional[earwax.mapping.box_level.CurrentBox] = None)¶ Bases:
earwax.level.Level
A level that deals with sound generation for boxes.
This level can be used in your games. Simply bind the various action methods (listed below) to whatever triggers suit your purposes.
Some of the attributes of this class refer to a “perspective”. This could theoretically be anything you want, but most likely refers to the player. Possible exceptions include if you made an instance to represent some kind of long range vision for the player.
Action-ready Methods
move()
.show_coordinates()
show_facing()
turn()
show_nearest_door()
describe_current_box()
Variables: - box – The box that this level will work with.
- coordinates – The coordinates of the perspective.
- bearing – The direction the perspective is facing.
- current_box –
The most recently walked over box.
If you don’t set this attribute when creating the instance, then the first time the player moves using the
move()
method, the name of the box they are standing on will be spoken. - reverb –
An optional reverb to play sounds through.
You shouldn’t write to this property, instead use the
connect_reverb()
method to set a new reverb, anddisconnect_reverb()
to clear.
-
activate
(door_distance: float = 2.0) → Callable[[], None]¶ Return a function that can be call when the enter key is pressed.
First we check if the current box is a portal. If it is, then we call
handle_portal()
.If it is not, we check to see if there is a door close enough to be opened or closed. If there is, then we call
handle_door()
on it.If none of this works, and there is a current box, dispatch the
on_activate()
event to let the box do its own thing.Parameters: door_distance – How close doors have to be for this method to open or close them.
-
add_box
(box: earwax.mapping.box.Box[typing.Any][Any]) → None¶ Add a box to
self.boxes
.Parameters: box – The box to add.
-
add_boxes
(boxes: Iterable[earwax.mapping.box.Box]) → None¶ Add multiple boxes with one call.
Parameters: boxes – An iterable for boxes to add.
-
add_default_actions
() → None¶ Add some default actions.
This method adds the following actions:
- Move forward: W
- Turn 180 degrees: S
- Turn 45 degrees left: A
- Turn 45 degrees right: D
- Show coordinates: C
- Show the facing direction: F
- Describe current box: X
- Speak nearest door: Z
- Activate nearby objects: Return
-
calculate_coordinates
(distance: float, bearing: int) → Tuple[float, float]¶ Calculate coordinates at the given distance in the given direction.
Used by
move()
to calculate new coordinates.Override this method if you want to change the algorithm used to calculate the target coordinates.
Please bear in mind however, that the coordinates this method returns should always be 2d.
Parameters: - distance – The distance which should be used.
- bearing –
The bearing the new coordinates are in.
This value may not be the same as
self.bearing
.
-
collide
(box: earwax.mapping.box.Box[typing.Any][Any], coordinates: earwax.point.Point) → None¶ Handle collitions.
Called to run collision code on a box.
Parameters: - box – The box the player collided with.
- coordinates – The coordinates the player was trying to reach.
-
describe_current_box
() → None¶ Describe the current box.
-
get_angle_between
(other: earwax.point.Point) → float¶ Return the angle between the perspective and the other coordinates.
This function takes into account
self.bearing
.Parameters: other – The target coordinates.
-
get_boxes
(t: Any) → List[earwax.mapping.box.Box]¶ Return a list of boxes of the current type.
If no boxes are found, an empty list is returned.
Parameters: t – The type of the boxes.
-
get_containing_box
(coordinates: earwax.point.Point) → Optional[earwax.mapping.box.Box]¶ Return the box that spans the given coordinates.
If no box is found,
None
will be returned.This method scans
self.boxes
using thesort_boxes()
method.Parameters: coordinates – The coordinates the box should span.
-
get_current_box
() → Optional[earwax.mapping.box.Box]¶ Get the box that lies at the current coordinates.
-
handle_box
(box: earwax.mapping.box.Box[typing.Any][Any]) → None¶ Handle a bulk standard box.
The coordinates have already been set, and the
on_footstep
event dispatched, so all that is left is to speak the name of the new box, if it is different to the last one, updateself.reverb
if necessary, and store the new box.
-
move
(distance: float = 1.0, vertical: Optional[float] = None, bearing: Optional[int] = None) → Callable[[], None]¶ Return a callable that allows the player to move on the map.
If the move is successful (I.E.: There is a box at the destination coordinates), the
on_move()
event is dispatched.If not, then
on_move_fail()
is dispatched.Parameters: - distance – The distance to move.
- vertical – An optional adjustment to be added to the vertical position.
- bearing –
An optional direction to move in.
If this value is
None
, thenself.bearing
will be used.
-
nearest_by_type
(start: earwax.point.Point, data_type: Any, same_z: bool = True) → Optional[earwax.mapping.box_level.NearestBox]¶ Get the nearest box to the given point by type.
If no boxes of the given type are found,
None
will be returned.Parameters: - start – The point to start looking from.
- data_type – The type of
box data
to search for. - same_z – If this value is
True
, only boxes on the same z axis will be considered.
-
nearest_door
(start: earwax.point.Point, same_z: bool = True) → Optional[earwax.mapping.box_level.NearestBox]¶ Get the nearest door.
Iterates over all doors, and returned the nearest one.
Parameters: - start – The coordinates to start from.
- same_z – If
True
, then doors on different levels will not be considered.
-
nearest_portal
(start: earwax.point.Point, same_z: bool = True) → Optional[earwax.mapping.box_level.NearestBox]¶ Return the nearest portal.
Parameters: - start – The coordinates to start from.
- same_z – If
True
, then portals on different levels will not be considered.
-
on_move_fail
(distance: float, vertical: Optional[float], bearing: int, coordinates: earwax.point.Point) → None¶ Handle a move failure.
An event that will be dispatched when the
move()
action has been used, but no move was performed.Parameters: - distance – The
distance
value that was passed tomove()
. - vertical – The
vertical
value that was passed tomove
. - bearing – The
bearing
argument that was passed tomove
, orself.bearing
.
- distance – The
-
on_move_success
() → None¶ Handle a successful move.
An event that will be dispatched when the
move()
action is used.By default, this method plays the correct footstep sound.
-
on_push
() → None¶ Set listener orientation, and start ambiances and tracks.
-
on_turn
() → None¶ Handle turning.
An event that will dispatched when the
turn()
action is used.
-
register_box
(box: earwax.mapping.box.Box) → None¶ Register a box that is already in the boxes list.
Parameters: box – The box to register.
-
remove_box
(box: earwax.mapping.box.Box[typing.Any][Any]) → None¶ Remove a box from
self.boxes
.Parameters: box – The box to remove.
-
set_bearing
(angle: int) → None¶ Set the direction of travel and the listener’s orientation.
Parameters: angle – The bearing (in degrees).
-
set_coordinates
(p: earwax.point.Point) → None¶ Set the current coordinates.
Also set listener position.
Parameters: p – The new point to assign to self.coordinates
.
-
show_coordinates
(include_z: bool = False) → Callable[[], None]¶ Speak the current coordinates.
-
show_facing
(include_angle: bool = True) → Callable[[], None]¶ Return a function that will let you see the current bearing as text.
For example:
l = BoxLevel(...) l.action('Show facing', symbol=key.F)(l.show_facing())
Parameters: include_angle – If True
, then the actual angle will be shown along with the direction name.
-
show_nearest_door
(max_distance: Optional[float] = None) → Callable[[], None]¶ Return a callable that will speak the position of the nearest door.
Parameters: max_distance – The maximum distance between the current coordinates and the nearest door where the door will still be reported.
If this value is
None
, then any door will be reported.
-
sort_boxes
() → List[earwax.mapping.box.Box]¶ Return
children
sorted by area.
-
turn
(amount: int) → Callable[[], None]¶ Return a turn function.
Return a function that will turn the perspective by the given amount and dispatch the
on_turn
event.For example:
l = BoxLevel(...) l.action('Turn right', symbol=key.D)(l.turn(45)) l.action('Turn left', symbol=key.A)(l.turn(-45))
The resulting angle will always be in the range 0-359.
Parameters: amount – The amount to turn by.
Positive numbers turn clockwise, while negative numbers turn anticlockwise.
-
walls_between
(end: earwax.point.Point, start: Optional[earwax.point.Point] = None) → int¶ Return the number of walls between two points.
Parameters: - end – The target coordinates.
- start –
The coordinates to start at.
If this value is
None
, then the currentcoordinates
will be used.
-
class
earwax.mapping.
CurrentBox
(coordinates: earwax.point.Point, box: earwax.mapping.box.Box[typing.Any][Any])¶ Bases:
object
Store a reference to the current box.
This class stores the position too, so that caching can be performed.
Variables: - coordinates – The coordinates that were last checked.
- box – The last current box.
-
class
earwax.mapping.
NearestBox
(box: earwax.mapping.box.Box, coordinates: earwax.point.Point, distance: float)¶ Bases:
object
A reference to the nearest box.
Variables: - box – The box that was found.
- coordinates – The nearest coordinates to the ones specified.
- distance – The distance between the supplied
coordinates, and
coordinates
.
-
class
earwax.mapping.
Door
(open: bool = True, closed_sound: Optional[pathlib.Path] = None, open_sound: Optional[pathlib.Path] = None, close_sound: Optional[pathlib.Path] = None, close_after: Union[float, Tuple[float, float], None] = None, can_open: Optional[Callable[[], bool]] = None, can_close: Optional[Callable[[], bool]] = None)¶ Bases:
object
An object that can be added to a box to optionally block travel.
Doors can currently either be open or closed. When opened, they can optionally close after a specified time:
Door() # Standard open door. Door(open=False) # Closed door. Door(close_after=5.0) # Will automatically close after 5 seconds. # A door that will automatically close between 5 and 10 seconds after # it has been opened: Door(close_after=(5.0, 10.0)
Variables: - open –
Whether or not this box can be walked on.
If this value is
False
, then the player will hearclosed_sound
when trying to walk on this box.If this value is
True
, the player will be able to enter the box as normal. - closed_sound – The sound that will be heard if
open
isFalse
. - open_sound – The sound that will be heard when opening this door.
- close_sound – The sound that will be heard when closing this door.
- close_after –
When (if ever) to close the door after it has been opened.
This attribute supports 3 possible values:
None
: The door will not close on its own.- A tuple of two positive floats
a
andb
: A random number - between
a
andb
will be selected, and the door will automatically close after that time.
- A tuple of two positive floats
- A float: The exact time the door will automatically close after.
- can_open –
An optional method which will be used to decide whether or not this door can be opened at this time.
This method must return
True
orFalse
, and must handle any messages which should be sent to the player. - can_close –
An optional method which will be used to decide whether or not this door can be closed at this time.
This method must return
True
orFalse
, and must handle any messages which should be sent to the player.
- open –
-
class
earwax.mapping.
MapEditor
(game: Game, boxes: List[earwax.mapping.box.Box[typing.Any][Any]] = NOTHING, coordinates: earwax.point.Point = NOTHING, bearing: int = 0, current_box: Optional[earwax.mapping.box_level.CurrentBox] = None, filename: Optional[pathlib.Path] = None, context: earwax.mapping.map_editor.MapEditorContext = NOTHING)¶ Bases:
earwax.mapping.box_level.BoxLevel
A level which can be used for editing maps.
When this level talks about a map, it talks about a
earwax.mapping.map_editor.LevelMap
instance.Push a menu to configure the provided box.
-
box_sound
(template: earwax.mapping.map_editor.BoxTemplate, name: str) → Callable[[], Generator[None, None, None]]¶ Push an editor for setting the given sound.
Parameters: - template – The template to modify.
- name – The name of the sound to modify.
-
box_sounds
() → None¶ Push a menu for configuring sounds.
Push a menu to select a box to configure.
If there is only 1 box, it will not be shown.
-
complain_box
() → None¶ Complain about there being no box.
-
create_box
() → None¶ Create a box, then call
box_menu()
.
-
get_default_context
() → earwax.mapping.map_editor.MapEditorContext¶ Return a suitable context.
-
id_box
() → Generator[None, None, None]¶ Change the ID for the current box.
-
label_box
() → Generator[None, None, None]¶ Rename the current box.
-
on_move_fail
(distance: float, vertical: Optional[float], bearing: int, coordinates: earwax.point.Point) → None¶ Tell the user their move failed.
Push a menu for configuring individual points.
Push a menu for moving the current box.
-
rename_box
() → Generator[None, None, None]¶ Rename the current box.
-
save
() → None¶ Save the map level.
-
class
earwax.mapping.
MapEditorContext
(level: MapEditor, level_map: earwax.mapping.map_editor.LevelMap, template_ids: Dict[str, earwax.mapping.map_editor.BoxTemplate] = NOTHING, box_ids: Dict[str, earwax.mapping.box.Box[str][str]] = NOTHING)¶ Bases:
object
A context to hold map information.
This class acts as an interface between a
LevelMap
instance, and aMapEditor
instance.-
add_template
(template: earwax.mapping.map_editor.BoxTemplate, box: Optional[earwax.mapping.map_editor.MapEditorBox] = None) → None¶ Add a template to this context.
This method will add the given template to its
box_template_ids
dictionary.Parameters: template – The template to add.
-
reload_template
(template: earwax.mapping.map_editor.BoxTemplate) → None¶ Reload the given template.
This method recreates the box associated with the given template.
Parameters: template – The template to reload.
-
to_box
(template: earwax.mapping.map_editor.BoxTemplate) → earwax.mapping.map_editor.MapEditorBox¶ Return a box from a template.
Parameters: template – The template to convert.
-
to_point
(data: earwax.mapping.map_editor.BoxPoint) → earwax.point.Point¶ Return a point from the given data.
Parameters: data – The BoxPoint
to load the point from.
-
-
class
earwax.mapping.
Portal
(level: BoxLevel, coordinates: earwax.point.Point, bearing: Optional[int] = None, enter_sound: Optional[pathlib.Path] = None, exit_sound: Optional[pathlib.Path] = None, can_use: Optional[Callable[[], bool]] = None)¶ Bases:
earwax.mixins.RegisterEventMixin
A portal to another map.
An object that can be added to a
earwax.Box
to make a link between two maps.This class implements
pyglet.event.EventDispatcher
, so events can be registered and dispatched on it.The currently-registered events are:
on_enter()
on_exit()
Variables: - level – The destination level.
- coordinates – The exit coordinates.
- bearing – If this value is
None
, then it will be used for the player’s bearing after this portal is used. Otherwise, the bearing from the old level will be used. - enter_sound –
The sound that should play when entering this portal.
This sound is probably only used when an NPC uses the portal.
- exit_sound –
The sound that should play when exiting this portal.
This is the sound that the player will hear when using the portal.
- can_use –
An optional method which will be called to ensure that this portal can be used at this time.
This function should return
True
orFalse
, and should handle any messages which should be sent to the player.
-
on_enter
() → None¶ Handle a player entering this portal.
-
on_exit
() → None¶ Handle a player exiting this portal.