@ -20,11 +20,12 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY , WHETHER IN AN ACTION OF CONTRACT , TORT OR OTHERWISE , ARISING FROM ,
LIABILITY , WHETHER IN AN ACTION OF CONTRACT , TORT OR OTHERWISE , ARISING FROM ,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE .
SOFTWARE .
] ] --
] ]
--
local path = ... .. ' . '
local path = ... .. " . "
local wf = { }
local wf = { }
wf.Math = require ( path .. ' mlib.mlib ' )
wf.Math = require ( path .. " mlib.mlib " )
World = { }
World = { }
World.__index = World
World.__index = World
@ -32,14 +33,28 @@ World.__index = World
function wf . newWorld ( xg , yg , sleep )
function wf . newWorld ( xg , yg , sleep )
local world = wf.World . new ( wf , xg , yg , sleep )
local world = wf.World . new ( wf , xg , yg , sleep )
world.box2d_world : setCallbacks ( world.collisionOnEnter , world.collisionOnExit , world.collisionPre , world.collisionPost )
world.box2d_world : setCallbacks (
world.collisionOnEnter ,
world.collisionOnExit ,
world.collisionPre ,
world.collisionPost
)
world : collisionClear ( )
world : collisionClear ( )
world : addCollisionClass ( ' Default ' )
world : addCollisionClass ( " Default " )
-- Points all box2d_world functions to this wf.World object
-- Points all box2d_world functions to this wf.World object
-- This means that the user can call world:setGravity for instance without having to say world.box2d_world:setGravity
-- This means that the user can call world:setGravity for instance without having to say world.box2d_world:setGravity
for k , v in pairs ( world.box2d_world . __index ) do
for k , v in pairs ( world.box2d_world . __index ) do
if k ~= ' __gc ' and k ~= ' __eq ' and k ~= ' __index ' and k ~= ' __tostring ' and k ~= ' update ' and k ~= ' destroy ' and k ~= ' type ' and k ~= ' typeOf ' then
if
k ~= " __gc "
and k ~= " __eq "
and k ~= " __index "
and k ~= " __tostring "
and k ~= " update "
and k ~= " destroy "
and k ~= " type "
and k ~= " typeOf "
then
world [ k ] = function ( self , ... )
world [ k ] = function ( self , ... )
return v ( self.box2d_world , ... )
return v ( self.box2d_world , ... )
end
end
@ -84,18 +99,20 @@ function World:draw(alpha)
for _ , body in ipairs ( bodies ) do
for _ , body in ipairs ( bodies ) do
local fixtures = body : getFixtures ( )
local fixtures = body : getFixtures ( )
for _ , fixture in ipairs ( fixtures ) do
for _ , fixture in ipairs ( fixtures ) do
if fixture : getShape ( ) : type ( ) == ' PolygonShape ' then
if fixture : getShape ( ) : type ( ) == " PolygonShape " then
love.graphics . polygon ( ' line ' , body : getWorldPoints ( fixture : getShape ( ) : getPoints ( ) ) )
love.graphics . polygon ( " line " , body : getWorldPoints ( fixture : getShape ( ) : getPoints ( ) ) )
elseif fixture : getShape ( ) : type ( ) == ' EdgeShape ' or fixture : getShape ( ) : type ( ) == ' ChainShape ' then
elseif fixture : getShape ( ) : type ( ) == " EdgeShape " or fixture : getShape ( ) : type ( ) == " ChainShape " then
local points = { body : getWorldPoints ( fixture : getShape ( ) : getPoints ( ) ) }
local points = { body : getWorldPoints ( fixture : getShape ( ) : getPoints ( ) ) }
for i = 1 , # points , 2 do
for i = 1 , # points , 2 do
if i < # points - 2 then love.graphics . line ( points [ i ] , points [ i + 1 ] , points [ i + 2 ] , points [ i + 3 ] ) end
if i < # points - 2 then
love.graphics . line ( points [ i ] , points [ i + 1 ] , points [ i + 2 ] , points [ i + 3 ] )
end
end
elseif fixture : getShape ( ) : type ( ) == ' CircleShape ' then
end
elseif fixture : getShape ( ) : type ( ) == " CircleShape " then
local body_x , body_y = body : getPosition ( )
local body_x , body_y = body : getPosition ( )
local shape_x , shape_y = fixture : getShape ( ) : getPoint ( )
local shape_x , shape_y = fixture : getShape ( ) : getPoint ( )
local r = fixture : getShape ( ) : getRadius ( )
local r = fixture : getShape ( ) : getRadius ( )
love.graphics . circle ( ' line ' , body_x + shape_x , body_y + shape_y , r , 360 )
love.graphics . circle ( " line " , body_x + shape_x , body_y + shape_y , r , 360 )
end
end
end
end
end
end
@ -106,8 +123,12 @@ function World:draw(alpha)
local joints = self.box2d_world : getJoints ( )
local joints = self.box2d_world : getJoints ( )
for _ , joint in ipairs ( joints ) do
for _ , joint in ipairs ( joints ) do
local x1 , y1 , x2 , y2 = joint : getAnchors ( )
local x1 , y1 , x2 , y2 = joint : getAnchors ( )
if x1 and y1 then love.graphics . circle ( ' line ' , x1 , y1 , 4 ) end
if x1 and y1 then
if x2 and y2 then love.graphics . circle ( ' line ' , x2 , y2 , 4 ) end
love.graphics . circle ( " line " , x1 , y1 , 4 )
end
if x2 and y2 then
love.graphics . circle ( " line " , x2 , y2 , 4 )
end
end
end
love.graphics . setColor ( 255 , 255 , 255 , alpha )
love.graphics . setColor ( 255 , 255 , 255 , alpha )
@ -115,15 +136,17 @@ function World:draw(alpha)
love.graphics . setColor ( 64 , 64 , 222 , alpha )
love.graphics . setColor ( 64 , 64 , 222 , alpha )
for _ , query_draw in ipairs ( self.query_debug_draw ) do
for _ , query_draw in ipairs ( self.query_debug_draw ) do
query_draw.frames = query_draw.frames - 1
query_draw.frames = query_draw.frames - 1
if query_draw.type == ' circle ' then
if query_draw.type == " circle " then
love.graphics . circle ( ' line ' , query_draw.x , query_draw.y , query_draw.r )
love.graphics . circle ( " line " , query_draw.x , query_draw.y , query_draw.r )
elseif query_draw.type == ' rectangle ' then
elseif query_draw.type == " rectangle " then
love.graphics . rectangle ( ' line ' , query_draw.x , query_draw.y , query_draw.w , query_draw.h )
love.graphics . rectangle ( " line " , query_draw.x , query_draw.y , query_draw.w , query_draw.h )
elseif query_draw.type == ' line ' then
elseif query_draw.type == " line " then
love.graphics . line ( query_draw.x1 , query_draw.y1 , query_draw.x2 , query_draw.y2 )
love.graphics . line ( query_draw.x1 , query_draw.y1 , query_draw.x2 , query_draw.y2 )
elseif query_draw.type == ' polygon ' then
elseif query_draw.type == " polygon " then
local triangles = love.math . triangulate ( query_draw.vertices )
local triangles = love.math . triangulate ( query_draw.vertices )
for _ , triangle in ipairs ( triangles ) do love.graphics . polygon ( ' line ' , triangle ) end
for _ , triangle in ipairs ( triangles ) do
love.graphics . polygon ( " line " , triangle )
end
end
end
end
end
for i = # self.query_debug_draw , 1 , - 1 do
for i = # self.query_debug_draw , 1 , - 1 do
@ -143,7 +166,9 @@ function World:setExplicitCollisionEvents(value)
end
end
function World : addCollisionClass ( collision_class_name , collision_class )
function World : addCollisionClass ( collision_class_name , collision_class )
if self.collision_classes [ collision_class_name ] then error ( ' Collision class ' .. collision_class_name .. ' already exists. ' ) end
if self.collision_classes [ collision_class_name ] then
error ( " Collision class " .. collision_class_name .. " already exists. " )
end
if self.explicit_collision_events then
if self.explicit_collision_events then
self.collision_classes [ collision_class_name ] = collision_class or { }
self.collision_classes [ collision_class_name ] = collision_class or { }
@ -177,10 +202,18 @@ function World:collisionClassesSet()
local collision_table = self : getCollisionCallbacksTable ( )
local collision_table = self : getCollisionCallbacksTable ( )
for collision_class_name , collision_list in pairs ( collision_table ) do
for collision_class_name , collision_list in pairs ( collision_table ) do
for _ , collision_info in ipairs ( collision_list ) do
for _ , collision_info in ipairs ( collision_list ) do
if collision_info.type == ' enter ' then self : addCollisionEnter ( collision_class_name , collision_info.other ) end
if collision_info.type == " enter " then
if collision_info.type == ' exit ' then self : addCollisionExit ( collision_class_name , collision_info.other ) end
self : addCollisionEnter ( collision_class_name , collision_info.other )
if collision_info.type == ' pre ' then self : addCollisionPre ( collision_class_name , collision_info.other ) end
end
if collision_info.type == ' post ' then self : addCollisionPost ( collision_class_name , collision_info.other ) end
if collision_info.type == " exit " then
self : addCollisionExit ( collision_class_name , collision_info.other )
end
if collision_info.type == " pre " then
self : addCollisionPre ( collision_class_name , collision_info.other )
end
if collision_info.type == " post " then
self : addCollisionPost ( collision_class_name , collision_info.other )
end
end
end
end
end
@ -213,26 +246,34 @@ end
function World : addCollisionEnter ( type1 , type2 )
function World : addCollisionEnter ( type1 , type2 )
if not self : isCollisionBetweenSensors ( type1 , type2 ) then
if not self : isCollisionBetweenSensors ( type1 , type2 ) then
table.insert ( self.collisions . on_enter.non_sensor , { type1 = type1 , type2 = type2 } )
table.insert ( self.collisions . on_enter.non_sensor , { type1 = type1 , type2 = type2 } )
else table.insert ( self.collisions . on_enter.sensor , { type1 = type1 , type2 = type2 } ) end
else
table.insert ( self.collisions . on_enter.sensor , { type1 = type1 , type2 = type2 } )
end
end
end
function World : addCollisionExit ( type1 , type2 )
function World : addCollisionExit ( type1 , type2 )
if not self : isCollisionBetweenSensors ( type1 , type2 ) then
if not self : isCollisionBetweenSensors ( type1 , type2 ) then
table.insert ( self.collisions . on_exit.non_sensor , { type1 = type1 , type2 = type2 } )
table.insert ( self.collisions . on_exit.non_sensor , { type1 = type1 , type2 = type2 } )
else table.insert ( self.collisions . on_exit.sensor , { type1 = type1 , type2 = type2 } ) end
else
table.insert ( self.collisions . on_exit.sensor , { type1 = type1 , type2 = type2 } )
end
end
end
function World : addCollisionPre ( type1 , type2 )
function World : addCollisionPre ( type1 , type2 )
if not self : isCollisionBetweenSensors ( type1 , type2 ) then
if not self : isCollisionBetweenSensors ( type1 , type2 ) then
table.insert ( self.collisions . pre.non_sensor , { type1 = type1 , type2 = type2 } )
table.insert ( self.collisions . pre.non_sensor , { type1 = type1 , type2 = type2 } )
else table.insert ( self.collisions . pre.sensor , { type1 = type1 , type2 = type2 } ) end
else
table.insert ( self.collisions . pre.sensor , { type1 = type1 , type2 = type2 } )
end
end
end
function World : addCollisionPost ( type1 , type2 )
function World : addCollisionPost ( type1 , type2 )
if not self : isCollisionBetweenSensors ( type1 , type2 ) then
if not self : isCollisionBetweenSensors ( type1 , type2 ) then
table.insert ( self.collisions . post.non_sensor , { type1 = type1 , type2 = type2 } )
table.insert ( self.collisions . post.non_sensor , { type1 = type1 , type2 = type2 } )
else table.insert ( self.collisions . post.sensor , { type1 = type1 , type2 = type2 } ) end
else
table.insert ( self.collisions . post.sensor , { type1 = type1 , type2 = type2 } )
end
end
end
function World : doesType1IgnoreType2 ( type1 , type2 )
function World : doesType1IgnoreType2 ( type1 , type2 )
@ -246,31 +287,46 @@ function World:doesType1IgnoreType2(type1, type2)
end
end
local ignored_types = { }
local ignored_types = { }
for _ , collision_class_type in ipairs ( collision_ignores [ type1 ] ) do
for _ , collision_class_type in ipairs ( collision_ignores [ type1 ] ) do
if collision_class_type == ' All ' then
if collision_class_type == " All " then
for _ , collision_class_name in ipairs ( all ) do
for _ , collision_class_name in ipairs ( all ) do
table.insert ( ignored_types , collision_class_name )
table.insert ( ignored_types , collision_class_name )
end
end
else table.insert ( ignored_types , collision_class_type ) end
else
table.insert ( ignored_types , collision_class_type )
end
end
end
for key , _ in pairs ( collision_ignores [ type1 ] ) do
for key , _ in pairs ( collision_ignores [ type1 ] ) do
if key == ' except ' then
if key == " except " then
for _ , except_type in ipairs ( collision_ignores [ type1 ] . except ) do
for _ , except_type in ipairs ( collision_ignores [ type1 ] . except ) do
for i = # ignored_types , 1 , - 1 do
for i = # ignored_types , 1 , - 1 do
if ignored_types [ i ] == except_type then table.remove ( ignored_types , i ) end
if ignored_types [ i ] == except_type then
table.remove ( ignored_types , i )
end
end
end
end
end
end
end
end
end
for _ , ignored_type in ipairs ( ignored_types ) do
for _ , ignored_type in ipairs ( ignored_types ) do
if ignored_type == type2 then return true end
if ignored_type == type2 then
return true
end
end
end
end
end
function World : isCollisionBetweenSensors ( type1 , type2 )
function World : isCollisionBetweenSensors ( type1 , type2 )
if not self.is_sensor_memo [ type1 ] then self.is_sensor_memo [ type1 ] = { } end
if not self.is_sensor_memo [ type1 ] then
if not self.is_sensor_memo [ type1 ] [ type2 ] then self.is_sensor_memo [ type1 ] [ type2 ] = ( self : doesType1IgnoreType2 ( type1 , type2 ) or self : doesType1IgnoreType2 ( type2 , type1 ) ) end
self.is_sensor_memo [ type1 ] = { }
if self.is_sensor_memo [ type1 ] [ type2 ] then return true
end
else return false end
if not self.is_sensor_memo [ type1 ] [ type2 ] then
self.is_sensor_memo [ type1 ] [ type2 ] = (
self : doesType1IgnoreType2 ( type1 , type2 ) or self : doesType1IgnoreType2 ( type2 , type1 )
)
end
if self.is_sensor_memo [ type1 ] [ type2 ] then
return true
else
return false
end
end
end
-- https://love2d.org/forums/viewtopic.php?f=4&t=75441
-- https://love2d.org/forums/viewtopic.php?f=4&t=75441
@ -289,18 +345,18 @@ function World:generateCategoriesMasks()
end
end
for object_type , ignore_list in pairs ( collision_ignores ) do
for object_type , ignore_list in pairs ( collision_ignores ) do
for key , ignored_type in pairs ( ignore_list ) do
for key , ignored_type in pairs ( ignore_list ) do
if ignored_type == ' All ' then
if ignored_type == " All " then
for _ , all_object_type in ipairs ( all ) do
for _ , all_object_type in ipairs ( all ) do
table.insert ( incoming [ all_object_type ] , object_type )
table.insert ( incoming [ all_object_type ] , object_type )
table.insert ( expanded [ object_type ] , all_object_type )
table.insert ( expanded [ object_type ] , all_object_type )
end
end
elseif type ( ignored_type ) == ' string ' then
elseif type ( ignored_type ) == " string " then
if ignored_type ~= ' All ' then
if ignored_type ~= " All " then
table.insert ( incoming [ ignored_type ] , object_type )
table.insert ( incoming [ ignored_type ] , object_type )
table.insert ( expanded [ object_type ] , ignored_type )
table.insert ( expanded [ object_type ] , ignored_type )
end
end
end
end
if key == ' except ' then
if key == " except " then
for _ , except_ignored_type in ipairs ( ignored_type ) do
for _ , except_ignored_type in ipairs ( ignored_type ) do
for i , v in ipairs ( incoming [ except_ignored_type ] ) do
for i , v in ipairs ( incoming [ except_ignored_type ] ) do
if v == object_type then
if v == object_type then
@ -322,7 +378,9 @@ function World:generateCategoriesMasks()
end
end
local edge_groups = { }
local edge_groups = { }
for k , v in pairs ( incoming ) do
for k , v in pairs ( incoming ) do
table.sort ( v , function ( a , b ) return string.lower ( a ) < string.lower ( b ) end )
table.sort ( v , function ( a , b )
return string.lower ( a ) < string.lower ( b )
end )
end
end
local i = 0
local i = 0
for k , v in pairs ( incoming ) do
for k , v in pairs ( incoming ) do
@ -330,7 +388,10 @@ function World:generateCategoriesMasks()
for _ , c in ipairs ( v ) do
for _ , c in ipairs ( v ) do
str = str .. c
str = str .. c
end
end
if not edge_groups [ str ] then i = i + 1 ; edge_groups [ str ] = { n = i } end
if not edge_groups [ str ] then
i = i + 1
edge_groups [ str ] = { n = i }
end
table.insert ( edge_groups [ str ] , k )
table.insert ( edge_groups [ str ] , k )
end
end
local categories = { }
local categories = { }
@ -343,12 +404,12 @@ function World:generateCategoriesMasks()
end
end
end
end
for k , v in pairs ( expanded ) do
for k , v in pairs ( expanded ) do
local category = { categories [ k ] }
local category = { categories [ k ] }
local current_masks = { }
local current_masks = { }
for _ , c in ipairs ( v ) do
for _ , c in ipairs ( v ) do
table.insert ( current_masks , categories [ c ] )
table.insert ( current_masks , categories [ c ] )
end
end
self.masks [ k ] = { categories = category , masks = current_masks }
self.masks [ k ] = { categories = category , masks = current_masks }
end
end
end
end
@ -356,24 +417,39 @@ function World:getCollisionCallbacksTable()
local collision_table = { }
local collision_table = { }
for collision_class_name , collision_class in pairs ( self.collision_classes ) do
for collision_class_name , collision_class in pairs ( self.collision_classes ) do
collision_table [ collision_class_name ] = { }
collision_table [ collision_class_name ] = { }
for _ , v in ipairs ( collision_class.enter or { } ) do table.insert ( collision_table [ collision_class_name ] , { type = ' enter ' , other = v } ) end
for _ , v in ipairs ( collision_class.enter or { } ) do
for _ , v in ipairs ( collision_class.exit or { } ) do table.insert ( collision_table [ collision_class_name ] , { type = ' exit ' , other = v } ) end
table.insert ( collision_table [ collision_class_name ] , { type = " enter " , other = v } )
for _ , v in ipairs ( collision_class.pre or { } ) do table.insert ( collision_table [ collision_class_name ] , { type = ' pre ' , other = v } ) end
end
for _ , v in ipairs ( collision_class.post or { } ) do table.insert ( collision_table [ collision_class_name ] , { type = ' post ' , other = v } ) end
for _ , v in ipairs ( collision_class.exit or { } ) do
table.insert ( collision_table [ collision_class_name ] , { type = " exit " , other = v } )
end
for _ , v in ipairs ( collision_class.pre or { } ) do
table.insert ( collision_table [ collision_class_name ] , { type = " pre " , other = v } )
end
for _ , v in ipairs ( collision_class.post or { } ) do
table.insert ( collision_table [ collision_class_name ] , { type = " post " , other = v } )
end
end
end
return collision_table
return collision_table
end
end
local function collEnsure ( collision_class_name1 , a , collision_class_name2 , b )
local function collEnsure ( collision_class_name1 , a , collision_class_name2 , b )
if a.collision_class == collision_class_name2 and b.collision_class == collision_class_name1 then return b , a
if a.collision_class == collision_class_name2 and b.collision_class == collision_class_name1 then
else return a , b end
return b , a
else
return a , b
end
end
end
local function collIf ( collision_class_name1 , collision_class_name2 , a , b )
local function collIf ( collision_class_name1 , collision_class_name2 , a , b )
if ( a.collision_class == collision_class_name1 and b.collision_class == collision_class_name2 ) or
if
( a.collision_class == collision_class_name2 and b.collision_class == collision_class_name1 ) then
( a.collision_class == collision_class_name1 and b.collision_class == collision_class_name2 )
or ( a.collision_class == collision_class_name2 and b.collision_class == collision_class_name1 )
then
return true
return true
else return false end
else
return false
end
end
end
function World . collisionOnEnter ( fixture_a , fixture_b , contact )
function World . collisionOnEnter ( fixture_a , fixture_b , contact )
@ -384,22 +460,33 @@ function World.collisionOnEnter(fixture_a, fixture_b, contact)
for _ , collision in ipairs ( a.world . collisions.on_enter . sensor ) do
for _ , collision in ipairs ( a.world . collisions.on_enter . sensor ) do
if collIf ( collision.type1 , collision.type2 , a , b ) then
if collIf ( collision.type1 , collision.type2 , a , b ) then
a , b = collEnsure ( collision.type1 , a , collision.type2 , b )
a , b = collEnsure ( collision.type1 , a , collision.type2 , b )
table.insert ( a.collision_events [ collision.type2 ] , { collision_type = ' enter ' , collider_1 = a , collider_2 = b , contact = contact } )
table.insert (
a.collision_events [ collision.type2 ] ,
{ collision_type = " enter " , collider_1 = a , collider_2 = b , contact = contact }
)
if collision.type1 == collision.type2 then
if collision.type1 == collision.type2 then
table.insert ( b.collision_events [ collision.type1 ] , { collision_type = ' enter ' , collider_1 = b , collider_2 = a , contact = contact } )
table.insert (
b.collision_events [ collision.type1 ] ,
{ collision_type = " enter " , collider_1 = b , collider_2 = a , contact = contact }
)
end
end
end
end
end
end
end
end
elseif not ( fixture_a : isSensor ( ) or fixture_b : isSensor ( ) ) then
elseif not ( fixture_a : isSensor ( ) or fixture_b : isSensor ( ) ) then
if a and b then
if a and b then
for _ , collision in ipairs ( a.world . collisions.on_enter . non_sensor ) do
for _ , collision in ipairs ( a.world . collisions.on_enter . non_sensor ) do
if collIf ( collision.type1 , collision.type2 , a , b ) then
if collIf ( collision.type1 , collision.type2 , a , b ) then
a , b = collEnsure ( collision.type1 , a , collision.type2 , b )
a , b = collEnsure ( collision.type1 , a , collision.type2 , b )
table.insert ( a.collision_events [ collision.type2 ] , { collision_type = ' enter ' , collider_1 = a , collider_2 = b , contact = contact } )
table.insert (
a.collision_events [ collision.type2 ] ,
{ collision_type = " enter " , collider_1 = a , collider_2 = b , contact = contact }
)
if collision.type1 == collision.type2 then
if collision.type1 == collision.type2 then
table.insert ( b.collision_events [ collision.type1 ] , { collision_type = ' enter ' , collider_1 = b , collider_2 = a , contact = contact } )
table.insert (
b.collision_events [ collision.type1 ] ,
{ collision_type = " enter " , collider_1 = b , collider_2 = a , contact = contact }
)
end
end
end
end
end
end
@ -415,22 +502,33 @@ function World.collisionOnExit(fixture_a, fixture_b, contact)
for _ , collision in ipairs ( a.world . collisions.on_exit . sensor ) do
for _ , collision in ipairs ( a.world . collisions.on_exit . sensor ) do
if collIf ( collision.type1 , collision.type2 , a , b ) then
if collIf ( collision.type1 , collision.type2 , a , b ) then
a , b = collEnsure ( collision.type1 , a , collision.type2 , b )
a , b = collEnsure ( collision.type1 , a , collision.type2 , b )
table.insert ( a.collision_events [ collision.type2 ] , { collision_type = ' exit ' , collider_1 = a , collider_2 = b , contact = contact } )
table.insert (
a.collision_events [ collision.type2 ] ,
{ collision_type = " exit " , collider_1 = a , collider_2 = b , contact = contact }
)
if collision.type1 == collision.type2 then
if collision.type1 == collision.type2 then
table.insert ( b.collision_events [ collision.type1 ] , { collision_type = ' exit ' , collider_1 = b , collider_2 = a , contact = contact } )
table.insert (
b.collision_events [ collision.type1 ] ,
{ collision_type = " exit " , collider_1 = b , collider_2 = a , contact = contact }
)
end
end
end
end
end
end
end
end
elseif not ( fixture_a : isSensor ( ) or fixture_b : isSensor ( ) ) then
elseif not ( fixture_a : isSensor ( ) or fixture_b : isSensor ( ) ) then
if a and b then
if a and b then
for _ , collision in ipairs ( a.world . collisions.on_exit . non_sensor ) do
for _ , collision in ipairs ( a.world . collisions.on_exit . non_sensor ) do
if collIf ( collision.type1 , collision.type2 , a , b ) then
if collIf ( collision.type1 , collision.type2 , a , b ) then
a , b = collEnsure ( collision.type1 , a , collision.type2 , b )
a , b = collEnsure ( collision.type1 , a , collision.type2 , b )
table.insert ( a.collision_events [ collision.type2 ] , { collision_type = ' exit ' , collider_1 = a , collider_2 = b , contact = contact } )
table.insert (
a.collision_events [ collision.type2 ] ,
{ collision_type = " exit " , collider_1 = a , collider_2 = b , contact = contact }
)
if collision.type1 == collision.type2 then
if collision.type1 == collision.type2 then
table.insert ( b.collision_events [ collision.type1 ] , { collision_type = ' exit ' , collider_1 = b , collider_2 = a , contact = contact } )
table.insert (
b.collision_events [ collision.type1 ] ,
{ collision_type = " exit " , collider_1 = b , collider_2 = a , contact = contact }
)
end
end
end
end
end
end
@ -453,7 +551,6 @@ function World.collisionPre(fixture_a, fixture_b, contact)
end
end
end
end
end
end
elseif not ( fixture_a : isSensor ( ) or fixture_b : isSensor ( ) ) then
elseif not ( fixture_a : isSensor ( ) or fixture_b : isSensor ( ) ) then
if a and b then
if a and b then
for _ , collision in ipairs ( a.world . collisions.pre . non_sensor ) do
for _ , collision in ipairs ( a.world . collisions.pre . non_sensor ) do
@ -484,7 +581,6 @@ function World.collisionPost(fixture_a, fixture_b, contact, ni1, ti1, ni2, ti2)
end
end
end
end
end
end
elseif not ( fixture_a : isSensor ( ) or fixture_b : isSensor ( ) ) then
elseif not ( fixture_a : isSensor ( ) or fixture_b : isSensor ( ) ) then
if a and b then
if a and b then
for _ , collision in ipairs ( a.world . collisions.post . non_sensor ) do
for _ , collision in ipairs ( a.world . collisions.post . non_sensor ) do
@ -501,34 +597,36 @@ function World.collisionPost(fixture_a, fixture_b, contact, ni1, ti1, ni2, ti2)
end
end
function World : newCircleCollider ( x , y , r , settings )
function World : newCircleCollider ( x , y , r , settings )
return self.wf . Collider.new ( self , ' Circle ' , x , y , r , settings )
return self.wf . Collider.new ( self , " Circle " , x , y , r , settings )
end
end
function World : newRectangleCollider ( x , y , w , h , settings )
function World : newRectangleCollider ( x , y , w , h , settings )
return self.wf . Collider.new ( self , ' Rectangle ' , x , y , w , h , settings )
return self.wf . Collider.new ( self , " Rectangle " , x , y , w , h , settings )
end
end
function World : newBSGRectangleCollider ( x , y , w , h , corner_cut_size , settings )
function World : newBSGRectangleCollider ( x , y , w , h , corner_cut_size , settings )
return self.wf . Collider.new ( self , ' BSGRectangle ' , x , y , w , h , corner_cut_size , settings )
return self.wf . Collider.new ( self , " BSGRectangle " , x , y , w , h , corner_cut_size , settings )
end
end
function World : newPolygonCollider ( vertices , settings )
function World : newPolygonCollider ( vertices , settings )
return self.wf . Collider.new ( self , ' Polygon ' , vertices , settings )
return self.wf . Collider.new ( self , " Polygon " , vertices , settings )
end
end
function World : newLineCollider ( x1 , y1 , x2 , y2 , settings )
function World : newLineCollider ( x1 , y1 , x2 , y2 , settings )
return self.wf . Collider.new ( self , ' Line ' , x1 , y1 , x2 , y2 , settings )
return self.wf . Collider.new ( self , " Line " , x1 , y1 , x2 , y2 , settings )
end
end
function World : newChainCollider ( vertices , loop , settings )
function World : newChainCollider ( vertices , loop , settings )
return self.wf . Collider.new ( self , ' Chain ' , vertices , loop , settings )
return self.wf . Collider.new ( self , " Chain " , vertices , loop , settings )
end
end
-- Internal AABB box2d query used before going for more specific and precise computations.
-- Internal AABB box2d query used before going for more specific and precise computations.
function World : _queryBoundingBox ( x1 , y1 , x2 , y2 )
function World : _queryBoundingBox ( x1 , y1 , x2 , y2 )
local colliders = { }
local colliders = { }
local callback = function ( fixture )
local callback = function ( fixture )
if not fixture : isSensor ( ) then table.insert ( colliders , fixture : getUserData ( ) ) end
if not fixture : isSensor ( ) then
table.insert ( colliders , fixture : getUserData ( ) )
end
return true
return true
end
end
self.box2d_world : queryBoundingBox ( x1 , y1 , x2 , y2 , callback )
self.box2d_world : queryBoundingBox ( x1 , y1 , x2 , y2 , callback )
@ -536,7 +634,7 @@ function World:_queryBoundingBox(x1, y1, x2, y2)
end
end
function World : collisionClassInCollisionClassesList ( collision_class , collision_classes )
function World : collisionClassInCollisionClassesList ( collision_class , collision_classes )
if collision_classes [ 1 ] == ' All ' then
if collision_classes [ 1 ] == " All " then
local all_collision_classes = { }
local all_collision_classes = { }
for class , _ in pairs ( self.collision_classes ) do
for class , _ in pairs ( self.collision_classes ) do
table.insert ( all_collision_classes , class )
table.insert ( all_collision_classes , class )
@ -552,25 +650,43 @@ function World:collisionClassInCollisionClassesList(collision_class, collision_c
end
end
end
end
for _ , class in ipairs ( all_collision_classes ) do
for _ , class in ipairs ( all_collision_classes ) do
if class == collision_class then return true end
if class == collision_class then
return true
end
end
end
else
else
for _ , class in ipairs ( collision_classes ) do
for _ , class in ipairs ( collision_classes ) do
if class == collision_class then return true end
if class == collision_class then
return true
end
end
end
end
end
end
end
function World : queryCircleArea ( x , y , radius , collision_class_names )
function World : queryCircleArea ( x , y , radius , collision_class_names )
if not collision_class_names then collision_class_names = { ' All ' } end
if not collision_class_names then
if self.query_debug_drawing_enabled then table.insert ( self.query_debug_draw , { type = ' circle ' , x = x , y = y , r = radius , frames = self.draw_query_for_n_frames } ) end
collision_class_names = { " All " }
end
if self.query_debug_drawing_enabled then
table.insert (
self.query_debug_draw ,
{ type = " circle " , x = x , y = y , r = radius , frames = self.draw_query_for_n_frames }
)
end
local colliders = self : _queryBoundingBox ( x - radius , y - radius , x + radius , y + radius )
local colliders = self : _queryBoundingBox ( x - radius , y - radius , x + radius , y + radius )
local outs = { }
local outs = { }
for _ , collider in ipairs ( colliders ) do
for _ , collider in ipairs ( colliders ) do
if self : collisionClassInCollisionClassesList ( collider.collision_class , collision_class_names ) then
if self : collisionClassInCollisionClassesList ( collider.collision_class , collision_class_names ) then
for _ , fixture in ipairs ( collider.body : getFixtures ( ) ) do
for _ , fixture in ipairs ( collider.body : getFixtures ( ) ) do
if self.wf . Math.polygon . getCircleIntersection ( x , y , radius , { collider.body : getWorldPoints ( fixture : getShape ( ) : getPoints ( ) ) } ) then
if
self.wf . Math.polygon . getCircleIntersection (
x ,
y ,
radius ,
{ collider.body : getWorldPoints ( fixture : getShape ( ) : getPoints ( ) ) }
)
then
table.insert ( outs , collider )
table.insert ( outs , collider )
break
break
end
end
@ -581,15 +697,27 @@ function World:queryCircleArea(x, y, radius, collision_class_names)
end
end
function World : queryRectangleArea ( x , y , w , h , collision_class_names )
function World : queryRectangleArea ( x , y , w , h , collision_class_names )
if not collision_class_names then collision_class_names = { ' All ' } end
if not collision_class_names then
if self.query_debug_drawing_enabled then table.insert ( self.query_debug_draw , { type = ' rectangle ' , x = x , y = y , w = w , h = h , frames = self.draw_query_for_n_frames } ) end
collision_class_names = { " All " }
end
if self.query_debug_drawing_enabled then
table.insert (
self.query_debug_draw ,
{ type = " rectangle " , x = x , y = y , w = w , h = h , frames = self.draw_query_for_n_frames }
)
end
local colliders = self : _queryBoundingBox ( x , y , x + w , y + h )
local colliders = self : _queryBoundingBox ( x , y , x + w , y + h )
local outs = { }
local outs = { }
for _ , collider in ipairs ( colliders ) do
for _ , collider in ipairs ( colliders ) do
if self : collisionClassInCollisionClassesList ( collider.collision_class , collision_class_names ) then
if self : collisionClassInCollisionClassesList ( collider.collision_class , collision_class_names ) then
for _ , fixture in ipairs ( collider.body : getFixtures ( ) ) do
for _ , fixture in ipairs ( collider.body : getFixtures ( ) ) do
if self.wf . Math.polygon . isPolygonInside ( { x , y , x + w , y , x + w , y + h , x , y + h } , { collider.body : getWorldPoints ( fixture : getShape ( ) : getPoints ( ) ) } ) then
if
self.wf . Math.polygon . isPolygonInside (
{ x , y , x + w , y , x + w , y + h , x , y + h } ,
{ collider.body : getWorldPoints ( fixture : getShape ( ) : getPoints ( ) ) }
)
then
table.insert ( outs , collider )
table.insert ( outs , collider )
break
break
end
end
@ -600,21 +728,35 @@ function World:queryRectangleArea(x, y, w, h, collision_class_names)
end
end
function World : queryPolygonArea ( vertices , collision_class_names )
function World : queryPolygonArea ( vertices , collision_class_names )
if not collision_class_names then collision_class_names = { ' All ' } end
if not collision_class_names then
if self.query_debug_drawing_enabled then table.insert ( self.query_debug_draw , { type = ' polygon ' , vertices = vertices , frames = self.draw_query_for_n_frames } ) end
collision_class_names = { " All " }
end
if self.query_debug_drawing_enabled then
table.insert (
self.query_debug_draw ,
{ type = " polygon " , vertices = vertices , frames = self.draw_query_for_n_frames }
)
end
local cx , cy = self.wf . Math.polygon . getCentroid ( vertices )
local cx , cy = self.wf . Math.polygon . getCentroid ( vertices )
local d_max = 0
local d_max = 0
for i = 1 , # vertices , 2 do
for i = 1 , # vertices , 2 do
local d = self.wf . Math.line . getLength ( cx , cy , vertices [ i ] , vertices [ i + 1 ] )
local d = self.wf . Math.line . getLength ( cx , cy , vertices [ i ] , vertices [ i + 1 ] )
if d > d_max then d_max = d end
if d > d_max then
d_max = d
end
end
local colliders = self : _queryBoundingBox ( cx - d_max , cy - d_max , cx + d_max , cy + d_max )
end
local colliders = self : _queryBoundingBox ( cx - d_max , cy - d_max , cx + d_max , cy + d_max )
local outs = { }
local outs = { }
for _ , collider in ipairs ( colliders ) do
for _ , collider in ipairs ( colliders ) do
if self : collisionClassInCollisionClassesList ( collider.collision_class , collision_class_names ) then
if self : collisionClassInCollisionClassesList ( collider.collision_class , collision_class_names ) then
for _ , fixture in ipairs ( collider.body : getFixtures ( ) ) do
for _ , fixture in ipairs ( collider.body : getFixtures ( ) ) do
if self.wf . Math.polygon . isPolygonInside ( vertices , { collider.body : getWorldPoints ( fixture : getShape ( ) : getPoints ( ) ) } ) then
if
self.wf . Math.polygon . isPolygonInside (
vertices ,
{ collider.body : getWorldPoints ( fixture : getShape ( ) : getPoints ( ) ) }
)
then
table.insert ( outs , collider )
table.insert ( outs , collider )
break
break
end
end
@ -625,14 +767,21 @@ function World:queryPolygonArea(vertices, collision_class_names)
end
end
function World : queryLine ( x1 , y1 , x2 , y2 , collision_class_names )
function World : queryLine ( x1 , y1 , x2 , y2 , collision_class_names )
if not collision_class_names then collision_class_names = { ' All ' } end
if not collision_class_names then
collision_class_names = { " All " }
end
if self.query_debug_drawing_enabled then
if self.query_debug_drawing_enabled then
table.insert ( self.query_debug_draw , { type = ' line ' , x1 = x1 , y1 = y1 , x2 = x2 , y2 = y2 , frames = self.draw_query_for_n_frames } )
table.insert (
self.query_debug_draw ,
{ type = " line " , x1 = x1 , y1 = y1 , x2 = x2 , y2 = y2 , frames = self.draw_query_for_n_frames }
)
end
end
local colliders = { }
local colliders = { }
local callback = function ( fixture , ... )
local callback = function ( fixture , ... )
if not fixture : isSensor ( ) then table.insert ( colliders , fixture : getUserData ( ) ) end
if not fixture : isSensor ( ) then
table.insert ( colliders , fixture : getUserData ( ) )
end
return 1
return 1
end
end
self.box2d_world : rayCast ( x1 , y1 , x2 , y2 , callback )
self.box2d_world : rayCast ( x1 , y1 , x2 , y2 , callback )
@ -647,10 +796,14 @@ function World:queryLine(x1, y1, x2, y2, collision_class_names)
end
end
function World : addJoint ( joint_type , ... )
function World : addJoint ( joint_type , ... )
local args = { ... }
local args = { ... }
if args [ 1 ] . body then args [ 1 ] = args [ 1 ] . body end
if args [ 1 ] . body then
if type ( args [ 2 ] ) == " table " and args [ 2 ] . body then args [ 2 ] = args [ 2 ] . body end
args [ 1 ] = args [ 1 ] . body
local joint = love.physics [ ' new ' .. joint_type ] ( unpack ( args ) )
end
if type ( args [ 2 ] ) == " table " and args [ 2 ] . body then
args [ 2 ] = args [ 2 ] . body
end
local joint = love.physics [ " new " .. joint_type ] ( unpack ( args ) )
return joint
return joint
end
end
@ -665,13 +818,13 @@ function World:destroy()
collider : destroy ( )
collider : destroy ( )
end
end
local joints = self.box2d_world : getJoints ( )
local joints = self.box2d_world : getJoints ( )
for _ , joint in ipairs ( joints ) do joint : destroy ( ) end
for _ , joint in ipairs ( joints ) do
joint : destroy ( )
end
self.box2d_world : destroy ( )
self.box2d_world : destroy ( )
self.box2d_world = nil
self.box2d_world = nil
end
end
local Collider = { }
local Collider = { }
Collider.__index = Collider
Collider.__index = Collider
@ -702,42 +855,60 @@ function Collider.new(world, collider_type, ...)
self.exit_collision_data = { }
self.exit_collision_data = { }
self.stay_collision_data = { }
self.stay_collision_data = { }
local args = { ... }
local args = { ... }
local shape , fixture
local shape , fixture
if self.type == ' Circle ' then
if self.type == " Circle " then
self.collision_class = ( args [ 4 ] and args [ 4 ] . collision_class ) or ' Default '
self.collision_class = ( args [ 4 ] and args [ 4 ] . collision_class ) or " Default "
self.body = love.physics . newBody ( self.world . box2d_world , args [ 1 ] , args [ 2 ] , ( args [ 4 ] and args [ 4 ] . body_type ) or ' dynamic ' )
self.body =
love.physics . newBody ( self.world . box2d_world , args [ 1 ] , args [ 2 ] , ( args [ 4 ] and args [ 4 ] . body_type ) or " dynamic " )
shape = love.physics . newCircleShape ( args [ 3 ] )
shape = love.physics . newCircleShape ( args [ 3 ] )
elseif self.type == " Rectangle " then
elseif self.type == ' Rectangle ' then
self.collision_class = ( args [ 5 ] and args [ 5 ] . collision_class ) or " Default "
self.collision_class = ( args [ 5 ] and args [ 5 ] . collision_class ) or ' Default '
self.body = love.physics . newBody (
self.body = love.physics . newBody ( self.world . box2d_world , args [ 1 ] + args [ 3 ] / 2 , args [ 2 ] + args [ 4 ] / 2 , ( args [ 5 ] and args [ 5 ] . body_type ) or ' dynamic ' )
self.world . box2d_world ,
args [ 1 ] + args [ 3 ] / 2 ,
args [ 2 ] + args [ 4 ] / 2 ,
( args [ 5 ] and args [ 5 ] . body_type ) or " dynamic "
)
shape = love.physics . newRectangleShape ( args [ 3 ] , args [ 4 ] )
shape = love.physics . newRectangleShape ( args [ 3 ] , args [ 4 ] )
elseif self.type == " BSGRectangle " then
elseif self.type == ' BSGRectangle ' then
self.collision_class = ( args [ 6 ] and args [ 6 ] . collision_class ) or " Default "
self.collision_class = ( args [ 6 ] and args [ 6 ] . collision_class ) or ' Default '
self.body = love.physics . newBody (
self.body = love.physics . newBody ( self.world . box2d_world , args [ 1 ] + args [ 3 ] / 2 , args [ 2 ] + args [ 4 ] / 2 , ( args [ 6 ] and args [ 6 ] . body_type ) or ' dynamic ' )
self.world . box2d_world ,
args [ 1 ] + args [ 3 ] / 2 ,
args [ 2 ] + args [ 4 ] / 2 ,
( args [ 6 ] and args [ 6 ] . body_type ) or " dynamic "
)
local w , h , s = args [ 3 ] , args [ 4 ] , args [ 5 ]
local w , h , s = args [ 3 ] , args [ 4 ] , args [ 5 ]
shape = love.physics . newPolygonShape ( {
shape = love.physics . newPolygonShape ( {
- w / 2 , - h / 2 + s , - w / 2 + s , - h / 2 ,
- w / 2 ,
w / 2 - s , - h / 2 , w / 2 , - h / 2 + s ,
- h / 2 + s ,
w / 2 , h / 2 - s , w / 2 - s , h / 2 ,
- w / 2 + s ,
- w / 2 + s , h / 2 , - w / 2 , h / 2 - s
- h / 2 ,
w / 2 - s ,
- h / 2 ,
w / 2 ,
- h / 2 + s ,
w / 2 ,
h / 2 - s ,
w / 2 - s ,
h / 2 ,
- w / 2 + s ,
h / 2 ,
- w / 2 ,
h / 2 - s ,
} )
} )
elseif self.type == " Polygon " then
elseif self.type == ' Polygon ' then
self.collision_class = ( args [ 2 ] and args [ 2 ] . collision_class ) or " Default "
self.collision_class = ( args [ 2 ] and args [ 2 ] . collision_class ) or ' Default '
self.body = love.physics . newBody ( self.world . box2d_world , 0 , 0 , ( args [ 2 ] and args [ 2 ] . body_type ) or " dynamic " )
self.body = love.physics . newBody ( self.world . box2d_world , 0 , 0 , ( args [ 2 ] and args [ 2 ] . body_type ) or ' dynamic ' )
shape = love.physics . newPolygonShape ( unpack ( args [ 1 ] ) )
shape = love.physics . newPolygonShape ( unpack ( args [ 1 ] ) )
elseif self.type == " Line " then
elseif self.type == ' Line ' then
self.collision_class = ( args [ 5 ] and args [ 5 ] . collision_class ) or " Default "
self.collision_class = ( args [ 5 ] and args [ 5 ] . collision_class ) or ' Default '
self.body = love.physics . newBody ( self.world . box2d_world , 0 , 0 , ( args [ 5 ] and args [ 5 ] . body_type ) or " dynamic " )
self.body = love.physics . newBody ( self.world . box2d_world , 0 , 0 , ( args [ 5 ] and args [ 5 ] . body_type ) or ' dynamic ' )
shape = love.physics . newEdgeShape ( args [ 1 ] , args [ 2 ] , args [ 3 ] , args [ 4 ] )
shape = love.physics . newEdgeShape ( args [ 1 ] , args [ 2 ] , args [ 3 ] , args [ 4 ] )
elseif self.type == " Chain " then
elseif self.type == ' Chain ' then
self.collision_class = ( args [ 3 ] and args [ 3 ] . collision_class ) or " Default "
self.collision_class = ( args [ 3 ] and args [ 3 ] . collision_class ) or ' Default '
self.body = love.physics . newBody ( self.world . box2d_world , 0 , 0 , ( args [ 3 ] and args [ 3 ] . body_type ) or " dynamic " )
self.body = love.physics . newBody ( self.world . box2d_world , 0 , 0 , ( args [ 3 ] and args [ 3 ] . body_type ) or ' dynamic ' )
shape = love.physics . newChainShape ( args [ 1 ] , unpack ( args [ 2 ] ) )
shape = love.physics . newChainShape ( args [ 1 ] , unpack ( args [ 2 ] ) )
end
end
@ -752,9 +923,9 @@ function Collider.new(world, collider_type, ...)
sensor : setSensor ( true )
sensor : setSensor ( true )
sensor : setUserData ( self )
sensor : setUserData ( self )
self.shapes [ ' main ' ] = shape
self.shapes [ " main " ] = shape
self.fixtures [ ' main ' ] = fixture
self.fixtures [ " main " ] = fixture
self.sensors [ ' main ' ] = sensor
self.sensors [ " main " ] = sensor
self.shape = shape
self.shape = shape
self.fixture = fixture
self.fixture = fixture
@ -764,21 +935,45 @@ function Collider.new(world, collider_type, ...)
-- Points all body, fixture and shape functions to this wf.Collider object
-- Points all body, fixture and shape functions to this wf.Collider object
-- This means that the user can call collider:setLinearVelocity for instance without having to say collider.body:setLinearVelocity
-- This means that the user can call collider:setLinearVelocity for instance without having to say collider.body:setLinearVelocity
for k , v in pairs ( self.body . __index ) do
for k , v in pairs ( self.body . __index ) do
if k ~= ' __gc ' and k ~= ' __eq ' and k ~= ' __index ' and k ~= ' __tostring ' and k ~= ' destroy ' and k ~= ' type ' and k ~= ' typeOf ' then
if
k ~= " __gc "
and k ~= " __eq "
and k ~= " __index "
and k ~= " __tostring "
and k ~= " destroy "
and k ~= " type "
and k ~= " typeOf "
then
self [ k ] = function ( self , ... )
self [ k ] = function ( self , ... )
return v ( self.body , ... )
return v ( self.body , ... )
end
end
end
end
end
end
for k , v in pairs ( self.fixture . __index ) do
for k , v in pairs ( self.fixture . __index ) do
if k ~= ' __gc ' and k ~= ' __eq ' and k ~= ' __index ' and k ~= ' __tostring ' and k ~= ' destroy ' and k ~= ' type ' and k ~= ' typeOf ' then
if
k ~= " __gc "
and k ~= " __eq "
and k ~= " __index "
and k ~= " __tostring "
and k ~= " destroy "
and k ~= " type "
and k ~= " typeOf "
then
self [ k ] = function ( self , ... )
self [ k ] = function ( self , ... )
return v ( self.fixture , ... )
return v ( self.fixture , ... )
end
end
end
end
end
end
for k , v in pairs ( self.shape . __index ) do
for k , v in pairs ( self.shape . __index ) do
if k ~= ' __gc ' and k ~= ' __eq ' and k ~= ' __index ' and k ~= ' __tostring ' and k ~= ' destroy ' and k ~= ' type ' and k ~= ' typeOf ' then
if
k ~= " __gc "
and k ~= " __eq "
and k ~= " __index "
and k ~= " __tostring "
and k ~= " destroy "
and k ~= " type "
and k ~= " typeOf "
then
self [ k ] = function ( self , ... )
self [ k ] = function ( self , ... )
return v ( self.shape , ... )
return v ( self.shape , ... )
end
end
@ -796,7 +991,9 @@ function Collider:collisionEventsClear()
end
end
function Collider : setCollisionClass ( collision_class_name )
function Collider : setCollisionClass ( collision_class_name )
if not self.world . collision_classes [ collision_class_name ] then error ( " Collision class " .. collision_class_name .. " doesn't exist. " ) end
if not self.world . collision_classes [ collision_class_name ] then
error ( " Collision class " .. collision_class_name .. " doesn't exist. " )
end
self.collision_class = collision_class_name
self.collision_class = collision_class_name
for _ , fixture in pairs ( self.fixtures ) do
for _ , fixture in pairs ( self.fixtures ) do
if self.world . masks [ collision_class_name ] then
if self.world . masks [ collision_class_name ] then
@ -810,10 +1007,15 @@ function Collider:enter(other_collision_class_name)
local events = self.collision_events [ other_collision_class_name ]
local events = self.collision_events [ other_collision_class_name ]
if events and # events >= 1 then
if events and # events >= 1 then
for _ , e in ipairs ( events ) do
for _ , e in ipairs ( events ) do
if e.collision_type == ' enter ' then
if e.collision_type == " enter " then
if not self.collision_stay [ other_collision_class_name ] then self.collision_stay [ other_collision_class_name ] = { } end
if not self.collision_stay [ other_collision_class_name ] then
table.insert ( self.collision_stay [ other_collision_class_name ] , { collider = e.collider_2 , contact = e.contact } )
self.collision_stay [ other_collision_class_name ] = { }
self.enter_collision_data [ other_collision_class_name ] = { collider = e.collider_2 , contact = e.contact }
end
table.insert (
self.collision_stay [ other_collision_class_name ] ,
{ collider = e.collider_2 , contact = e.contact }
)
self.enter_collision_data [ other_collision_class_name ] = { collider = e.collider_2 , contact = e.contact }
return true
return true
end
end
end
end
@ -828,14 +1030,16 @@ function Collider:exit(other_collision_class_name)
local events = self.collision_events [ other_collision_class_name ]
local events = self.collision_events [ other_collision_class_name ]
if events and # events >= 1 then
if events and # events >= 1 then
for _ , e in ipairs ( events ) do
for _ , e in ipairs ( events ) do
if e.collision_type == ' exit ' then
if e.collision_type == " exit " then
if self.collision_stay [ other_collision_class_name ] then
if self.collision_stay [ other_collision_class_name ] then
for i = # self.collision_stay [ other_collision_class_name ] , 1 , - 1 do
for i = # self.collision_stay [ other_collision_class_name ] , 1 , - 1 do
local collision_stay = self.collision_stay [ other_collision_class_name ] [ i ]
local collision_stay = self.collision_stay [ other_collision_class_name ] [ i ]
if collision_stay.collider . id == e.collider_2 . id then table.remove ( self.collision_stay [ other_collision_class_name ] , i ) end
if collision_stay.collider . id == e.collider_2 . id then
table.remove ( self.collision_stay [ other_collision_class_name ] , i )
end
end
end
end
self.exit_collision_data [ other_collision_class_name ] = { collider = e.collider_2 , contact = e.contact }
end
self.exit_collision_data [ other_collision_class_name ] = { collider = e.collider_2 , contact = e.contact }
return true
return true
end
end
end
end
@ -875,9 +1079,11 @@ function Collider:getObject()
end
end
function Collider : addShape ( shape_name , shape_type , ... )
function Collider : addShape ( shape_name , shape_type , ... )
if self.shapes [ shape_name ] or self.fixtures [ shape_name ] then error ( " Shape/fixture " .. shape_name .. " already exists. " ) end
if self.shapes [ shape_name ] or self.fixtures [ shape_name ] then
local args = { ... }
error ( " Shape/fixture " .. shape_name .. " already exists. " )
local shape = love.physics [ ' new ' .. shape_type ] ( unpack ( args ) )
end
local args = { ... }
local shape = love.physics [ " new " .. shape_type ] ( unpack ( args ) )
local fixture = love.physics . newFixture ( self.body , shape )
local fixture = love.physics . newFixture ( self.body , shape )
if self.world . masks [ self.collision_class ] then
if self.world . masks [ self.collision_class ] then
fixture : setCategory ( unpack ( self.world . masks [ self.collision_class ] . categories ) )
fixture : setCategory ( unpack ( self.world . masks [ self.collision_class ] . categories ) )
@ -894,7 +1100,9 @@ function Collider:addShape(shape_name, shape_type, ...)
end
end
function Collider : removeShape ( shape_name )
function Collider : removeShape ( shape_name )
if not self.shapes [ shape_name ] then return end
if not self.shapes [ shape_name ] then
return
end
self.shapes [ shape_name ] = nil
self.shapes [ shape_name ] = nil
self.fixtures [ shape_name ] : setUserData ( nil )
self.fixtures [ shape_name ] : setUserData ( nil )
self.fixtures [ shape_name ] : destroy ( )
self.fixtures [ shape_name ] : destroy ( )
@ -926,4 +1134,3 @@ wf.World = World
wf.Collider = Collider
wf.Collider = Collider
return wf
return wf