Projectile

class pygamelib.board_items.Projectile(name='projectile', direction=Direction.RIGHT, step=1, range=5, model='⌁', movement_animation=None, hit_animation=None, hit_model=None, hit_callback=None, is_aoe=False, aoe_radius=0, parent=None, callback_parameters=None, movement_speed=0.15, collision_exclusions=None, **kwargs)

Bases: Movable

A class representing a projectile type board item. That class can be sub-classed to represent all your needs (fireballs, blasters shots, etc.).

That class support the 2 types of representations: model and animations. The animation cases are slightly more evolved than the regular item.animation. It does use the item.animation but with more finesse as a projectile can travel in many directions. So it also keeps track of models and animation per travel direction.

You probably want to subclass Projectile. It is totally ok to use it as it, but it is easier to create a subclass that contains all your Projectile information and let the game engine deal with orientation, range keeping, etc. Please see examples/07_projectiles.py for a good old fireball example.

By default, Projectile travels in straight line in one direction. This behavior can be overwritten by setting a specific actuator (a projectile is a Movable so you can use my_projectile.actuator).

The general way to use it is as follow:

  • Create a factory object with your static content (usually the static models, default direction and hit callback)

  • Add the direction related models and/or animation (keep in mind that animation takes precedence over static models)

  • deep copy that object when needed and add it to the projectiles stack of the game object.

  • use Game.actuate_projectiles(level) to let the Game engine do the heavy lifting.

The Projectile constructor takes the following parameters:

Parameters:
  • direction (Direction) – A direction from the constants module

  • range (int) – The maximum range of the projectile in number of cells that can be crossed. When range is attained the hit_callback is called with a BoardItemVoid as a collision object.

  • step (int) – the amount of cells a projectile can cross in one turn

  • model (str) – the default model of the projectile.

  • movement_animation (Animation) – the default animation of a projectile. If a projectile is sent in a direction that has no explicit and specific animation, then movement_animation is used if defined.

  • hit_animation (Animation) – the animation used when the projectile collide with something.

  • hit_model (str) – the model used when the projectile collide with something.

  • hit_callback (function) – A reference to a function that will be called upon collision. The hit_callback is receiving the object it collides with as first parameter.

  • is_aoe (bool) – Is this an ‘area of effect’ type of projectile? Meaning, is it doing something to everything around (mass heal, exploding rocket, fireball, etc.)? If yes, you must set that parameter to True and set the aoe_radius. If not, the Game object will only send the colliding object in front of the projectile.

  • aoe_radius (int) – the radius of the projectile area of effect. This will force the Game object to send a list of all objects in that radius.

  • callback_parameters (list) – A list of parameters to pass to hit_callback.

  • movement_speed (int|float) – The movement speed of the projectile

  • collision_exclusions (list) – A list of TYPES of objects that should not collides with that projectile. It is usually a good idea to put the projectile type in the exclusion list. This prevent the projectile to collide with other instances of itself. Adding the projectile’s emitter is also a valid idea.

  • parent – The parent object (usually a Board object or some sort of BoardItem).

Important

The effects of a Projectile are determined by the callback. No callback == no effect!

Example:

fireball = Projectile(
                        name="fireball",
                        model=Utils.red_bright(black_circle),
                        hit_model=graphics.Models.EXPLOSION,
                        # won't collide with other projectiles.
                        collision_exclusions = [Projectile],
                    )
fireball.set_direction(Direction.RIGHT)
my_game.add_projectile(1, fireball,
                       my_game.player.pos[0], my_game.player.pos[1] + 1)
__init__(name='projectile', direction=Direction.RIGHT, step=1, range=5, model='⌁', movement_animation=None, hit_animation=None, hit_model=None, hit_callback=None, is_aoe=False, aoe_radius=0, parent=None, callback_parameters=None, movement_speed=0.15, collision_exclusions=None, **kwargs)

Like the object class, this class constructor takes no parameter.

Methods

__init__([name, direction, step, range, ...])

Like the object class, this class constructor takes no parameter.

add_directional_animation(direction, animation)

Add an animation for a specific direction.

add_directional_model(direction, model)

Add an model for a specific direction.

attach(observer)

Attach an observer to this instance.

can_move()

Movable implements can_move().

collides_with(other[, projection_offset])

Tells if this item collides with another item.

debug_info()

Return a string with the list of the attributes and their current value.

detach(observer)

Detach an observer from this instance.

directional_animation(direction)

Return the animation for a specific direction.

directional_model(direction)

Return the model for a specific direction.

display()

Print the model WITHOUT carriage return.

distance_to(other)

Calculates the distance with an item.

handle_notification(subject[, attribute, value])

A virtual method that needs to be implemented by the observer.

has_inventory()

Projectile cannot have inventory by default.

hit(objects)

A method that is called when the projectile hit something.

load(data)

Load data and create a new Movable out of it.

notify([modifier, attribute, value])

Notify all the observers that a change occurred.

overlappable()

Projectile are overlappable by default.

pickable()

Returns True if the item is pickable, False otherwise.

position_as_vector()

Returns the current item position as a Vector2D

remove_directional_animation(direction)

Remove an animation for a specific direction.

remove_directional_model(direction)

Remove the model for a specific direction.

render_to_buffer(buffer, row, column, ...)

Render the board item into a display buffer (not a screen buffer).

restorable()

We assume that by default, Projectiles are restorable.

serialize()

Serialize the Immovable object.

set_can_move(value)

Set the value of the can_move property to value.

set_direction(direction)

Set the direction of a projectile

set_overlappable(value)

Set the value of the overlappable property to value.

set_pickable(value)

Set the value of the pickable property to value.

set_restorable(value)

Set the value of the restorable property to value.

store_position(row, column[, layer])

Store the BoardItem position for self access.

store_screen_position(row, column)

Store the screen position of the object.

Attributes

animation

A property to get and set an Animation for this item.

column

Convenience method to get the current stored column of the item.

direction

The direction of the projectile.

dtmove

heading

Return the heading of the item.

height

Convenience method to get the height of the item.

inventory_space

A property to get and set the size that the BoardItem takes in the Inventory.

layer

Convenience method to get the current stored layer number of the item.

model

particle_emitter

row

Convenience method to get the current stored row of the item.

screen_column

A property to get/set the screen column.

screen_row

A property to get/set the screen row.

size

A read-only property that gives the size of the item as a 2 dimensions list.

width

Convenience method to get the width of the item.

add_directional_animation(direction, animation)

Add an animation for a specific direction.

Parameters:
  • direction (int) – A direction from the constants module.

  • animation (Animation) – The animation for the direction

Example:

fireball.add_directional_animation(Direction.UP, Direction.UP, animation)
add_directional_model(direction, model)

Add an model for a specific direction.

Parameters:
  • direction (int) – A direction from the constants module.

  • model (str) – The model for the direction

Example:

fireball.add_directional_animation(Direction.UP, upward_animation)
property animation

A property to get and set an Animation for this item.

Important

When an animation is set, the item is setting the animation’s parent to itself.

attach(observer)

Attach an observer to this instance. It means that until it is detached, it will be notified every time that a notification is issued (usually on changes).

An object cannot add itself to the list of observers (to avoid infinite recursions).

Parameters:

observer (PglBaseObject) – An observer to attach to this object.

Returns:

True or False depending on the success of the operation.

Return type:

bool

Example:

myboard = Board()
screen = Game.instance().screen
# screen will be notified of all changes in myboard
myboard.attach(screen)
can_move() bool

Movable implements can_move().

Returns:

True

Return type:

Boolean

collides_with(other, projection_offset: Vector2D = None)

Tells if this item collides with another item.

Important

collides_with() does not take the layer into account! It is not desirable for the pygamelib to assume that 2 items on different layers wont collide. For example, if a player is over a door, they are on different layers, but logically speaking they are colliding. The player is overlapping the door. Therefor, it is the responsibility of the developer to check for layers in collision, if it is important to the game logic.

Parameters:
  • other (BoardItem) – The item you want to check for collision.

  • projection_offset (Vector2D) – A vector to offset this board item’s position (not the position of the other item). Use this to detect a collision before moving the board item. You can pass the movement vector before moving to check if a collision will occur when moving.

Return type:

bool

Example:

if projectile.collides_with(game.player):
    game.player.hp -= 5
property column

Convenience method to get the current stored column of the item.

This is absolutely equivalent to access to item.pos[1].

Returns:

The column coordinate

Return type:

int

Example:

if item.column != item.pos[1]:
    print('Something extremely unlikely just happened...')
debug_info()

Return a string with the list of the attributes and their current value.

Return type:

str

detach(observer)

Detach an observer from this instance. If observer is not in the list this returns False.

Parameters:

observer (PglBaseObject) – An observer to detach from this object.

Returns:

True or False depending on the success of the operation.

Return type:

bool

Example:

# screen will no longer be notified of the changes in myboard.
myboard.detach(screen)
property direction

The direction of the projectile.

Updating this property also updates the UnidirectionalActuator’s direction.

Parameters:

value (int | Vector2D) – some param

Warning

If your projectile uses directional model and/or animation you should use set_direction() to set the projectile direction.

Example:

bullet.direction = Vector2D(0, 1)
directional_animation(direction)

Return the animation for a specific direction.

Parameters:

direction (int) – A direction from the constants module.

Return type:

Animation

Example:

# No more animation for the UP direction
fireball.directional_animation(Direction.UP)
directional_model(direction)

Return the model for a specific direction.

Parameters:

direction (int) – A direction from the constants module.

Return type:

str

Example:

fireball.directional_model(Direction.UP)
display()

Print the model WITHOUT carriage return.

distance_to(other)

Calculates the distance with an item.

Parameters:

other (BoardItem) – The item you want to calculate the distance to.

Returns:

The distance between this item and the other.

Return type:

float

Example:

if npc.distance_to(game.player) <= 2.0:
    npc.seek_and_destroy = True
property dtmove
handle_notification(subject, attribute=None, value=None)

A virtual method that needs to be implemented by the observer. By default it does nothing but each observer needs to implement it if something needs to be done when notified.

This method always receive the notifying object as first parameter. The 2 other parameters are optional and can be None.

You can use the attribute and value as you see fit. You are free to consider attribute as an event and value as the event’s value.

Parameters:
  • subject (PglBaseObject) – The object that has changed.

  • attribute (str) – The attribute that has changed, it is usually a “FQDN style” string. This can be None.

  • value (Any) – The new value of the attribute. This can be None.

has_inventory()

Projectile cannot have inventory by default.

Returns:

False

Return type:

Boolean

property heading

Return the heading of the item.

This is a read only property that is updated by store_position().

The property represent the orientation and movement of the item in the board. It gives the difference between the item’s centroid current and previous position. Thus, giving you both the direction and the distance of the movement. You can get the angle from here.

One of the possible usage of that property is to set the sprite/sprixel/model of a moving item.

Returns:

The heading of the item.

Return type:

Vector2D

Example:

if my_item.heading.column > 0:
    my_item.sprixel.model = item_models["heading_right"]

Warning

Just after placing an item on the board, and before moving it, the heading cannot be trusted! The heading represent the direction and orientation of the movement, therefore, it is not reliable before the item moved.

property height

Convenience method to get the height of the item.

This is absolutely equivalent to access to item.size[1].

Returns:

The height

Return type:

int

Example:

if item.height > board.height:
    print('The item is too big for the board.')
hit(objects)

A method that is called when the projectile hit something.

That method is automatically called by the Game object when the Projectile collide with another object or is at the end of its range.

Here are the call cases covered by the Game object:

  • range is reached without collision and projectile IS NOT an AoE type: hit() is called with a single BoardItemVoid in the objects list.

  • range is reached without collision and projectile IS an AoE type: hit() is called with the list of all objects within aoe_radius (including structures).

  • projectile collide with something and IS NOT an AoE type: hit() is called with the single colliding object in the objects list.

  • projectile collide with something and IS an AoE type: hit() is called with the list of all objects within aoe_radius (including structures).

In turn, that method calls the hit_callback with the following parameters (in that order):

  1. the projectile object

  2. the list of colliding objects (that may contain only one object)

  3. the callback parameters (from the constructor callback_parameters)

Parameters:

objects – A list of objects hit by or around the projectile.

Example:

my_projectile.hit([npc1])
property inventory_space

A property to get and set the size that the BoardItem takes in the Inventory.

Returns:

The size of the item.

Return type:

int

property layer

Convenience method to get the current stored layer number of the item.

This is absolutely equivalent to access to item.pos[2].

Returns:

The layer number

Return type:

int

Example:

if item.layer != item.pos[2]:
    print('Something extremely unlikely just happened...')
classmethod load(data)

Load data and create a new Movable out of it.

Parameters:

data (dict) – Data to create a new movable item (usually generated by serialize())

Returns:

A new complex item.

Return type:

~pygamelib.board_items.Movable

property model
notify(modifier=None, attribute: str = None, value: Any = None) None

Notify all the observers that a change occurred.

Parameters:
  • modifier (PglBaseObject) – An optional parameter that identify the modifier object to exclude it from the notified objects.

  • attribute (str) – An optional parameter that identify the attribute that has changed.

  • value (Any) – An optional parameter that identify the new value of the attribute.

Example:

# This example is silly, you would usually notify other objects from inside
# an object that changes a value that's important for the observers.
color = Color(255,200,125)
color.attach(some_text_object)
color.notify()
overlappable()

Projectile are overlappable by default.

Returns:

True

Return type:

Boolean

property particle_emitter
pickable()

Returns True if the item is pickable, False otherwise.

Example:

if board.item(4,5).pickable():
    print('The item is pickable')
position_as_vector()

Returns the current item position as a Vector2D

Returns:

The position as a 2D vector

Return type:

Vector2D

Example:

gravity = Vector2D(9.81, 0)
next_position = item.position_as_vector() + gravity.unit()
remove_directional_animation(direction)

Remove an animation for a specific direction.

Parameters:

direction (int) – A direction from the constants module.

Example:

# No more animation for the UP direction
fireball.remove_directional_animation(Direction.UP)
remove_directional_model(direction)

Remove the model for a specific direction.

Parameters:

direction (int) – A direction from the constants module.

Example:

fireball.directional_model(Direction.UP)
render_to_buffer(buffer, row, column, height, width)

Render the board item into a display buffer (not a screen buffer).

This method is automatically called by pygamelib.engine.Screen.render().

Parameters:
  • buffer (numpy.array) – A screen buffer to render the item into.

  • row (int) – The row to render in.

  • column (int) – The column to render in.

  • height (int) – The total height of the display buffer.

  • width (int) – The total width of the display buffer.

restorable()

We assume that by default, Projectiles are restorable.

Returns:

True

Return type:

bool

property row

Convenience method to get the current stored row of the item.

This is absolutely equivalent to access to item.pos[0].

Returns:

The row coordinate

Return type:

int

Example:

if item.row != item.pos[0]:
    print('Something extremely unlikely just happened...')
property screen_column: int

A property to get/set the screen column.

Parameters:

value (int) – the screen column

Return type:

int

property screen_row: int

A property to get/set the screen row.

Parameters:

value (int) – the screen row

Return type:

int

serialize() dict

Serialize the Immovable object.

This returns a dictionary that contains all the key/value pairs that makes up the object.

set_can_move(value)

Set the value of the can_move property to value.

Parameters:

value (bool) – The value to set.

Example:

item.set_can_move(False)
set_direction(direction)

Set the direction of a projectile

This method will set a UnidirectionalActuator with the direction. It will also take care of updating the model and animation for the given direction if they are specified.

Parameters:

direction (int) – A direction from the constants module.

Example:

fireball.set_direction(Direction.UP)
set_overlappable(value)

Set the value of the overlappable property to value.

Parameters:

value (bool) – The value to set.

Example:

item.set_overlappable(False)
set_pickable(value)

Set the value of the pickable property to value.

Parameters:

value (bool) – The value to set.

Example:

item.set_pickable(False)
set_restorable(value)

Set the value of the restorable property to value.

Parameters:

value (bool) – The value to set.

Example:

item.set_restorable(False)
property size

A read-only property that gives the size of the item as a 2 dimensions list. The first element is the width and the second the height.

Returns:

The size.

Return type:

list

Example:

# This is a silly example because the Board object does not allow
# that use case.
if item.column + item.size[0] >= board.width:
    Game.instance().screen.display_line(
        f"{item.name} cannot be placed at {item.pos}."
    )
store_position(row: int, column: int, layer: int = 0)

Store the BoardItem position for self access.

The stored position is used for consistency and quick access to the self position. It is a redundant information and might not be synchronized.

Parameters:
  • row (int) – the row of the item in the Board.

  • column (int) – the column of the item in the Board.

  • layer – the layer of the item in the Board. By default layer is set to 0.

Example:

item.store_position(3,4)
store_screen_position(row: int, column: int) bool

Store the screen position of the object.

This method is automatically called by Screen.place().

Parameters:
  • row (int) – The row (or y) coordinate.

  • column (int) – The column (or x) coordinate.

Example:

an_object.store_screen_coordinate(3,8)
property width

Convenience method to get the width of the item.

This is absolutely equivalent to access to item.size[0].

Returns:

The width

Return type:

int

Example:

if item.width > board.width:
    print('The item is too big for the board.')