physics body scale Group

I have a question with scale physics body. I have polygons in a group and I’m not add physics body before the Scale change, but the polygons physics don’t change after Scale change. What’s the problem??

Léo.

local Scala = function()

    for t=1, MapGroup.numChildren do

      pol=MapGroup[t];

      physics.addBody(pol, “static”, {density=0.9, friction=0.1});

    end;

  end;

  transition.to(MapGroup, {delay=3505,time=2000,xScale=zoom,yScale=zoom,onComplete=Scala});

[sharedmedia=core:attachments:3725]

Hi @suporte37,

You cannot scale objects with physics bodies. The visual object will scale, but the physics body will remain as if the object was not scaled.

Take care,

Brent

Hi Brent, I’m not add the physics bodies before scale. Do you know how to add shape on a polyline acessing x,y points? Thanks, Leo.

Hi Leo,

The absolute best utility I’ve found for adding physics bodies to polygons is linked below. It automatically handles both convex and concave polygon shapes (by creating multiple body elements if necessary), it aligns the shape properly around the polygon, it accepts various parameters, and more.

http://code.coronalabs.com/code/create-complex-non-convex-bodies

Brent

Hi Brent, 

thanks for the answer. I modify the bodySeparator to work with zoom. 

Example: local bodySeparator = require “bodySeparator”;

            bodySeparator.addNonConvexBody(pol, {zoom=zoom, shape = vertices, bodyType = “static”, bounce = 0, friction = 1, density = 1});

– bodySeparator.lua


–Convex Separator for Box2D Flash for Corona SDK

–The original class has been written by Antoan Angelov.

–This LUA port was done by Ragdog Studios SRL (http://www.ragdogstudios.com)

–It is designed to work with Erin Catto’s Box2D physics library implementation in Corona SDK (http://www.coronalabs.com)

–Everybody can use this software for any purpose, under two restrictions:

–1. You cannot claim that you wrote this software.

–2. You cannot remove or alter this notice.

–How to use it:

–local bodySeparator = require “bodySeparator”;

–local shape = {x1, y1, x2, y2, x3, y3…}; --your series of points

–local polygon = display.newPolygon(240, 160, shape); --can be any display object

–bodySeparator.addNonConvexBody(polygon, {shape = shape, bodyType = “static”, bounce = 0, friction = 1, density = 1});


local bodySeparator = {};

local reverseIfClockewise, reverseTable, calcShapes, validate, hitRay, hitSegment, isOnSegment, pointsMatch, isOnLine, det, err;

reverseIfClockwise = function(points)

  local lastIndex = 1;

  local totalPoints = #points;

  for i = 2, totalPoints do

    local currPoint = points[i];

    local lastPoint = points[lastIndex];

    if (currPoint.y < lastPoint.y) or ((currPoint.y == lastPoint.y) and (currPoint.x > lastPoint.x)) then

      lastIndex = i

    end

  end

  local index1 = ((lastIndex-2)%totalPoints)+1;

  local index2 = ((lastIndex-1)%totalPoints)+1;

  local index3 = ((lastIndex)%totalPoints)+1;

  local point1 = points[index1];

  local point2 = points[index2];

  local point3 = points[index3];

  if  (((point2.x-point1.x)*(point3.y-point1.y))-((point3.x-point1.x)*(point2.y-point1.y))) <= 0 then

    local dumTab = {};

    for i = 1, totalPoints do

      dumTab[totalPoints+1-i] = points[i];

    end

    return dumTab

  else

    return points;

  end

end

reverseTable = function(tab)

  local size = #tab;

  local newTable = {}

  for i = 1, size do

    newTable[i] = tab[size-i+1];

  end

  return newTable

end

calcShapes = function(vertices)

  local vec;

  local i, n, j;

  local d, t, dx, dy, minLen;

  local i1, i2, i3, p1, p2, p3;

  local j1, j2, v1, v2, k, h;

  local vec1, vec2;

  local v, hitV;

  local isConvex;

  local figsVec = {};

  local queue = {vertices};

  

  while #queue > 0 do

    vec = queue[1];

    n = #vec;

    isConvex = true;

    

    for i = 1, n, 1 do

      i1 = i;

      i2 = (i < n) and i+1 or i+1-n;

      i3 = (i < n-1) and i+2 or i+2-n;

      

      p1 = vec[i1];

      p2 = vec[i2];

      p3 = vec[i3];

      

      d = det(p1.x, p1.y, p2.x, p2.y, p3.x, p3.y);

      if (d < 0) then

        isConvex = false;

        minLen = 8.9884656743116e+307;

        for j = 1, n, 1 do

          if j ~= i1 and j ~= i2 then

            j1 = j;

            j2 = (j < n) and j+1 or 1;

            v1 = vec[j1];

            v2 = vec[j2];

            

            v = hitRay(p1.x, p1.y, p2.x, p2.y, v1.x, v1.y, v2.x, v2.y);

            

            if (v) then

              dx = p2.x-v.x;

              dy = p2.y-v.y;

              t = dx*dx+dy*dy;

              if t < minLen then

                h = j1;

                k = j2;

                hitV = v;

                minLen = t;

              end

            end

          end

        end

        

        if minLen == 8.9884656743116e+307 then 

          return nil;

          --err(1); 

        end;

        

        vec1 = {};

        vec2 = {};

        

        j1 = h;

        j2 = k;

        v1 = vec[j1];

        v2 = vec[j2];

        

        if (not pointsMatch(hitV.x, hitV.y, v2.x, v2.y)) then

          vec1[#vec1+1] = hitV;

        end

        if (not pointsMatch(hitV.x, hitV.y, v1.x, v1.y)) then

          vec2[#vec2+1] = hitV;

        end

        

        if (vec1==nil or vec2==nil or j1==nil or j2==nil) then return nil end;

        h = 0;

        k = i1;

        while true do

          if k ~= j2 then

            vec1[#vec1+1] = vec[k];

          else

            if h < 1 or h > n then return nil; --err(2); 

            end

            

            if (not isOnSegment(v2.x, v2.y, vec[h].x, vec[h].y, p1.x, p1.y)) then

              vec1[#vec1+1] = vec[k];

            end

            break;

          end

          

          h = k;

          if k-1 < 1 then

            k = n;

          else

            k = k-1;

          end

        end

        

        vec1 = reverseTable(vec1);

        

        h = 0;

        k = i2;

        while true do

          if k ~= j1 then

            vec2[#vec2+1] = vec[k];

          else

            if h < 1 or h > n then return nil --err(3) 

            end

            if k == j1 and not isOnSegment(v1.x, v1.y, vec[h].x, vec[h].y, p2.x, p2.y) then

              vec2[#vec2+1] = vec[k];

            end

            break;

          end

          

          h = k;

          if k+1 > n then

            k = 1;

          else

            k = k+1;

          end

        end

        

        queue[#queue+1] = vec1;

        queue[#queue+1] = vec2;

        table.remove(queue, 1);

        break;

      end

    end

    

    if isConvex then

      figsVec[#figsVec+1] = queue[1];

      table.remove(queue, 1);

    end

  end

  

  return figsVec;

end

hitRay = function(x1, y1, x2, y2, x3, y3, x4, y4)

  local t1 = x3-x1;

  local t2 = y3-y1;

  local t3 = x2-x1;

  local t4 = y2-y1;

  local t5 = x4-x3;

  local t6 = y4-y3;

  local t7 = t4*t5-t3*t6;

  

  local a = (((t5*t2)-t6*t1)/t7);

  local px = x1+a*t3;

  local py = y1+a*t4;

  local b1 = isOnSegment(x2, y2, x1, y1, px, py);

  local b2 = isOnSegment(px, py, x3, y3, x4, y4);

  

  if (b1 and b2) then

    return {x = px, y = py};

  end

  return nil;

end

hitSegment = function(x1, y1, x2, y2, x3, y3, x4, y4)

  local t1 = x3-x1;

  local t2 = y3-y1;

  local t3 = x2-x1;

  local t4 = y2-y1;

  local t5 = x4-x3;

  local t6 = y4-y3;

  local t7 = t4*t5-t3*t6;

  

  local a = (((t5*t2)-t6*t1)/t7);

  local px = x1+a*t3;

  local py = y1+a*t4;

  local b1 = isOnSegment(px, py, x1, y1, x2, y2);

  local b2 = isOnSegment(px, py, x3, y3, x4, y4);

  

  if (b1 and b2) then

    return {x = px, y = py};

  end

  return nil;

end

isOnSegment = function(px, py, x1, y1, x2, y2)

  local b1 = ((((x1+0.1) >= px) and px >= x2-0.1) or (((x1-0.1) <= px) and px <= x2+0.1));

  local b2 = ((((y1+0.1) >= py) and py >= y2-0.1) or (((y1-0.1) <= py) and py <= y2+0.1));

  return ((b1 and b2) and isOnLine(px, py, x1, y1, x2, y2));

end

pointsMatch = function(x1, y1, x2, y2) 

  local dx = (x2 >= x1) and x2-x1 or x1-x2;

  local dy = (y2 >= y1) and y2-y1 or y1-y2;

  return ((dx < 0.1) and dy < 0.1);

end

isOnLine = function(px, py, x1, y1, x2, y2)

  if ((((x2-x1) > 0.1) or x1-x2>0.1)) then

    local a = (y2-y1)/(x2-x1);

    local possibleY = a*(px-x1)+y1;

    local diff;

    if possibleY > py then

      diff = possibleY-py;

    else

      diff = py-possibleY;

    end

    return (diff<0.1);

  end

  return (((px-x1)<0.1) or x1-px<0.1);

end

det = function(x1, y1, x2, y2, x3, y3)

  return x1*y2+x2*y3+x3*y1-y1*x2-y2*x3-y3*x1;

end

err = function(where)

  print(where);

  --return nil;

  --assert(false, “An error has occured in the creation of the non-convex body shape”);

end

bodySeparator.addNonConvexBody = function(object, params)

  local physics = require “physics”;

  

  local verticesVec = {};

  

  local minimumX, minimumY = 8.9884656743116e+307, 8.9884656743116e+307;

  

  --zoom

  for g=1, #params.shape do 

    local vertice=params.shape[g];

    params.shape[g]=vertice*params.zoom;

  end; 

  local n = #params.shape;

  local count = 1;

  for i = 1, n, 2 do

    verticesVec[count] = {x = params.shape[i], y = params.shape[i+1]};

    if params.shape[i] < minimumX then

      minimumX = params.shape[i];

    end

    if params.shape[i+1] < minimumY then

      minimumY = params.shape[i+1];

    end

    count = count+1;

  end

  local figsVec;

  

  verticesVec = reverseIfClockwise(verticesVec);

  

  figsVec = calcShapes(verticesVec);

  if figsVec == nil then return nil; end;

  

  physics.start();

  physics.setDrawMode(“hybrid”);

  

  n = #figsVec;

  

  local finalShapes = {};

  for i = 1, n do

    local shape = {};

    for a = 1, #figsVec[i] do

      shape[#shape+1] = figsVec[i][a].x-object.width*.5*params.zoom-minimumX;

      shape[#shape+1] = figsVec[i][a].y-object.height*.5*params.zoom-minimumY;

    end

    finalShapes[#finalShapes+1] = {bounce = params.bounce, friction = params.friction, density = params.density, shape = shape};

  end

  physics.addBody(object, params.bodyType or “dynamic”, unpack(finalShapes));

end

return bodySeparator;

Hi @suporte37,

You cannot scale objects with physics bodies. The visual object will scale, but the physics body will remain as if the object was not scaled.

Take care,

Brent

Hi Brent, I’m not add the physics bodies before scale. Do you know how to add shape on a polyline acessing x,y points? Thanks, Leo.

Hi Leo,

The absolute best utility I’ve found for adding physics bodies to polygons is linked below. It automatically handles both convex and concave polygon shapes (by creating multiple body elements if necessary), it aligns the shape properly around the polygon, it accepts various parameters, and more.

http://code.coronalabs.com/code/create-complex-non-convex-bodies

Brent

Hi Brent, 

thanks for the answer. I modify the bodySeparator to work with zoom. 

Example: local bodySeparator = require “bodySeparator”;

            bodySeparator.addNonConvexBody(pol, {zoom=zoom, shape = vertices, bodyType = “static”, bounce = 0, friction = 1, density = 1});

– bodySeparator.lua


–Convex Separator for Box2D Flash for Corona SDK

–The original class has been written by Antoan Angelov.

–This LUA port was done by Ragdog Studios SRL (http://www.ragdogstudios.com)

–It is designed to work with Erin Catto’s Box2D physics library implementation in Corona SDK (http://www.coronalabs.com)

–Everybody can use this software for any purpose, under two restrictions:

–1. You cannot claim that you wrote this software.

–2. You cannot remove or alter this notice.

–How to use it:

–local bodySeparator = require “bodySeparator”;

–local shape = {x1, y1, x2, y2, x3, y3…}; --your series of points

–local polygon = display.newPolygon(240, 160, shape); --can be any display object

–bodySeparator.addNonConvexBody(polygon, {shape = shape, bodyType = “static”, bounce = 0, friction = 1, density = 1});


local bodySeparator = {};

local reverseIfClockewise, reverseTable, calcShapes, validate, hitRay, hitSegment, isOnSegment, pointsMatch, isOnLine, det, err;

reverseIfClockwise = function(points)

  local lastIndex = 1;

  local totalPoints = #points;

  for i = 2, totalPoints do

    local currPoint = points[i];

    local lastPoint = points[lastIndex];

    if (currPoint.y < lastPoint.y) or ((currPoint.y == lastPoint.y) and (currPoint.x > lastPoint.x)) then

      lastIndex = i

    end

  end

  local index1 = ((lastIndex-2)%totalPoints)+1;

  local index2 = ((lastIndex-1)%totalPoints)+1;

  local index3 = ((lastIndex)%totalPoints)+1;

  local point1 = points[index1];

  local point2 = points[index2];

  local point3 = points[index3];

  if  (((point2.x-point1.x)*(point3.y-point1.y))-((point3.x-point1.x)*(point2.y-point1.y))) <= 0 then

    local dumTab = {};

    for i = 1, totalPoints do

      dumTab[totalPoints+1-i] = points[i];

    end

    return dumTab

  else

    return points;

  end

end

reverseTable = function(tab)

  local size = #tab;

  local newTable = {}

  for i = 1, size do

    newTable[i] = tab[size-i+1];

  end

  return newTable

end

calcShapes = function(vertices)

  local vec;

  local i, n, j;

  local d, t, dx, dy, minLen;

  local i1, i2, i3, p1, p2, p3;

  local j1, j2, v1, v2, k, h;

  local vec1, vec2;

  local v, hitV;

  local isConvex;

  local figsVec = {};

  local queue = {vertices};

  

  while #queue > 0 do

    vec = queue[1];

    n = #vec;

    isConvex = true;

    

    for i = 1, n, 1 do

      i1 = i;

      i2 = (i < n) and i+1 or i+1-n;

      i3 = (i < n-1) and i+2 or i+2-n;

      

      p1 = vec[i1];

      p2 = vec[i2];

      p3 = vec[i3];

      

      d = det(p1.x, p1.y, p2.x, p2.y, p3.x, p3.y);

      if (d < 0) then

        isConvex = false;

        minLen = 8.9884656743116e+307;

        for j = 1, n, 1 do

          if j ~= i1 and j ~= i2 then

            j1 = j;

            j2 = (j < n) and j+1 or 1;

            v1 = vec[j1];

            v2 = vec[j2];

            

            v = hitRay(p1.x, p1.y, p2.x, p2.y, v1.x, v1.y, v2.x, v2.y);

            

            if (v) then

              dx = p2.x-v.x;

              dy = p2.y-v.y;

              t = dx*dx+dy*dy;

              if t < minLen then

                h = j1;

                k = j2;

                hitV = v;

                minLen = t;

              end

            end

          end

        end

        

        if minLen == 8.9884656743116e+307 then 

          return nil;

          --err(1); 

        end;

        

        vec1 = {};

        vec2 = {};

        

        j1 = h;

        j2 = k;

        v1 = vec[j1];

        v2 = vec[j2];

        

        if (not pointsMatch(hitV.x, hitV.y, v2.x, v2.y)) then

          vec1[#vec1+1] = hitV;

        end

        if (not pointsMatch(hitV.x, hitV.y, v1.x, v1.y)) then

          vec2[#vec2+1] = hitV;

        end

        

        if (vec1==nil or vec2==nil or j1==nil or j2==nil) then return nil end;

        h = 0;

        k = i1;

        while true do

          if k ~= j2 then

            vec1[#vec1+1] = vec[k];

          else

            if h < 1 or h > n then return nil; --err(2); 

            end

            

            if (not isOnSegment(v2.x, v2.y, vec[h].x, vec[h].y, p1.x, p1.y)) then

              vec1[#vec1+1] = vec[k];

            end

            break;

          end

          

          h = k;

          if k-1 < 1 then

            k = n;

          else

            k = k-1;

          end

        end

        

        vec1 = reverseTable(vec1);

        

        h = 0;

        k = i2;

        while true do

          if k ~= j1 then

            vec2[#vec2+1] = vec[k];

          else

            if h < 1 or h > n then return nil --err(3) 

            end

            if k == j1 and not isOnSegment(v1.x, v1.y, vec[h].x, vec[h].y, p2.x, p2.y) then

              vec2[#vec2+1] = vec[k];

            end

            break;

          end

          

          h = k;

          if k+1 > n then

            k = 1;

          else

            k = k+1;

          end

        end

        

        queue[#queue+1] = vec1;

        queue[#queue+1] = vec2;

        table.remove(queue, 1);

        break;

      end

    end

    

    if isConvex then

      figsVec[#figsVec+1] = queue[1];

      table.remove(queue, 1);

    end

  end

  

  return figsVec;

end

hitRay = function(x1, y1, x2, y2, x3, y3, x4, y4)

  local t1 = x3-x1;

  local t2 = y3-y1;

  local t3 = x2-x1;

  local t4 = y2-y1;

  local t5 = x4-x3;

  local t6 = y4-y3;

  local t7 = t4*t5-t3*t6;

  

  local a = (((t5*t2)-t6*t1)/t7);

  local px = x1+a*t3;

  local py = y1+a*t4;

  local b1 = isOnSegment(x2, y2, x1, y1, px, py);

  local b2 = isOnSegment(px, py, x3, y3, x4, y4);

  

  if (b1 and b2) then

    return {x = px, y = py};

  end

  return nil;

end

hitSegment = function(x1, y1, x2, y2, x3, y3, x4, y4)

  local t1 = x3-x1;

  local t2 = y3-y1;

  local t3 = x2-x1;

  local t4 = y2-y1;

  local t5 = x4-x3;

  local t6 = y4-y3;

  local t7 = t4*t5-t3*t6;

  

  local a = (((t5*t2)-t6*t1)/t7);

  local px = x1+a*t3;

  local py = y1+a*t4;

  local b1 = isOnSegment(px, py, x1, y1, x2, y2);

  local b2 = isOnSegment(px, py, x3, y3, x4, y4);

  

  if (b1 and b2) then

    return {x = px, y = py};

  end

  return nil;

end

isOnSegment = function(px, py, x1, y1, x2, y2)

  local b1 = ((((x1+0.1) >= px) and px >= x2-0.1) or (((x1-0.1) <= px) and px <= x2+0.1));

  local b2 = ((((y1+0.1) >= py) and py >= y2-0.1) or (((y1-0.1) <= py) and py <= y2+0.1));

  return ((b1 and b2) and isOnLine(px, py, x1, y1, x2, y2));

end

pointsMatch = function(x1, y1, x2, y2) 

  local dx = (x2 >= x1) and x2-x1 or x1-x2;

  local dy = (y2 >= y1) and y2-y1 or y1-y2;

  return ((dx < 0.1) and dy < 0.1);

end

isOnLine = function(px, py, x1, y1, x2, y2)

  if ((((x2-x1) > 0.1) or x1-x2>0.1)) then

    local a = (y2-y1)/(x2-x1);

    local possibleY = a*(px-x1)+y1;

    local diff;

    if possibleY > py then

      diff = possibleY-py;

    else

      diff = py-possibleY;

    end

    return (diff<0.1);

  end

  return (((px-x1)<0.1) or x1-px<0.1);

end

det = function(x1, y1, x2, y2, x3, y3)

  return x1*y2+x2*y3+x3*y1-y1*x2-y2*x3-y3*x1;

end

err = function(where)

  print(where);

  --return nil;

  --assert(false, “An error has occured in the creation of the non-convex body shape”);

end

bodySeparator.addNonConvexBody = function(object, params)

  local physics = require “physics”;

  

  local verticesVec = {};

  

  local minimumX, minimumY = 8.9884656743116e+307, 8.9884656743116e+307;

  

  --zoom

  for g=1, #params.shape do 

    local vertice=params.shape[g];

    params.shape[g]=vertice*params.zoom;

  end; 

  local n = #params.shape;

  local count = 1;

  for i = 1, n, 2 do

    verticesVec[count] = {x = params.shape[i], y = params.shape[i+1]};

    if params.shape[i] < minimumX then

      minimumX = params.shape[i];

    end

    if params.shape[i+1] < minimumY then

      minimumY = params.shape[i+1];

    end

    count = count+1;

  end

  local figsVec;

  

  verticesVec = reverseIfClockwise(verticesVec);

  

  figsVec = calcShapes(verticesVec);

  if figsVec == nil then return nil; end;

  

  physics.start();

  physics.setDrawMode(“hybrid”);

  

  n = #figsVec;

  

  local finalShapes = {};

  for i = 1, n do

    local shape = {};

    for a = 1, #figsVec[i] do

      shape[#shape+1] = figsVec[i][a].x-object.width*.5*params.zoom-minimumX;

      shape[#shape+1] = figsVec[i][a].y-object.height*.5*params.zoom-minimumY;

    end

    finalShapes[#finalShapes+1] = {bounce = params.bounce, friction = params.friction, density = params.density, shape = shape};

  end

  physics.addBody(object, params.bodyType or “dynamic”, unpack(finalShapes));

end

return bodySeparator;