Module windfield
windfield is a physics module for LÖVE.
It wraps LÖVE's physics API so that using box2d becomes as simple as possible.
Functions
wf.newWorld (xg, yg, sleep) | Creates a new World. |
World:update (dt) | Updates the world to allow bodies to continue their motion and starts a new frame for collision events. |
World:draw (alpha) | Draws the world visualizing colliders, joints, and world queries (for debugging purposes). |
World:setQueryDebugDrawing (value) | Sets query debug drawing to be active or not. |
World:setExplicitCollisionEvents (value) | Sets collision events to be explicit or not. |
World:addCollisionClass (collision_class_name, collision_class) | Adds a new collision class to the World. |
World:addCollisionClassTable (definition_map) | Adds multiple new collision classes to the World. |
World:newCircleCollider (x, y, r) | Creates a new CircleCollider. |
World:newRectangleCollider (x, y, w, h) | Creates a new RectangleCollider. |
World:newBSGRectangleCollider (x, y, w, h, corner_cut_size) | Creates a new BSGRectangleCollider, which is a rectangle with its corners cut (an octagon). |
World:newPolygonCollider (vertices) | Creates a new PolygonCollider. |
World:newLineCollider (x1, y1, x2, y2) | Creates a new LineCollider. |
World:newChainCollider (vertices, loop) | Creates a new ChainCollider. |
World:queryCircleArea (x, y, radius, collision_class_names) | Queries a circular area around a point for colliders. |
World:queryRectangleArea (x, y, w, h, collision_class_names) | Queries a rectangular area for colliders. |
World:queryPolygonArea (vertices, collision_class_names) | Queries a polygon area for colliders. |
World:queryLine (x1, y1, x2, y2, collision_class_names) | Queries for colliders that intersect with a line. |
World:addJoint (joint_type, ...) | Adds a joint to the world. |
World:removeJoint (joint) | Removes a joint from the world. |
World:destroy () | Destroys the collider and removes it from the world. |
Collider:setCollisionClass (collision_class_name) | Sets this collider's collision class. |
Collider:enter (other_collision_class_name) | Checks for collision enter events from this collider with another. |
Collider:getEnterCollisionData (other_collision_class_name) | Gets the collision data generated from the last collision enter event. |
Collider:exit (other_collision_class_name) | Checks for collision exit events from this collider with another. |
Collider:getExitCollisionData (other_collision_class_name) | Gets the collision data generated from the last collision exit event. |
Collider:stay (other_collision_class_name) | Checks for collision stay events from this collider with another. |
Collider:getStayCollisionData (other_collision_class_name) | Gets the collision data generated from the last collision stay event Only valid after calling Collider:stay. |
Collider:setPreSolve (callback) | Sets the preSolve callback. |
Collider:setPostSolve (callback) | Sets the postSolve callback. |
Collider:setObject (object) | Sets the collider's object. |
Collider:getObject () | Gets the object that a collider belongs to. |
Collider:addShape (shape_name, shape_type, ...) | Adds a shape to the collider. |
Collider:removeShape (shape_name) | Removes a shape from the collider (also removes the accompanying fixture). |
Collider:destroy () | Destroys the collider and removes it from the world. |
Functions
- wf.newWorld (xg, yg, sleep)
-
Creates a new World.
newWorld(number, number, boolean) -> table
Parameters:
- xg number The world's x gravity component
- yg number The world's y gravity component
- sleep bool =true Whether the world's bodies are allowed to sleep
Returns:
-
table: World the World object, containing all attributes and methods defined below as well as all of a box2d World
Usage:
world = wf.newWorld(0, 0, true)
- World:update (dt)
-
Updates the world to allow bodies to continue their motion and starts a new frame for collision events.
update(number) -> nil
Parameters:
- dt number The time step delta
Usage:
world:update(dt)
- World:draw (alpha)
-
Draws the world visualizing colliders, joints, and world queries (for debugging purposes).
draw(number) -> nil
Parameters:
- alpha number =1 The optional alpha value to use when drawing, defaults to 1.
Usage:
world:draw() -- default drawing world:draw(128) -- semi transparent drawing
- World:setQueryDebugDrawing (value)
-
Sets query debug drawing to be active or not.
If active, then collider queries will be drawn to the screen for 10 frames. This is used for debugging purposes and incurs a performance penalty. Don't forget to turn it off!
setQueryDebugDrawing(boolean) -> nil
Parameters:
- value bool Whether query debug drawing is active
Usage:
world:setQueryDebugDrawing(true)
- World:setExplicitCollisionEvents (value)
-
Sets collision events to be explicit or not.
If explicit, then collision events will only be generated between collision classes when they are specified in
addCollisionClasses
. By default this is set to false, meaning that collision events are generated between all collision classes. The main reason why you might want to set this to true is for performance, since not generating collision events between every collision class will require less computation. This function must be called before any collision class is added to the world.setExplicitCollisionEvents(boolean) -> nil
Parameters:
- value bool Whether collision events are explicit
Usage:
world:setExplicitCollisionEvents(true)
- World:addCollisionClass (collision_class_name, collision_class)
-
Adds a new collision class to the World.
Collision classes are attached to Colliders and defined their behaviors in terms of which ones will physically ignore each other and which ones will generate collision events between each other. All collision classes must be added before any Collider is created. If
world:setExplicitCollisionEvents
is set to false (the default setting) then enter, exit, pre, and post settings don't need to be specified, otherwise they do.addCollisionClass(string, table) -> nil
Parameters:
- collision_class_name string The unique name of the collision class
- collision_class
{[string]={}}
The collision class definition. Mostly specifying collision class names that should generate collision events with the collider of this collision class at different points in time.
collision_class = { ignores = {}, -- physically ignore enter = {}, -- collision events when they *enter* contact with each other exit = {}, -- collision events when they *exit* contact with each other pre = {}, -- collision events *just before* collision response is applied post = {}, -- collision events *right after* collision response is applied }
Usage:
world:addCollisionClass('Player', {ignores = {'NPC', 'Enemy'}})
- World:addCollisionClassTable (definition_map)
-
Adds multiple new collision classes to the World.
Allows you to add multiple collision classes that ignore each other without worrying about specifying them in a specific order.
addCollisionClassTable(table) -> nil
Parameters:
- definition_map {[string]={[string]={}}} A map of collision class names to their definitions. Definitions are the same as collision_class in World:addCollisionClass.
Usage:
world:addCollisionClassTable({ Player = {ignores = {'NPC', 'Enemy'}}, NPC = {}, Enemy = {ignores = {'NPC'}}, })
- World:newCircleCollider (x, y, r)
-
Creates a new CircleCollider.
newCircleCollider(number, number, number) -> table
Parameters:
- x number The x position of the circle's center
- y number The y position of the circle's center
- r number The radius of the circle
Returns:
-
table: Collider The created CircleCollider
Usage:
circle = world:newCircleCollider(100, 100, 30)
- World:newRectangleCollider (x, y, w, h)
-
Creates a new RectangleCollider.
newRectangleCollider(number, number, number, number) -> table
Parameters:
- x number The x position of the rectangle's top-left corner
- y number The y position of the rectangle's top-left corner
- w number The width of the rectangle
- h number The height of the rectangle
Returns:
-
table: Collider The created RectangleCollider
Usage:
rectangle = world:newRectangleCollider(100, 100, 50, 50)
- World:newBSGRectangleCollider (x, y, w, h, corner_cut_size)
-
Creates a new BSGRectangleCollider, which is a rectangle with its corners cut (an octagon).
newBSGRectangleCollider(number, number, number, number, number) -> table
Parameters:
- x number The x position of the rectangle's top-left corner
- y number The y position of the rectangle's top-left corner
- w number The width of the rectangle
- h number The height of the rectangle
- corner_cut_size number The corner cut size
Returns:
-
table: Collider The created BSGRectangleCollider
Usage:
bsg_rectangle = world:newBSGRectangleCollider(100, 100, 50, 50, 5)
- World:newPolygonCollider (vertices)
-
Creates a new PolygonCollider.
newPolygonCollider({number}) -> table
Parameters:
- vertices {number} The polygon vertices as a table of numbers
Returns:
-
table: Collider The created PolygonCollider
Usage:
polygon = world:newPolygonCollider({10, 10, 10, 20, 20, 20, 20, 10})
- World:newLineCollider (x1, y1, x2, y2)
-
Creates a new LineCollider.
newLineCollider(number, number, number, number) -> table
Parameters:
- x1 number The x position of the first point of the line
- y1 number The y position of the first point of the line
- x2 number The x position of the second point of the line
- y2 number The y position of the second point of the line
Returns:
-
table: Collider The created LineCollider
Usage:
line = world:newLineCollider(100, 100, 200, 200)
- World:newChainCollider (vertices, loop)
-
Creates a new ChainCollider.
newChainCollider({number}, boolean) -> table
Parameters:
- vertices {number} The chain vertices as a table of numbers
- loop bool If the chain should loop back from the last to the first point
Returns:
-
table: Collider The created ChainCollider
Usage:
chain = world:newChainCollider({10, 10, 10, 20, 20, 20}, true)
- World:queryCircleArea (x, y, radius, collision_class_names)
-
Queries a circular area around a point for colliders.
queryCircleArea(number, number, number, {string}) -> {Collider}
Parameters:
- x number The x position of the circle's center
- y number The y position of the circle's center
- radius number The radius of the circle
- collision_class_names
{string}
='All'] A table of strings with collision class names to be queried. The special value
'All'
(default) can be used to query for all existing collision classes. Another special valueexcept
can be used to exclude some collision classes when'All'
is used.
Returns:
-
{Collider}: The table of colliders with the specified collision classes inside the area
Usage:
colliders_1 = world:queryCircleArea(100, 100, 50, {'Enemy', 'NPC'}) colliders_2 = world:queryCircleArea(100, 100, 50, {'All', except = {'Player'}})
- World:queryRectangleArea (x, y, w, h, collision_class_names)
-
Queries a rectangular area for colliders.
queryRectangleArea(number, number, number, number, {string}) -> {Collider}
Parameters:
- x number The x position of the rectangle's top-left corner
- y number The y position of the rectangle's top-left corner
- w number The width of the rectangle
- h number The height of the rectangle
- collision_class_names
{string}
='All'] A table of strings with collision class names to be queried. The special value
'All'
(default) can be used to query for all existing collision classes. Another special valueexcept
can be used to exclude some collision classes when'All'
is used.
Returns:
-
{Collider}: The table of colliders with the specified collision classes inside the area
Usage:
colliders_1 = world:queryRectangleArea(100, 100, 50, 50, {'Enemy', 'NPC'}) colliders_2 = world:queryRectangleArea(100, 100, 50, 50, {'All', except = {'Player'}})
- World:queryPolygonArea (vertices, collision_class_names)
-
Queries a polygon area for colliders.
queryPolygonArea({number}, {string}) -> {Collider}
Parameters:
- vertices {number} The polygon vertices as a table of numbers
- collision_class_names
{string}
='All'] A table of strings with collision class names to be queried. The special value
'All'
(default) can be used to query for all existing collision classes. Another special valueexcept
can be used to exclude some collision classes when'All'
is used.
Returns:
-
{Collider}: The table of colliders with the specified collision classes inside the area
Usage:
colliders_1 = world:queryPolygonArea({10, 10, 20, 10, 20, 20, 10, 20}, {'Enemy'}) colliders_2 = world:queryPolygonArea({10, 10, 20, 10, 20, 20, 10, 20}, {'All', except = {'Player'}})
- World:queryLine (x1, y1, x2, y2, collision_class_names)
-
Queries for colliders that intersect with a line.
queryLine(number, number, number, number, {string}) -> {Collider}
Parameters:
- x1 number The x position of the first point of the line
- y1 number The y position of the first point of the line
- x2 number The x position of the second point of the line
- y2 number The y position of the second point of the line
- collision_class_names
{string}
='All'] A table of strings with collision class names to be queried. The special value
'All'
(default) can be used to query for all existing collision classes. Another special valueexcept
can be used to exclude some collision classes when'All'
is used.
Returns:
-
{Collider}: The table of colliders with the specified collision classes inside the area
Usage:
colliders_1 = world:queryLine(100, 100, 200, 200, {'Enemy', 'NPC', 'Projectile'}) colliders_2 = world:queryLine(100, 100, 200, 200, {'All', except = {'Player'}})
- World:addJoint (joint_type, ...)
-
Adds a joint to the world.
addJoint(string, any) -> Joint
Parameters:
- joint_type
string
The joint type, it can be
'DistanceJoint'
,'FrictionJoint'
,'GearJoint'
,'MouseJoint'
,'PrismaticJoint'
,'PulleyJoint'
,'RevoluteJoint'
,'RopeJoint'
,'WeldJoint'
or'WheelJoint'
- ... any The joint creation arguments that are different for each joint type, check Joint for more details
Returns:
-
Joint: joint The created Joint
Usage:
joint = world:addJoint('RevoluteJoint', collider_1, collider_2, 50, 50, true)
- joint_type
string
The joint type, it can be
- World:removeJoint (joint)
-
Removes a joint from the world.
removeJoint(Joint) -> nil
Parameters:
- joint Joint The joint to be removed
Usage:
joint = world:addJoint('RevoluteJoint', collider_1, collider_2, 50, 50, true) world:removeJoint(joint)
- World:destroy ()
-
Destroys the collider and removes it from the world.
This must be called whenever the Collider is to discarded otherwise it will result in it not getting collected (and so memory will leak).
destroy() -> nil
Usage:
collider:destroy()
- Collider:setCollisionClass (collision_class_name)
-
Sets this collider's collision class.
The collision class must be a valid one previously added with
world:addCollisionClass
.setCollisionClass(string) -> nil
Parameters:
- collision_class_name string The name of the collision class
Usage:
world:addCollisionClass('Player') collider = world:newRectangleCollider(100, 100, 50, 50) collider:setCollisionClass('Player')
- Collider:enter (other_collision_class_name)
-
Checks for collision enter events from this collider with another.
Enter events are generated on the frame when one collider enters contact with another.
enter(string) -> boolean
Parameters:
- other_collision_class_name string The name of the target collision class
Returns:
-
boolean: If the enter collision event between both colliders happened on this frame or not
Usage:
-- in some update function if collider:enter('Enemy') then print('Collision entered!') end
- Collider:getEnterCollisionData (other_collision_class_name)
-
Gets the collision data generated from the last collision enter event.
Only valid after calling Collider:enter.
getEnterCollisionData(string) -> {Collider, Contact}
Parameters:
- other_collision_class_name string The name of the target collision class
Returns:
-
{Collider, Contact}: collision_data A table containing the Collider and the Contact generated from the last enter collision event. The Contact is read-only (only get* and is* methods exist) and will become invalid on the next call to World:update, but you can use contact:clone() to create a permanent copy.
Usage:
-- in some update function if collider:enter('Enemy') then local collision_data = collider:getEnterCollisionData('Enemy') print(collision_data.collider, collision_data.contact) end
- Collider:exit (other_collision_class_name)
-
Checks for collision exit events from this collider with another.
Exit events are generated on the frame when one collider exits contact with another.
exit(string) -> boolean
Parameters:
- other_collision_class_name string The name of the target collision class
Returns:
-
boolean: If the exit collision event between both colliders happened on this frame or not
Usage:
-- in some update function if collider:exit('Enemy') then print('Collision exited!') end
- Collider:getExitCollisionData (other_collision_class_name)
-
Gets the collision data generated from the last collision exit event.
Only valid after calling Collider:exit.
getExitCollisionData(string) -> {Collider, Contact}
Parameters:
- other_collision_class_name string The name of the target collision class
Returns:
-
{Collider, Contact}: collision_data A table containing the Collider and the Contact generated from the last exit collision event. The Contact is read-only (only get* and is* methods exist) and will become invalid on the next call to World:update, but you can use contact:clone() to create a permanent copy.
Usage:
-- in some update function if collider:exit('Enemy') then local collision_data = collider:getExitCollisionData('Enemy') print(collision_data.collider, collision_data.contact) end
- Collider:stay (other_collision_class_name)
-
Checks for collision stay events from this collider with another.
Stay events are generated on every frame when one collider is in contact with another.
stay(string) -> boolean
Parameters:
- other_collision_class_name string The name of the target collision class
Returns:
-
boolean: Whether the stay collision event between both colliders is happening on this frame
Usage:
-- in some update function if collider:stay('Enemy') then print('Collision staying!') end
- Collider:getStayCollisionData (other_collision_class_name)
-
Gets the collision data generated from the last collision stay event
Only valid after calling Collider:stay.
getStayCollisionData(string) -> {{Collider, Contact}}
Parameters:
- other_collision_class_name string The name of the target collision class
Returns:
-
{{Collider, Contact}}: collisiondatalist A table containing multiple Colliders and Contacts generated from the last stay collision event. Usually this list will be of size 1, but sometimes this collider will be staying in contact with multiple other colliders on the same frame, and so those multiple stay events (with multiple colliders) are returned. The Contact is read-only (only get* and is* methods exist) and will become invalid on the next call to World:update, but you can use contact:clone() to create a permanent copy.
Usage:
-- in some update function if collider:stay('Enemy') then local collision_data_list = collider:getStayCollisionData('Enemy') for _, collision_data in ipairs(collision_data_list) do print(collision_data.collider, collision_data.contact) end end
- Collider:setPreSolve (callback)
-
Sets the preSolve callback.
Unlike
:enter
or:exit
, which can be delayed and checked after the physics simulation is done for this frame, both preSolve and postSolve must be callbacks that are resolved immediately, since they may change how the rest of the simulation plays out on this frame.You cannot modify the World inside of the preSolve callback because the underlying Box2D world will be locked. See also World:setCallbacks.
setPreSolve(function) -> nil
Parameters:
- callback
func
The preSolve callback. Receives
collider_1
,collider_2
, andcontact
as arguments
Usage:
collider:setPreSolve(function(collider_1, collider_2, contact) contact:setEnabled(false) end
- callback
func
The preSolve callback. Receives
- Collider:setPostSolve (callback)
-
Sets the postSolve callback.
Unlike
:enter
or:exit
, which can be delayed and checked after the physics simulation is done for this frame, both preSolve and postSolve must be callbacks that are resolved immediately, since they may change how the rest of the simulation plays out on this frame.You cannot modify the World inside of the postSolve callback because the underlying Box2D world will be locked. See also World:setCallbacks.
setPostSolve(function) -> nil
Parameters:
- callback
func
The postSolve callback. Receives
collider_1
,collider_2
,contact
,normal_impulse1
,tangent_impulse1
,normal_impulse2
, andtangent_impulse2
as arguments
Usage:
collider:setPostSolve(function(collider_1, collider_2, contact, ni1, ti1, ni2, ti2) contact:setEnabled(false) end
- callback
func
The postSolve callback. Receives
- Collider:setObject (object)
-
Sets the collider's object.
This is useful to set the object that the collider belongs to, so that when a query call is made and colliders are returned you can immediately get the pertinent object.
setObject(any) -> nil
Parameters:
- object any The object that this collider belongs to
Usage:
-- in the constructor of some object self.collider = world:newRectangleCollider(...) self.collider:setObject(self)
- Collider:getObject ()
-
Gets the object that a collider belongs to.
getObject() -> any
Returns:
-
any: object The object that is attached to this collider
Usage:
-- in an update function if self.collider:enter('Enemy') then local collision_data = self.collider:getEnterCollisionData('SomeTag') -- gets the reference to the enemy object, the enemy object must have used :setObject(self) to attach itself to the collider otherwise this wouldn't work local enemy = collision_data.collider:getObject() end
- Collider:addShape (shape_name, shape_type, ...)
-
Adds a shape to the collider.
A shape can be accessed via collider.shapes[shapename]. A fixture of the same name is also added to attach the shape to the collider body. A fixture can be accessed via collider.fixtures[fixturename].
addShape(string, string, any) -> nil
Parameters:
- shape_name string The unique name of the shape
- shape_type
string
The shape type, can be
'ChainShape'
,'CircleShape'
,'EdgeShape'
,'PolygonShape'
or'RectangleShape'
- ... any The shape creation arguments that are different for each shape. Check Shape for more details
- Collider:removeShape (shape_name)
-
Removes a shape from the collider (also removes the accompanying fixture).
removeShape(string) -> nil
Parameters:
- shape_name
string
The unique name of the shape to be removed. Must be a name previously added with
:addShape
- shape_name
string
The unique name of the shape to be removed. Must be a name previously added with
- Collider:destroy ()
-
Destroys the collider and removes it from the world.
This must be called whenever the Collider is to discarded otherwise it will result in it not getting collected (and so memory will leak).
destroy() -> nil
Usage:
collider:destroy()