physics
— A 2D physics system, with rigid bodies, collisions and more!¶
Kaa inlcudes a 2D physics engine which allows you to easily add physical features to objects in your game, handle collisions etc. The idea is based on three types of specialized nodes:
SpaceNode
- it represents physical simulation environment, introducing environmental properties such as gravity or damping.BodyNode
- represents a physical body. Each BodyNode must be a direct child of aphysics.SpaceNode
. BodyNode can have HitboxNodes as child nodes.HitboxNode
- represents an area of a BodyNode which can collide with other HitboxNodes. Must be a direct child of aphysics.BodyNode
.
Read more about the nodes concept in general.
Note
Physics system present in the kaa engine is a wrapper of an excellent 2D physics library - Chipmunk.
SpaceNode
reference¶
-
class
physics.
SpaceNode
(gravity=Vector(0, 0), damping=1, position=Vector(0, 0), rotation=0, scale=Vector(1, 1), z_index=0, color=Color(0, 0, 0, 0), sprite=None, shape=None, origin_alignment=Alignment.center, lifetime=None, transition=None, visible=True)¶ SpaceNode extends the
nodes.Node
. It represents physical simulation environment. All BodyNodes must be direct children of a SpaceNode. Typically you’ll need just one SpaceNode per Scene, but nothing prevents you from adding more. If you decide to use multiple SpaceNodes on a Scene, be aware that they will be isolated (BodyNodes under SpaceNode A won’t be able to interact with BodyNodes under SpaceNode B).Space node is also place where you can register collision handlers (see
SpaceNode.set_collision_handler()
). Collision handlers are your custom functions which will be called when a collision between a pair of defined hitbox nodes occurs.Another feature of the SpaceNode is running spatial queries. You can find hitboxes colliding with a custom shape (
geometry.Circle
,geometry.Polygon
orgeometry.Segment
) viaSpaceNode.query_shape_overlaps()
. You can find hitboxes colliding with a ray cast between points A and B usingSpaceNode.query_ray()
. Finally you can also find hitboxes around a specific point withSpacenNode.query_point_neighbors()
.Constructor accepts all parameters from the base
nodes.Node
class and adds the following new parameters:gravity
- ageometry.Vector
damping
- a number
Instance properties:
-
SpaceNode.
gravity
¶ Gets or sets the gravity inside the SpaceNode, as
geometry.Vector
. Direction of the vector determines the direction of the gravitational force, while it’s length determines gravity strength.Gravity will be applied only to the dynamic BodyNodes. Kinematic and Static BodyNodes do not have mass and therefore are not affected by the gravity.
Default gravity is zero, meaning no gravitational forces applied.
-
SpaceNode.
damping
¶ Gets or sets the damping inside the SpaceNode. Represents a “friction” or a “drag force” inside the environment which slows all BodyNodes down with time. A damping of 0.25 means velocity of all BodyNodes will decrease by a factor of 4 in 1 second. A damping of 1 (default) means no slowdown force applied. A damping greater than 1 will make all BodyNodes accelerate, proportionally to its value.
Damping is applied only to the dynamic BodyNodes. Kinematic and Static BodyNodes do not have mass and therefore ignore the damping effect.
-
SpaceNode.
sleeping_threshold
¶ Gets of sets the sleep time threshold (in seconds) which affects all BodyNodes in the SpaceNode. If given BodyNode remains static (doesn’t change its position or rotation) for that amount of time the engine will stop making physical calculations for it. In some situations it can improve the performance. A body remaining in a sleeping state can still collide with other bodies - that will force it to move and ‘wake up’ as a consequence.
Default value for the sleeping_threshold is infinite, which effectively means that the performance mechanism is disabled.
Instance methods:
-
SpaceNode.
set_collision_handler
(trigger_a, trigger_b, handler_callable)¶ Registers a custom collision handler function between two
HitboxNode
instances, tagged with trigger_a and trigger_b respectively. The function will get called when collision between hitboxes occur.Note, that collisions occur between HitboxNodes (not between BodyNodes!). The
trigger_a
andtrigger_b
params are your own values which you use to tagHitboxNode
. They should be of integer type.handler_callable
is your own callable, it takes the following three parameters:arbiter
- anArbiter
object that holds additional information about collision.collision_pair_a
- aCollisionPair
object that allows identifying which BodyNode and which HitboxNoded collided. Corresponds with HitboxNode identified by trigger_a.collision_pair_b
- aCollisionPair
object that allows identifying which BodyNode and which HitboxNoded collided. Corresponds with HitboxNode identified by trigger_b.
If your collision handler function does not return any value, the collision will occur normally. However if you return 0 in the collision handler AND you do that in the begin or pre_solve phase, then collision will be ignored by the physics engine (no impulses will be applied to colliding objects).
# somwhere in the code... bullet_hitbox = HitboxNode(shape=Circle(radius=10), trigger_id=123, ...... ) # 123 is our own value we give to all bullet hitboxes enemy_hitbox = HitboxNode(shape=Circle(radius=10), trigger_id=456, ...... ) # 456 is our own value we give to all enemy hitboxes # collision handler function: def on_collision_bullet_enemy(arbiter, bullet_pair, enemy_pair): print("Detected a collision between a bullet object's {} hitbox {} and Enemy's object {} hitbox {}".format( bullet_pair.body, bullet_pair.hitbox, enemy_pair.body, enemy_pair.hitbox)) # ... write code to handle the collision effects .... # assuming space_node is <SpaceNode>, # 123 and 456 here are defining which pair of hitbox collisions shall be handled by the on_collision_bullet_enemy # in this case it defines a pair of a bullet hitbox and enemy hitbox space_node.set_collision_handler(123, 456, on_collision_bullet_enemy)
IMPORTANT: Collision handler function can be called multiple times for given pair of colliding objects (even multiple times per frame). This can happen if object’s hitboxes touch for the first time, then they either overlap or touch each other for some time and finally - they separate. The collision handler function will be called every frame, as long as the hitboxes touch or overlap. When they make apart, the collision handler function stops being called.
-
SpaceNode.
query_shape_overlaps
(shape, mask=kaa.physics.COLLISION_BITMASK_ALL, collision_mask=kaa.physics.COLLISION_BITMASK_ALL, group=kaa.physics.COLLISION_GROUP_NONE)¶ Takes a shape (
geometry.Circle
orgeometry.Polygon
) and returns hitboxes which overlap with that shape (either partially or entirely) as well as body nodes which own those hitboxes. The shape coordinates are expected to be in a frame reference relative to the SpaceNode.When running the query, the shape you pass is treated like a hitbox node, therefore parameters such as mask, collision_mask and group behave identically as in
HitboxNode
. It means you can use those params for filtering purpose. Refer to mask, collision_mask and group for more information.The query returns a list of
ShapeQueryResult
objects. EachShapeQueryResult
represents a ‘collision’ of the shape with one hitbox. It holds a reference to hitbox’ parent (body node) and other metadata such as intersection points.from kaa.physics import SpaceNode, BodyNode, HitboxNode from kaa.geometry import Polygon self.space = SpaceNode() self.root.add_child(self.space) body_node = BodyNode(position=Vector(0, 0)) hitbox = HitboxNode(shape=Polygon.from_box(Vector(100, 100))) body_node.add_child(hitbox) self.space.add_child(body_node) # find hitboxes intersecting with our triangular polygon triangle = Polygon([Vector(0, 0), Vector(100, 100), Vector(0, 200) ]) results = self.space.query_shape_overlaps(triangle) for result in results: print(f"Shape {triangle.points} collided with hitbox {result.hitbox.shape.points} owned " f"by {result.body}. Contact points metadata accessible at {result.contact_points}.")
-
SpaceNode.
query_ray
(ray_start, ray_end, radius=0., mask=kaa.physics.COLLISION_BITMASK_ALL, collision_mask=kaa.physics.COLLISION_BITMASK_ALL, group=kaa.physics.COLLISION_GROUP_NONE)¶ A “ray casting” method. Takes in a ray (two Vectors:
ray_start
andray_end
) and returns hitboxes (and their owning BodyNodes) which collide with that ray. The ray coordinates are expected to be in a frame reference relative to the SpaceNode.The
radius
parameter sets the width of the cast ray.When running the query, the ray is treated like a hitbox node, therefore parameters such as mask, collision_mask and group behave identically as in
HitboxNode
. It means you can use those params for filtering purpose. Refer to mask, collision_mask and group for more information.The query returns a list of
RayQueryResult
objects. Each represents a collision of the ray with one hitbox. It holds a reference to hitbox owner (body node) and other metadata such as intersection point.from kaa.physics import SpaceNode, BodyNode, HitboxNode from kaa.geometry import Polygon self.space = SpaceNode() self.root.add_child(self.space) body_node = BodyNode(position=Vector(0, 0)) hitbox = HitboxNode(shape=Polygon.from_box(Vector(100, 100))) body_node.add_child(hitbox) self.space.add_child(body_node) # cast a ray and find hitboxes colliding with the ray results = self.space.query_ray(ray_start=Vector(-200, -200), ray_end=Vector(200,200)) for result in results: print(f"Ray collided with {result.hitbox.shape.points} hitbox owned by {result.body} at " f"{result.point}. Normal was {result.normal} and alpha was {result.alpha}")
-
SpaceNode.
query_point_neighbors
(point, max_distance, mask=kaa.physics.COLLISION_BITMASK_ALL, collision_mask=kaa.physics.COLLISION_BITMASK_ALL, group=kaa.physics.COLLISION_GROUP_NONE)¶ Queries for hitboxes
max_distance
away frompoint
. Thepoint
must be ageometry.Vector
.When running the query, the
point
is treated like a hitbox node, therefore parameters such as mask, collision_mask and group behave identically as inHitboxNode
. It means you can use those params for filtering purpose. Refer to mask, collision_mask and group for more information.The query returns a list of
PointQueryResult
objects which contain collision data such as references to hitbox, its owner body node and other metadata.from kaa.physics import SpaceNode, BodyNode, HitboxNode from kaa.geometry import Polygon self.space = SpaceNode() self.root.add_child(self.space) body_node = BodyNode(position=Vector(0, 0)) hitbox = HitboxNode(shape=Polygon.from_box(Vector(100, 100))) body_node.add_child(hitbox) self.space.add_child(body_node) # find hitboxes in the vicinity of a point point = Vector(-140, 140) results = self.space.query_point_neighbors(point=point, max_distance=200) for result in results: print(f"Point {point} collided with hitbox {result.hitbox.shape.points} owned " f"by {result.body}. Collision point is at {result.point}, distance: {result.distance}")
BodyNode
reference¶
-
class
physics.
BodyNode
(body_type=BodyNodeType.dynamic, force=Vector(0, 0), velocity=Vector(0, 0), mass=20.0, moment=10000.0, torque=0, torque_degrees=0, angular_velocity=0, angular_velocity_degrees=0, position=Vector(0, 0), rotation=0, scale=Vector(1, 1), z_index=0, color=Color(0, 0, 0, 0), sprite=None, shape=None, origin_alignment=Alignment.center, lifetime=None, transition=None, visible=True)¶ BodyNode extends the
nodes.Node
class, introducing physical features.In the nodes tree, BodyNode must be a direct child of a
SpaceNode
.BodyNode is the only node type which can have
HitboxNode
as children nodes.BodyNodes themselves never collide with each other. The need to have HitboxNodes as children to generate collisions. A BodyNode can have multiple HitboxNodes.
BodyNode constructor accepts all parameters from the base
nodes.Node
class and adds the following new parameters:body_type
- aBodyNodeType
enum value. Learn more hereforce
- ageometry.Vector
velocity
- ageometry.Vector
mass
- a numbermoment
- a numbertorque
- a numbertorque_degrees
- a number, alternative totorque
, using degrees instead of radiansangular_velocity
- a numberangular_velocity_degrees
- a number, alternative toangular_velocity
, using degrees instead of radians
Instance properties:
-
BodyNode.
body_type
¶ Gets or sets body type, must be a
BodyNodeType
value. There are three types available:static - the body has infinite mass and won’t move when its hitboxes collide with any other hitboxes. You cannot move it “manually” by setting its velocity or angular velocity either. Those nodes are truly static.
kinematic - similar to static body in a sense that its velocity or rotation will never be affected by anything, e.g. its hitboxes colliding. But the difference is that you can move and rotate that type of body. The collisions will occur normally and you will be able to handle them.
dynamic - the default type. Physics engine will calculate body’s velocity and angular velocity when its hitboxes will collide with other bodies’ hitboxes.
Use static bodies for static obstacles and other elements on the scene that you know won’t move, but you want them to collide with other bodies and block their movement. Those bodies will always have zero velocity and zero angular velocity.
Use kinematic bodies for objects which you want to move but you don’t want their velocity controlled by the physics engine. Those nodes won’t move or rotate on their own. The onus is on you to set their velocity or angular velocity but you still want to be able to detect collisions between them and other objects on the scene.
Use dynamic bodies for freely moving objects that you want physics engine to fully take care of. Dynamic bodies have their velocity and angular velocity calculated by the engine.
Note
Example: a classic space shooter Git Gud or Get Rekt, built with kaa engine is using kinematic bodies for player, enemies, and bullets, and dynamic bodies for debris left on the scene after enemies explode.
-
BodyNode.
force
¶ Gets or sets a custom force applied to the BodyNode, as
geometry.Vector
. The force is reset to zero on each frame, so if you want it to constantly work on the object, you need to apply it on each frame.Applying force affects object’s velocity.
Force has an effect only on dynamic body nodes. Static and kinematic body nodes will not be affected.
-
BodyNode.
local_force
¶ Same as BodyNode.force but uses strictly local frame of reference.
node.rotation_degrees = 0 node.force = Vector(1, 0) # force will drag the object in direction V(1, 0), regardless to node rotation other_node.rotation_degrees = 45 other_node.local_force = Vector(1, 0) # force direction will be calculated AFTER applying the rotation!
-
BodyNode.
velocity
¶ Gets or sets the linear velocity of the BodyNode, as
geometry.Vector
. Linear velocity vector determines the speed and direction of movement of an object.For dynamic body nodes the velocity is calculated by the physics engine. You can override the velocity value calculated by the engine but you should consider applying force instead.
Setting velocity from your code is recommended for kinematic bodies, as they won’t move on their own otherwise.
-
BodyNode.
mass
¶ Gets or sets the mass for the body node. Mass has an effect on the output velocity of dynamic body when it collides with other bodies.
-
BodyNode.
torque
¶ Gets or sets the torque for the body node. Using radians. The torque is reset to zero on each frame, so if you want it to constantly work on the object you need to apply it on each frame.
Applying torque affects object’s angular velocity.
Applying torque has an effect only on dynamic body nodes. Static and kinematic body nodes are not affected.
For degrees use torque_degrees
-
BodyNode.
angular_velocity
¶ Gets or sets the angular velocity for the body node. Using radians. Angular velocity determines how fast the object rotates and the direction of the rotation (clockwise or anticlockwise).
Similarly to velocity the angular velocity is calculated by the physics engine for dynamic body nodes. You can override the angular velocity manually but you should consider applying torque instead.
Setting angular velocity from your code is recommended for kinematic bodies, as they won’t rotate on their own otherwise.
For degrees use angular_velocity_degrees
-
BodyNode.
angular_velocity_degrees
¶ Gets or sets the angular velocity for the body node. Using degrees. See angular_velocity
-
BodyNode.
moment
¶ Gets or sets the moment for the body node. Moment has an effect on the output angular velocity of dynamic body when it collides with other bodies.
-
BodyNode.
sleeping
¶ Gets or sets the sleeping status of the node as bool. If set to
True
it gives the physics engine a performance hint, making it ignore this node when calculating its velocity and angular velocity. The node will wake up automatically when it’s moving or rotating so it doesn’t makes sense to set the sleeping status on a moving or rotating nodes.See also: SpaceNode.sleeping_threshold.
Instance methods:
-
BodyNode.
apply_force_at_local
(force, at)¶ Applies
force
(geometry.Vector
) to this body node at positionat
(geometry.Vector
). Theat
parameter is in a relative frame of reference. For example, ifat
isVector(0, 0)
then the force will be applied at the center of the body node.Note
Applied force will be automatically reset to zero each frame, so if you want to apply force constantly you should do that on each frame.
-
BodyNode.
apply_impulse_at_local
(impulse, at)¶ Applies
impulse
(geometry.Vector
) to this body node at positionat
(geometry.Vector
). Theat
parameter is in a relative frame of reference. For example, ifat
isVector(0, 0)
then the impulse will be applied at the center of the body node.Note
Use impulses when you need to apply a very large force applied over a very short period of time. Some examples are a ball hitting a wall or cannon firing.
-
BodyNode.
apply_force_at
(force, at)¶ Same as
BodyNode.apply_force_at_local()
butat
is in an absolute frame of reference. For instance, if body node’s absolute position is Vector(110, 34) and you want to apply the force at the center of the body, you need to passat=Vector(110, 34)
.
-
BodyNode.
apply_impulse_at
(impulse, at)¶ Same as
BodyNode.apply_impulse_at_local()
butat
is in an absolute frame of reference. For instance, if body node’s absolute position is Vector(110, 34) and you want to apply the impulse at the center of the body, you need to passat=Vector(110, 34)
.
HitboxNode
reference¶
-
class
physics.
HitboxNode
(shape, group=kaa.physics.COLLISION_GROUP_NONE, mask=kaa.physics.COLLISION_BITMASK_ALL, collision_mask=kaa.physics.COLLISION_BITMASK_ALL, trigger_id=None, position=Vector(0, 0), rotation=0, scale=Vector(1, 1), z_index=0, color=Color(0, 0, 0, 0), sprite=None, shape=None, sensor=False, elasticity=0.95, friction=0, surface_velocity=Vector(0, 0), origin_alignment=Alignment.center, lifetime=None, transition=None, visible=True))¶ HitboxNode extends the
Node
class and introduces collision detection features.In the nodes tree, HitboxNode must be a direct child of a
BodyNode
. ABodyNode
can have many HitboxNodes.HitboxNode inherits all
Node
properties and methods, some of which may be particularly useful for debugging. For example, by setting a color and z_index of on a HitboxNode you can make the hitbox visible.Hitbox node has its own specific params, related with collision handling:
shape
- can be eithergeometry.Polygon
orgeometry.Circle
group
- an integer, default value is a kaa constant meaning “no group”. Hitboxes within the same group will never collide with each other.mask
- an integer, used as a bit mask, it’s recommended to use enum.Intflag enumerated constant. Default value is a kaa constant meaning “match all masks”. Defines a category of this hitbox.collision_mask
- an integer, used as a bit mask, it’s recommended to use enum.Intflag enumerated constant. Default value is a kaa constant meaning “match all masks”. Defines with which categories this hitbox should collide.trigger_id
- an integer, your own value used with theSpaceNode.set_collision_handler()
method. Used in custom collision handling.
The hitbox node also has a few properties affecting its physical behaviour:
sensor
elasticity
friction
surface_velocity
Instance properties:
-
HitboxNode.
shape
¶ Gets or sets the shape of the hitbox. It can be either
geometry.Polygon
orgeometry.Circle
.
-
HitboxNode.
group
¶ Gets or sets the group of the hitbox, as integer. Hitboxes with the same group won’t collide with each other. It’s basically a performance hint for the physics engine. Default value is kaa.physics.COLLISION_GROUP_NONE, meaning no group is used.
Another method of telling the engine which hitbox collisions it should ignore is to set
mask
andcollision_mask
on a HitboxNode.
-
HitboxNode.
mask
¶ Gets or sets the category of this hitbox node, as a bit mask. Other nodes will collide with this node if they match on collision_mask. Otherwise collisions will be ignored. Use mask and collision_mask as performance hints for the engine.
By default mask and hitbox_mask are kaa.physics.COLLISION_BITMASK_ALL which meaning the engine will not apply any filtering when detecting collisions - hitbox with those values will collide with any other hitbox.
An example below shows how to set mask and collision_mask values to apply the following logic:
player hitbox will collide only with enemy hitbox, enemy bullet hitbox and wall hitbox
player bullet hitbox will collide only with the enemy hitbox
enemy hitbox will collide only with other enemy hitboxes, player, player bullet and wall hitbox
enemy bullet will collide only with the player hitboxes
wall will collide with everything except other wall hitboxes
from kaa.physics import HitboxNode from kaa.geometry import Circle, Vector, Polygon import enum class CollisionMask(enum.IntFlag): player = enum.auto() player_bullet = enum.auto() enemy = enum.auto() enemy_bullet = enum.auto() wall = enum.auto() player_collision_mask = enemy | enemy_bullet | wall enemy_collision_mask = enemy | player | player_bullet | wall wall_collision_mask = player | player_bullet | enemy | enemy_bullet player_hitbox = HitboxNode(shape=Circle(radius=20), mask=CollisionMask.player, collision_mask=CollisionMask.player_collision_mask) player_bullet_hitbox = HitboxNode(shape=Circle(radius=5), mask=CollisionMask.player_bullet, collision_mask=CollisionMask.enemy) enemy_hitbox = HitboxNode(shape=Circle(radius=20), mask=CollisionMask.enemy, collision_mask=CollisionMask.enemy_collision_mask) enemy_bullet_hitbox = HitboxNode(shape=Circle(radius=5), mask=CollisionMask.enemy_bullet, collision_mask=CollisionMask.player) wall = HitboxNode(shape=Polygon([Vector(-50, -50), Vector(-50, 50), Vector(0, 100)], mask=CollisionMask.wall, collision_mask=CollisionMask.wall_collision_mask))
What if there’s assymetry in the mask and collision_mask definitions? For example, what will happens if we set the player to collide with enemy, but won’t set enemy to collide with the player? In that case, those collisions won’t occur. The collision masks need to match symmetrically from both sides for collision to be detected.
What if there is a proper symmetry in collision mask definitions but both hitboxes have the same group? In that case the group value takes precedence and collisions won’t occur.
-
HitboxNode.
collision_mask
¶ Gets or sets the categories of other hitboxes that you want this hitbox to collide with.
See the full example in the mask section above for more information.
-
HitboxNode.
trigger_id
¶ Gets or sets the trigger id value. It can be any value of your choice. It’s a ‘tag’ value which you need to pass when registering your custom collision handler function
-
HitboxNode.
sensor
¶ Gets or sets the sensor flag (bool). Default is
False
. If set toTrue
, the hitbox will not cause any physical collision effects (i.e. will not interact with other colliding objects) but will still trigger its collision handler function (check out SpaceNode.set_collision_handler method for more info on how to register a collision handlers for hitboxes).
-
HitboxNode.
elasticity
¶ Gets or sets hitbox elasticity, as
float
. This is a percentage of kinetic energy transferred during collision and should be between 0 and 1. A value of 0.0 gives no bounce, while a value of 1.0 will give a “perfect” bounce. Default elasticity is 0.95. The elasticity for a collision is found by multiplying the elasticity of the interacting hitboxes together.
-
HitboxNode.
friction
¶ Gets or sets hitbox friction coefficient, as
float
. Physics engine uses the Coulomb friction model, a value of 0.0 is frictionless. The friction for a collision is found by multiplying the friction of the interacting hitboxes together. Default is 0.
-
HitboxNode.
surface_velocity
¶ Gets or sets hitbox surface velocity, as
geometry.Vector
. Useful for creating conveyor belts or players that move around. This value is only used when calculating friction, not resolving the collision. Default isVector(0, 0)
(no surface velocity)
ShapeQueryResult
reference¶
-
class
physics.
ShapeQueryResult
¶ ShapeQueryResult object is returned by the
SpaceNode.query_shape_overlaps()
method. A single query can return multiple ShapeQueryResult objects. A ShapeQueryResult has the following properties:hitbox
- an instance ofHitboxNode
which collidedbody
- aBodyNode
instance that owns the hitboxcontact_points
- a list ofCollisionContactPoint
objects which contain information about collision points
CollisionContactPoint
reference¶
-
class
physics.
CollisionContactPoint
¶ A CollisionContactPoint instance represents an actual point where collision between two shapes occurred. It has the following properties:
point_a
point_b
distance
Arbiter
reference¶
-
class
physics.
Arbiter
¶ Arbiter object is passed to the collision handler function when collision occurs. It holds information about the collision in following fields:
space
- aSpaceNode
where collision occurred.phase
- an enum value (CollisionPhase
), indicating collision phase. Available values are:CollisionPhase.begin
- indicates that collision betwen two objects has started (their hitboxes have just touched or overlapped)CollisionPhase.pre_solve
- indicates that two hitboxes are still in contact (touching or overlapping). It is called before the engine calculates the physics (e.g. velocities of both colliding objects)CollisionPhase.post_solve
- like pre_solve, but called after the engine calculates the physics for the objects.CollisionPhase.separate
- indicates that hitboxes of our two objects have separated - the collision has ended
CollisionPair
reference¶
-
class
physics.
CollisionPair
¶ CollisionPair object is passed to the collision handler function (see
SpaceNode.set_collision_handler()
). It holds references to an object that collided. The CollisionPair has the following fields:body
- referencingBodyNode
which collidedhitbox
- referencingHitboxNode
which collided. Note that body nodes can have multiple hitboxes: here you can find which of them has collided
BodyNodeType
reference¶
-
class
physics.
BodyNodeType
¶ Enum type used for classifying BodyNodes. It has the following values:
BodyNodeType.static
BodyNodeType.dynamic
BodyNodeType.kinematic
Refer to BodyNode’s body_type property for more information.
CollisionPhase
reference¶
RayQueryResult
reference¶
-
class
physics.
RayQueryResult
¶ RayQueryResult objects are returned by the
SpaceNode.query_ray()
method. A ShapeQueryResult represents a collision between a ray and a hitbox. It has the following properties:hitbox
- an instance ofHitboxNode
which collidedbody
- aBodyNode
instance that owns the hitboxpoint
- ageometry.Vector
where the ray intersected the hitboxnormal
- ageometry.Vector
with ray reflection direction. This vector is normalized.alpha
- a float number indicating distance from the ray start point to the point where collision occurred. The distance is in relation to the ray length so the number is always between 0 and 1.
PointQueryResult
reference¶
-
class
physics.
PointQueryResult
¶ PointQueryResult objects are returned by the
SpaceNode.query_point_neighbors()
method. Properties arehitbox
- an instance ofHitboxNode
which collidedbody
- aBodyNode
instance that owns the hitboxpoint
- ageometry.Vector
coords of the nearest point of collisiondistance
- ageometry.Vector
with a distance to the point of collision