# Getting stuck in the wall

Hey all,

I’m playing around with the physics engine, but I came upon an issue I cannot seem to resolve; I spawn a bunch of circles (15), add a dynamic body to it, and give them a random velocity : (simplified code)

``````globe = display.newCircle(
math.random(30, FIELD.WIDTH-30),
math.random(30, FIELD.HEIGHT-30),
5 )
physics.addBody( globe, "dynamic", { radius=5, bounce=0.99 } )
globe.setLinearVelocity(Xv, Yv)
``````

I have my “playfield” bordered by rectangles that are “static” body;

``````bot = rect(0, FIELD.HEIGHT, FIELD.WIDTH, 15, green)
right = rect(FIELD.WIDTH-5, 0,  15, FIELD.HEIGHT, purple)

top = rect(0, 0, FIELD.WIDTH, 15, green)
left = rect(0, 0, 5, FIELD.HEIGHT, red)

physics.addBody( top, "static" )
physics.addBody( bot, "static" )
physics.addBody( left, "static" )
physics.addBody( right, "static" )

function rect(x, y, w, h, color)
local new_x = x+(w/2)
local new_y = y+(h/2)
local r = display.newRect(new_x, new_y, w, h)
r.fill = color
return r
end
``````

After running the simulation for a few seconds, some globes get stuck to the wall; I’m not exactly sure what happens, but I observe that Xv or Yv drops to 0 in this state, my attempt to fix this was to run check regularly for this case and reset Xv or Yv to the initial state (which I store); while this sometimes fixes it, mostly it does not; (simplified)

``````if (vx == 0 or vy == 0) then
new_vx = vx
new_vy = vy

if (vx == 0) then
new_vx = globe[id].init_Xv
end
if (vy == 0) then
new_vy = globe[id].init_Yv
end

globe[id]:setLinearVelocity(new_vx, new_vy)
end
``````

I also attempted to make the border not straight by adding, but again no luck;

``````r.path.x4 = -1
r.path.x3 = -2
r.path.x2 = -3
r.path.x1 = -4
``````

I then tried to round the x and y position because I believe it might be related to floating calculations; so I round the numbers and reset Xv and Yv; (depending on what is 0) Sadly this does not resolve it either; The last thing I tried is to teleport them away from the wall while resetting :

``````globe[id].x = round(globe[id].x) + (math.random(20,30)/10)
globe[id].y = round(globe[id].y) + (math.random(20,30)/10)
globe[id]:setLinearVelocity(new_vx, new_vy)
``````

While this helps somewhat, its clearly visible, and not a full solution; Does anyone have an idea how to resolve this ?

This is what I want to recreate : https://upload.wikimedia.org/wikipedia/commons/6/6d/Translational_motion.gif

Thanks for the help / idea’s !

Very hard to understand how your code works from these fragments. I would expect your globes to just drop down thanks to gravity since they are dynamic bodies.

Have you configured any collision detection for the globes and walls?

Hey Markus,

I set physics.setGravity( 0, 0 ) ; and globes are dynamic, walls are static;

The marked globe will only move horizontally against (/in) the wall;

This is the code (warning : its not clean )

``````-----------------------------------------------------------------------------------------
--
-- main.lua
--
-----------------------------------------------------------------------------------------

local physics = require( "physics" )
physics.start()
physics.setGravity( 0, 0 )
physics.setDrawMode( "hybrid" )

-- Hide status bar
display.setStatusBar( display.HiddenStatusBar )

-- Seed the random number generator
-- math.randomseed( os.time() )
math.randomseed(os.clock()*1000) -- os.time() is to easy

-- game constants
local FIELD = {WIDTH = 320, HEIGHT = 480}
local LEVEL = {START = 1, VERIFY = 2, REQUIREMENT = {}, ATOMS = {}, ENTROPY = {}, TEXT = {}}

local background

-- color definitions
local white 	= {1}
local black 	= {0}

local yellow 	= {255, 255, 0}
local red 		= {255, 0, 0 , 0.6}
local green 	= {0, 255, 0}
local blue 		= {0, 0, 255}

local pink 		= {255, 204, 204}
local orange	= {255, 128, 0}
local seablue	= {0, 255, 255}
local purple	= {255, 0, 255}

-- vars
local atoms = {}
local atom_count = 35

function create_borders()
bot = rect(0, FIELD.HEIGHT, FIELD.WIDTH, 15, green)
right = rect(FIELD.WIDTH-5, 0,  15, FIELD.HEIGHT, purple)

top = rect(0, 0, FIELD.WIDTH, 15, green)
left = rect(0, 0, 5, FIELD.HEIGHT, red)
-- playfield = rect(0, 0, FIELD.WIDTH, FIELD.HEIGHT, red)

-- physics.addBody( playfield, "static" )
physics.addBody( top, "static" )
physics.addBody( bot, "static" )
physics.addBody( left, "static" )
physics.addBody( right, "static" )
end

function create_atom(n)

-- we need a 1 or a -1
local function random_direction()

local result = math.random(0,1)
if result == 0 then
result = -1
end
return result
end

-- for n atoms
local count = 0
local atom_id = #atoms
while count < (n+1) do

-- determ type
local selected_atom = math.random(0,1)
-- local atom
if selected_atom == 0 then
atoms[atom_id] = display.newCircle(
math.random(30, FIELD.WIDTH-30),
math.random(30, FIELD.HEIGHT-30),
3 )
atoms[atom_id].fill = orange
physics.addBody( atoms[atom_id], "dynamic", { radius=5, bounce=0.99 } )
else
atoms[atom_id] = display.newCircle(
math.random(30, FIELD.WIDTH-30),
math.random(30, FIELD.HEIGHT-30),
5 )
atoms[atom_id].fill = purple
physics.addBody( atoms[atom_id], "dynamic", { radius=7, bounce=0.99 } )
end

local Xv = math.random( 40,120 ) * random_direction()
local Yv = math.random( 20,60 ) * random_direction()
atoms[atom_id]:setLinearVelocity(Xv, Yv)
atoms[atom_id].init_Xv = Xv
atoms[atom_id].init_Yv = Yv

atom_id = atom_id + 1
count = count + 1
end
end

-- changed from newRect that start with centered x,y
function rect(x, y, w, h, color)
local new_x = x+(w/2)
local new_y = y+(h/2)
local r = display.newRect(new_x, new_y, w, h)
r.fill = color
r.path.x4 = -1
r.path.x3 = -2
r.path.x2 = -3
r.path.x1 = -4
return r
end

function printatoms()

local atom_id = 0
local n = #atoms
while atom_id < (n+1) do

local vx, vy = atoms[atom_id]:getLinearVelocity()

local function round(number)
return number - (number % 1)
end

-- print ("vx:" .. round(vx) .. " vy:" .. round(vy))

if (vx == 0 or vy == 0) then
new_vx = vx
new_vy = vy

if (vx == 0) then
new_vx = atoms[atom_id].init_Xv
end
if (vy == 0) then
new_vy = atoms[atom_id].init_Yv
end

-- atoms[atom_id].fill = red

print ("x" .. atoms[atom_id].x .. " y:" .. atoms[atom_id].y)
print ("vx ori : " .. atoms[atom_id].init_Xv .. " vy ori: " .. atoms[atom_id].init_Yv)
print ("vx:" .. vx .. " vy:" .. vy .. " to vx:" .. new_vx .. " vy:" .. new_vy)
atoms[atom_id].x = round(atoms[atom_id].x) + (math.random(20,30)/10)
atoms[atom_id].y = round(atoms[atom_id].y) + (math.random(20,30)/10)
atoms[atom_id]:setLinearVelocity(new_vx, new_vy)
end
atom_id = atom_id + 1
end
end

function add_atoms()
atom_count = atom_count + 5;
create_atom(5)
print (#atoms)
-- draw_debug()
end

-- main function
function main()

create_borders()
-- generate atoms
create_atom(atom_count)
updateLoopTimer = timer.performWithDelay( 400, printatoms, 0 )
end

-- run the code
main()

-- return to menu
-- state = MENU.MENU``````

I ran your code and now I see what you mean. Strange behavior indeed, and I wasn’t able to solve it either.

Did some googling and it seems to be a “feature” of the Box2D engine. Maybe this can help you:

And this:

I tried `physics.setMKS("velocityThreshold", 0)` but it didn’t seem to have any effect as the balls still got stuck around the edges when colliding with too small velocity.

1 Like

Hey Markus,

Thanks for having a look! It’s weird nobody seemed to have faced this issue before; I can kinda work around it by the reseting velocity; but its far from ideal.

We also meet this issue and fixed, and we have submitted a pull request to submodule-box2d.

1 Like