UElasticBody.pas
上传用户:zkjn0718
上传日期:2021-01-01
资源大小:776k
文件大小:22k
源码类别:

Delphi/CppBuilder

开发平台:

Delphi

  1. unit UElasticBody;
  2. interface
  3. {$I ......SourcePhysics2D.inc}
  4. uses
  5.    UMain,
  6.    UPhysics2DTypes,
  7.    UPhysics2D,
  8.    SysUtils;
  9. type
  10.    TElasticBody = class(TTester)
  11.    private
  12.       procedure Process;
  13.       procedure AddSpringForce(bA: Tb2Body; const localA: TVector2;
  14.          bB: Tb2Body; const localB: TVector2; const k, friction, desiredDist: Float);
  15.    public
  16.       bodies: array[0..63] of Tb2Body;
  17.       m_ground: Tb2Body;
  18.       m_elev: Tb2Body;
  19.       m_joint_elev: Tb2PrismaticJoint;
  20.       constructor Create; override;
  21.       procedure Step(var settings: TSettings; timeStep: Float); override;
  22.    end;
  23. implementation
  24. { TElasticBody }
  25. constructor TElasticBody.Create;
  26. const
  27.    startpoint: TVector2 = (X: 30.0; Y: 20.0);
  28. var
  29.    i, j: Integer;
  30.    sd: Tb2PolygonDef;
  31.    cd: Tb2CircleDef;
  32.    bd: Tb2BodyDef;
  33.    g, body, rightmotor, hammerleft, hammerright, pusher: Tb2Body;
  34.    jr: Tb2RevoluteJointDef;
  35.    jd: Tb2DistanceJointDef;
  36.    jp: Tb2PrismaticJointDef;
  37. begin
  38.    inherited;
  39.   /// Bottom static body
  40.    begin
  41.       sd := Tb2PolygonDef.Create;
  42.       sd.SetAsBox(50.0, 2.0);
  43.       sd.friction := 0.1;
  44.       sd.restitution := 0.1;
  45.       bd := Tb2BodyDef.Create;
  46.       {$IFDEF OP_OVERLOAD}
  47.       bd.position.SetValue(-1.0, -7.5);
  48.       {$ELSE}
  49.       SetValue(bd.position, -1.0, -7.5);
  50.       {$ENDIF}
  51.       m_ground := m_world.CreateBody(bd);
  52.       m_ground.CreateShape(sd);
  53.    end;
  54.    /// Upper static body
  55.    begin
  56.       sd := Tb2PolygonDef.Create;
  57.       sd.SetAsBox(20.0, 0.50, MakeVector(0.0, 0.0), 0.047 * Pi);
  58.       sd.friction := 0.01;
  59.       sd.restitution := 0.001;
  60.       bd := Tb2BodyDef.Create;
  61.       {$IFDEF OP_OVERLOAD}
  62.       bd.position.SetValue(-20.0, 93.0);
  63.       {$ELSE}
  64.       SetValue(bd.position, -20.0, 93.0);
  65.       {$ENDIF}
  66.       g := m_world.CreateBody(bd);
  67.       g.CreateShape(sd, False);
  68.       sd.SetAsBox(15.0, 0.50, MakeVector(-15.0, 12.5), 0.0);
  69.       g.CreateShape(sd, False);
  70.       sd.SetAsBox(20.0, 0.5, MakeVector(0.0, -25.0), -0.5);
  71.       g.CreateShape(sd);
  72.    end;
  73.    /// Left channel left wall
  74.    begin
  75.       sd := Tb2PolygonDef.Create;
  76.       sd.SetAsBox(0.7, 55.0);
  77.       sd.friction := 0.1;
  78.       sd.restitution := 0.1;
  79.       bd := Tb2BodyDef.Create;
  80.       {$IFDEF OP_OVERLOAD}
  81.       bd.position.SetValue(-49.3, 50.0);
  82.       {$ELSE}
  83.       SetValue(bd.position, -49.3, 50.0);
  84.       {$ENDIF}
  85.       g := m_world.CreateBody(bd);
  86.       g.CreateShape(sd);
  87.    end;
  88.    /// Right wall
  89.    begin
  90.       sd := Tb2PolygonDef.Create;
  91.       sd.SetAsBox(0.7, 55.0);
  92.       sd.friction := 0.1;
  93.       sd.restitution := 0.1;
  94.       bd := Tb2BodyDef.Create;
  95.       {$IFDEF OP_OVERLOAD}
  96.       bd.position.SetValue(45.0, 50.0);
  97.       {$ELSE}
  98.       SetValue(bd.position, 45.0, 50.0);
  99.       {$ENDIF}
  100.       g := m_world.CreateBody(bd);
  101.       g.CreateShape(sd);
  102.    end;
  103.    /// Left channel right upper wall
  104.    begin
  105.       sd := Tb2PolygonDef.Create;
  106.       sd.SetAsBox(0.5, 20.0);
  107.       sd.friction := 0.05;
  108.       sd.restitution := 0.01;
  109.       bd := Tb2BodyDef.Create;
  110.       {$IFDEF OP_OVERLOAD}
  111.       bd.position.SetValue(-42.0, 70.0);
  112.       {$ELSE}
  113.       SetValue(bd.position, -42.0, 70.0);
  114.       {$ENDIF}
  115.       bd.angle := -0.03 * Pi;
  116.       g := m_world.CreateBody(bd);
  117.       g.CreateShape(sd);
  118.    end;
  119.    /// Left channel right lower wall
  120.    begin
  121.       sd := Tb2PolygonDef.Create;
  122.       sd.SetAsBox(0.50, 23.0);
  123.       sd.friction := 0.05;
  124.       sd.restitution := 0.01;
  125.       bd := Tb2BodyDef.Create;
  126.       {$IFDEF OP_OVERLOAD}
  127.       bd.position.SetValue(-44.0, 27.0);
  128.       {$ELSE}
  129.       SetValue(bd.position, -44.0, 27.0);
  130.       {$ENDIF}
  131.       g := m_world.CreateBody(bd, False);
  132.       g.CreateShape(sd, False);
  133.       /// Bottom motors
  134.       cd := Tb2CircleDef.Create;
  135.       cd.radius := 3.0;
  136.       cd.density := 15.0;
  137.       cd.friction := 1.0;
  138.       cd.restitution := 0.2;
  139.       /// 1.
  140.       {$IFDEF OP_OVERLOAD}
  141.       bd.position.SetValue(-40.0, 2.5);
  142.       {$ELSE}
  143.       SetValue(bd.position, -40.0, 2.5);
  144.       {$ENDIF}
  145.       body := m_world.CreateBody(bd, False);
  146.       body.CreateShape(cd, False);
  147.       body.SetMassFromShapes;
  148.       jr := Tb2RevoluteJointDef.Create;
  149.       {$IFDEF OP_OVERLOAD}
  150.       jr.Initialize(g, body, body.GetWorldCenter + MakeVector(0.0, 1.0));
  151.       {$ELSE}
  152.       jr.Initialize(g, body, Add(body.GetWorldCenter, MakeVector(0.0, 1.0)));
  153.       {$ENDIF}
  154.       jr.maxMotorTorque := 30000.0;
  155.       jr.enableMotor := True;
  156.       jr.motorSpeed := 20.0;
  157.       m_world.CreateJoint(jr, False);
  158.       /// 1. left down
  159.       {$IFDEF OP_OVERLOAD}
  160.       bd.position.SetValue(-46.0, -2.5);
  161.       {$ELSE}
  162.       SetValue(bd.position, -46.0, -2.5);
  163.       {$ENDIF}
  164.       cd.radius := 1.5;
  165.       jr.motorSpeed := -20.0;
  166.       body := m_world.CreateBody(bd, False);
  167.       body.CreateShape(cd, False);
  168.       sd.SetAsBox(2.0, 0.50);
  169.       body.CreateShape(sd, False);
  170.       body.SetMassFromShapes;
  171.       jr.Initialize(g, body, body.GetWorldCenter);
  172.       m_world.CreateJoint(jr, False);
  173.       /// 2.
  174.       cd.radius := 3.0;
  175.       jr.motorSpeed := 20.0;
  176.       {$IFDEF OP_OVERLOAD}
  177.       bd.position.SetValue(-32.0, 2.5);
  178.       {$ELSE}
  179.       SetValue(bd.position, -32.0, 2.5);
  180.       {$ENDIF}
  181.       body := m_world.CreateBody(bd, False);
  182.       body.CreateShape(cd, False);
  183.       body.SetMassFromShapes;
  184.       {$IFDEF OP_OVERLOAD}
  185.       jr.Initialize(g, body, body.GetWorldCenter + MakeVector(0.0, 1.0));
  186.       {$ELSE}
  187.       jr.Initialize(g, body, Add(body.GetWorldCenter, MakeVector(0.0, 1.0)));
  188.       {$ENDIF}
  189.       m_world.CreateJoint(jr, False);
  190.       /// 3.
  191.       jr.motorSpeed := 20.0;
  192.       {$IFDEF OP_OVERLOAD}
  193.       bd.position.SetValue(-24.0, 1.5);
  194.       {$ELSE}
  195.       SetValue(bd.position, -24.0, 1.5);
  196.       {$ENDIF}
  197.       body := m_world.CreateBody(bd, False);
  198.       body.CreateShape(cd, False);
  199.       body.SetMassFromShapes;
  200.       {$IFDEF OP_OVERLOAD}
  201.       jr.Initialize(g, body, body.GetWorldCenter + MakeVector(0.0, 1.0));
  202.       {$ELSE}
  203.       jr.Initialize(g, body, Add(body.GetWorldCenter, MakeVector(0.0, 1.0)));
  204.       {$ENDIF}
  205.       m_world.CreateJoint(jr, False);
  206.       /// 4.
  207.       {$IFDEF OP_OVERLOAD}
  208.       bd.position.SetValue(-16.0, 0.8);
  209.       {$ELSE}
  210.       SetValue(bd.position, -16.0, 0.8);
  211.       {$ENDIF}
  212.       body := m_world.CreateBody(bd, False);
  213.       body.CreateShape(cd, False);
  214.       body.SetMassFromShapes;
  215.       {$IFDEF OP_OVERLOAD}
  216.       jr.Initialize(g, body, body.GetWorldCenter + MakeVector(0.0, 1.0));
  217.       {$ELSE}
  218.       jr.Initialize(g, body, Add(body.GetWorldCenter, MakeVector(0.0, 1.0)));
  219.       {$ENDIF}
  220.       m_world.CreateJoint(jr, False);
  221.       /// 5.
  222.       {$IFDEF OP_OVERLOAD}
  223.       bd.position.SetValue(-8.0, 0.5);
  224.       {$ELSE}
  225.       SetValue(bd.position, -8.0, 0.5);
  226.       {$ENDIF}
  227.       body := m_world.CreateBody(bd, False);
  228.       body.CreateShape(cd, False);
  229.       body.SetMassFromShapes;
  230.       {$IFDEF OP_OVERLOAD}
  231.       jr.Initialize(g, body, body.GetWorldCenter + MakeVector(0.0, 1.0));
  232.       {$ELSE}
  233.       jr.Initialize(g, body, Add(body.GetWorldCenter, MakeVector(0.0, 1.0)));
  234.       {$ENDIF}
  235.       m_world.CreateJoint(jr, False);
  236.       /// 6.
  237.       {$IFDEF OP_OVERLOAD}
  238.       bd.position.SetValue(0.0, 0.1);
  239.       {$ELSE}
  240.       SetValue(bd.position, 0.0, 0.1);
  241.       {$ENDIF}
  242.       body := m_world.CreateBody(bd, False);
  243.       body.CreateShape(cd, False);
  244.       body.SetMassFromShapes;
  245.       {$IFDEF OP_OVERLOAD}
  246.       jr.Initialize(g, body, body.GetWorldCenter + MakeVector(0.0, 1.0));
  247.       {$ELSE}
  248.       jr.Initialize(g, body, Add(body.GetWorldCenter, MakeVector(0.0, 1.0)));
  249.       {$ENDIF}
  250.       m_world.CreateJoint(jr, False);
  251.       /// 7.
  252.       {$IFDEF OP_OVERLOAD}
  253.       bd.position.SetValue(8.0, -0.5);
  254.       {$ELSE}
  255.       SetValue(bd.position, 8.0, -0.5);
  256.       {$ENDIF}
  257.       body := m_world.CreateBody(bd, False);
  258.       body.CreateShape(cd, False);
  259.       sd.SetAsBox(3.7, 0.5);
  260.       body.CreateShape(sd, False);
  261.       body.SetMassFromShapes;
  262.       {$IFDEF OP_OVERLOAD}
  263.       jr.Initialize(g, body, body.GetWorldCenter + MakeVector(0.0, 1.0));
  264.       {$ELSE}
  265.       jr.Initialize(g, body, Add(body.GetWorldCenter, MakeVector(0.0, 1.0)));
  266.       {$ENDIF}
  267.       m_world.CreateJoint(jr, False);
  268.       /// 8. right rotator
  269.       sd.SetAsBox(5.0, 0.5);
  270.       sd.density := 2.0;
  271.       {$IFDEF OP_OVERLOAD}
  272.       bd.position.SetValue(18.0, 1.0);
  273.       {$ELSE}
  274.       SetValue(bd.position, 18.0, 1.0);
  275.       {$ENDIF}
  276.       rightmotor := m_world.CreateBody(bd, False);
  277.       rightmotor.CreateShape(sd, False);
  278.       sd.SetAsBox(4.5, 0.5, b2Vec2_Zero, Pi / 3.0);
  279.       rightmotor.CreateShape(sd, False);
  280.       sd.SetAsBox(4.5, 0.5, b2Vec2_Zero, Pi * 2.0 / 3.0);
  281.       rightmotor.CreateShape(sd, False);
  282.       cd.radius := 4.2;
  283.       rightmotor.CreateShape(cd, False);
  284.       rightmotor.SetMassFromShapes;
  285.       jr.Initialize(g, rightmotor, rightmotor.GetWorldCenter);
  286.       jr.maxMotorTorque := 70000.0;
  287.       jr.motorSpeed := -4.0;
  288.       m_world.CreateJoint(jr, False);
  289.       /// 9. left rotator
  290.       sd.SetAsBox(8.5, 0.5);
  291.       sd.density := 2.0;
  292.       {$IFDEF OP_OVERLOAD}
  293.       bd.position.SetValue(-34.0, 17.0);
  294.       {$ELSE}
  295.       SetValue(bd.position, -34.0, 17.0);
  296.       {$ENDIF}
  297.       body := m_world.CreateBody(bd, False);
  298.       body.CreateShape(sd, False);
  299.       sd.SetAsBox(8.5, 0.5, MakeVector(0.0, 0.0), Pi / 2);
  300.       body.CreateShape(sd, False);
  301.       cd.radius := 7.0;
  302.       cd.friction := 0.9;
  303.       body.CreateShape(cd);
  304.       body.SetMassFromShapes;
  305.       jr.Initialize(g, body, body.GetWorldCenter);
  306.       jr.maxMotorTorque := 100000.0;
  307.       jr.motorSpeed := -5.0;
  308.       m_world.CreateJoint(jr);
  309.       /// big compressor
  310.       sd.SetAsBox(3.0, 4.0);
  311.       sd.density := 10.0;
  312.       {$IFDEF OP_OVERLOAD}
  313.       bd.position.SetValue(-16.0, 17.0);
  314.       {$ELSE}
  315.       SetValue(bd.position, -16.0, 17.0);
  316.       {$ENDIF}
  317.       hammerleft := m_world.CreateBody(bd, False);
  318.       hammerleft.CreateShape(sd, False);
  319.       hammerleft.SetMassFromShapes;
  320.       jd := Tb2DistanceJointDef.Create;
  321.       {$IFDEF OP_OVERLOAD}
  322.       jd.Initialize(body, hammerleft, body.GetWorldCenter + MakeVector(0.0, 6.0), hammerleft.GetWorldCenter);
  323.       {$ELSE}
  324.       jd.Initialize(body, hammerleft, Add(body.GetWorldCenter, MakeVector(0.0, 6.0)), hammerleft.GetWorldCenter);
  325.       {$ENDIF}
  326.       m_world.CreateJoint(jd, False);
  327.       {$IFDEF OP_OVERLOAD}
  328.       bd.position.SetValue(4.0, 17.0);
  329.       {$ELSE}
  330.       SetValue(bd.position, 4.0, 17.0);
  331.       {$ENDIF}
  332.       hammerright := m_world.CreateBody(bd, False);
  333.       hammerright.CreateShape(sd, False);
  334.       hammerright.SetMassFromShapes;
  335.       {$IFDEF OP_OVERLOAD}
  336.       jd.Initialize(body, hammerright, body.GetWorldCenter - MakeVector(0.0, 6.0), hammerright.GetWorldCenter);
  337.       {$ELSE}
  338.       jd.Initialize(body, hammerright, Subtract(body.GetWorldCenter, MakeVector(0.0, 6.0)), hammerright.GetWorldCenter);
  339.       {$ENDIF}
  340.       m_world.CreateJoint(jd, False);
  341.       /// pusher
  342.       sd.SetAsBox(6.0, 0.75);
  343.       {$IFDEF OP_OVERLOAD}
  344.       bd.position.SetValue(-21.0, 9.0);
  345.       {$ELSE}
  346.       SetValue(bd.position, -21.0, 9.0);
  347.       {$ENDIF}
  348.       pusher := m_world.CreateBody(bd);
  349.       pusher.CreateShape(sd, False);
  350.       sd.SetAsBox(2.0, 1.5, MakeVector(-5.0, 0.0), 0.0);
  351.       pusher.SetMassFromShapes;
  352.       pusher.CreateShape(sd);
  353.       {$IFDEF OP_OVERLOAD}
  354.       jd.Initialize(rightmotor, pusher, rightmotor.GetWorldCenter + MakeVector(-8.0, 0.0),
  355.          pusher.GetWorldCenter + MakeVector(5.0, 0.0));
  356.       {$ELSE}
  357.       jd.Initialize(rightmotor, pusher, Add(rightmotor.GetWorldCenter, MakeVector(-8.0, 0.0)),
  358.          Add(pusher.GetWorldCenter, MakeVector(5.0, 0.0)));
  359.       {$ENDIF}
  360.       m_world.CreateJoint(jd);
  361.    end;
  362.    /// Static bodies above motors
  363.    begin
  364.       sd := Tb2PolygonDef.Create;
  365.       cd := Tb2CircleDef.Create;
  366.       sd.SetAsBox(9.0, 0.5);
  367.       sd.friction := 0.05;
  368.       sd.restitution := 0.01;
  369.       bd := Tb2BodyDef.Create;
  370.       {$IFDEF OP_OVERLOAD}
  371.       bd.position.SetValue(-15.5, 12.0);
  372.       {$ELSE}
  373.       SetValue(bd.position, -15.5, 12.0);
  374.       {$ENDIF}
  375.       bd.angle := 0.0;
  376.       g := m_world.CreateBody(bd);
  377.       g.CreateShape(sd, False);
  378.       sd.SetAsBox(8.0, 0.5, MakeVector(23.0, 0.0), 0.0);
  379.       g.CreateShape(sd, False);
  380.       /// compressor statics
  381.       sd.SetAsBox(7.0, 0.5, MakeVector(-2.0, 9.0), 0.0);
  382.       g.CreateShape(sd, False);
  383.       sd.SetAsBox(9.0, 0.5, MakeVector(22.0, 9.0), 0.0);
  384.       g.CreateShape(sd, False);
  385.       sd.SetAsBox(19.0, 0.5, MakeVector(-9.0, 15.0), -0.05);
  386.       g.CreateShape(sd, False);
  387.       sd.SetAsBox(4.7, 0.5, MakeVector(15.0, 11.5), -0.5);
  388.       g.CreateShape(sd, False);
  389.       /// below compressor
  390.       sd.SetAsBox(26.0, 0.3, MakeVector(17.0, -4.4), -0.02);
  391.       g.CreateShape(sd);
  392.       cd.radius := 1.0;
  393.       cd.friction := 1.0;
  394.       cd.localPosition := MakeVector(29.0, -6.0);
  395.       g.CreateShape(cd, False);
  396.       cd.radius := 0.7;
  397.       cd.localPosition := MakeVector(-2.0, -4.5);
  398.       g.CreateShape(cd);
  399.    end;
  400.    /// Elevator
  401.    begin
  402.       bd := Tb2BodyDef.Create;
  403.       cd := Tb2CircleDef.Create;
  404.       sd := Tb2PolygonDef.Create;
  405.       {$IFDEF OP_OVERLOAD}
  406.       bd.position.SetValue(40.0, 4.0);
  407.       {$ELSE}
  408.       SetValue(bd.position, 40.0, 4.0);
  409.       {$ENDIF}
  410.       m_elev := m_world.CreateBody(bd, False);
  411.       sd.SetAsBox(0.5, 2.5, MakeVector(3.0, -3.0), 0.0);
  412.       sd.density := 1.0;
  413.       sd.friction := 0.01;
  414.       m_elev.CreateShape(sd, False);
  415.       sd.SetAsBox(7.0, 0.5, MakeVector(-3.5, -5.5), 0.0);
  416.       m_elev.CreateShape(sd, False);
  417.       sd.SetAsBox(0.5, 2.5, MakeVector(-11.0, -3.5), 0.0);
  418.       m_elev.CreateShape(sd, False);
  419.       m_elev.SetMassFromShapes;
  420.       jp := Tb2PrismaticJointDef.Create;
  421.       jp.Initialize(m_ground, m_elev, bd.position, MakeVector(0.0, 1.0));
  422.       jp.lowerTranslation := 0.0;
  423.       jp.upperTranslation := 100.0;
  424.       jp.enableLimit := True;
  425.       jp.enableMotor := True;
  426.       jp.maxMotorForce := 10000.0;
  427.       jp.motorSpeed := 0.0;
  428.       m_joint_elev := Tb2PrismaticJoint(m_world.CreateJoint(jp));
  429.       /// Korb
  430.       sd.SetAsBox(2.3, 0.5, MakeVector(1.0, 0.0), 0.0);
  431.       sd.density := 0.5;
  432.       {$IFDEF OP_OVERLOAD}
  433.       bd.position.SetValue(29.0, 6.5);
  434.       {$ELSE}
  435.       SetValue(bd.position, 29.0, 6.5);
  436.       {$ENDIF}
  437.       body := m_world.CreateBody(bd, False);
  438.       body.CreateShape(sd, False);
  439.       sd.SetAsBox(2.5, 0.5, MakeVector(3.0, -2.0), Pi / 2.0);
  440.       body.CreateShape(sd, False);
  441.       sd.SetAsBox(4.6, 0.5, MakeVector(7.8, -4.0), 0.0);
  442.       body.CreateShape(sd, False);
  443.       sd.SetAsBox(0.5, 4.5, MakeVector(12.0, 0.0), 0.0);
  444.       body.CreateShape(sd, False);
  445.       sd.SetAsBox(0.5, 0.5, MakeVector(13.0, 4.0), 0.0);
  446.       body.CreateShape(sd, False);
  447.       cd.radius := 0.7;
  448.       cd.density := 1.0;
  449.       cd.friction := 0.01;
  450.       cd.localPosition := MakeVector(0.0, 0.0);
  451.       body.CreateShape(cd);
  452.       body.SetMassFromShapes;
  453.       jr := Tb2RevoluteJointDef.Create;
  454.       jr.Initialize(m_elev, body, bd.position);
  455.       jr.enableLimit := True;
  456.       jr.lowerAngle := -0.2;
  457.       jr.upperAngle := Pi * 1.1;
  458.       jr.collideConnected := True;
  459.       m_world.CreateJoint(jr);
  460.       /// upper body exit
  461.       sd.SetAsBox(14.0, 0.5, MakeVector(-3.5, -10.0), 0.0);
  462.       {$IFDEF OP_OVERLOAD}
  463.       bd.position.SetValue(17.5, 96.0);
  464.       {$ELSE}
  465.       SetValue(bd.position, 17.5, 96.0);
  466.       {$ENDIF}
  467.       body := m_world.CreateBody(bd);
  468.       body.CreateShape(sd);
  469.    end;
  470.    /// "Elastic body" 64 bodies - something like a lin. elastic compound
  471.    /// connected via dynamic forces (springs)
  472.    begin
  473.       sd := Tb2PolygonDef.Create;
  474.       bd := Tb2BodyDef.Create;
  475.       sd.SetAsBox(0.55, 0.55);
  476.       sd.density := 1.5;
  477.       sd.friction := 0.01;
  478.       sd.filter.groupIndex := -1;
  479.       bd.isBullet := False;
  480.       bd.allowSleep := false;
  481.       for i := 0 to 7 do
  482.          for j := 0 to 7 do
  483.          begin
  484.             {$IFDEF OP_OVERLOAD}
  485.             bd.position.SetValue(j * 1.02, 2.51 + 1.02 * i);
  486.             bd.position.AddBy(startpoint);
  487.             {$ELSE}
  488.             SetValue(bd.position, j * 1.02, 2.51 + 1.02 * i);
  489.             AddBy(bd.position, startpoint);
  490.             {$ENDIF}
  491.             body := m_world.CreateBody(bd, False);
  492.             bodies[8 * i + j] := body;
  493.             body.CreateShape(sd, False);
  494.             body.SetMassFromShapes;
  495.          end;
  496.       bd.Free;
  497.       sd.Free;
  498.    end;
  499. end;
  500. procedure TElasticBody.Step(var settings: TSettings; timeStep: Float);
  501. begin
  502.    settings.customedStep := True; // Use customed step method
  503.    m_pointCount := 0;
  504.    if not settings.realTime then
  505.       timeStep := DefaultStep;
  506.    if settings.pause then
  507.    begin
  508.       m_RemainTime := 0.0;
  509.       if settings.singleStep then
  510.       begin
  511.          settings.singleStep := False;
  512.          Inc(m_frameCount);
  513.       end
  514.       else
  515.          timeStep := 0.0;
  516.       DrawText('****PAUSED****');
  517.    end
  518.    else
  519.       Inc(m_frameCount);
  520.    if settings.realTime then // Make sure that every frame is processed using a time step pf 1/60s.
  521.    begin
  522.       timeStep := timeStep + m_RemainTime;
  523.       while timeStep > DefaultStep do
  524.       begin
  525.          Process;
  526.          timeStep := timeStep - DefaultStep;
  527.       end;
  528.       m_RemainTime := timeStep;
  529.    end
  530.    else
  531.       Process;
  532.    m_world.DrawDebugData;
  533.    m_world.Validate;
  534.    if Assigned(m_bomb) and m_bomb.IsFrozen then
  535.    begin
  536.       m_world.DestroyBody(m_bomb);
  537.       m_bomb := nil;
  538.    end;
  539.    inherited; // Draw other objects, but do not Step
  540. end;
  541. procedure TElasticBody.Process;
  542. const
  543.    spring = 500.0;
  544.    damp = 5.0;
  545.    down: TVector2 = (X: 0.0; Y: - 0.5);
  546.    up: TVector2 = (X: 0.0; Y: 0.5);
  547.    right: TVector2 = (X: 0.5; Y: 0.0);
  548.    left: TVector2 = (X: -0.5; Y: 0.0);
  549.    drdist = 1.4142135;
  550.    drdist2 = 2 * drdist;
  551. var
  552.    i, j: Integer;
  553.    ind, indr, indd, inddr, inddl: Int32;
  554.    p1, p2, e: TVector2;
  555. begin
  556.    m_world.Step(DefaultStep, 10, False);
  557.    for i := 0 to 7 do
  558.       for j := 0 to 7 do
  559.       begin
  560.          ind := i * 8 + j;
  561.          indr := ind + 1;
  562.          indd := ind + 8;
  563.          if j < 7 then
  564.          begin
  565.             AddSpringForce(bodies[ind], b2Vec2_Zero, bodies[indr], b2Vec2_Zero, spring, damp, 1.0);
  566.             AddSpringForce(bodies[ind], right, bodies[indr], left, 0.5 * spring, damp, 0.0);
  567.          end;
  568.          if i < 7 then
  569.          begin
  570.             AddSpringForce(bodies[ind], b2Vec2_Zero, bodies[indd], b2Vec2_Zero, spring, damp, 1.0);
  571.             AddSpringForce(bodies[ind], up, bodies[indd], down, 0.5 * spring, damp, 0.0);
  572.          end;
  573.          inddr := indd + 1;
  574.          inddl := indd - 1;
  575.          if (i < 7) and (j < 7) then
  576.             AddSpringForce(bodies[ind], b2Vec2_Zero, bodies[inddr], b2Vec2_Zero, spring, damp, drdist);
  577.          if (i < 7) and (j > 0) then
  578.             AddSpringForce(bodies[ind], b2Vec2_Zero, bodies[inddl], b2Vec2_Zero, spring, damp, drdist);
  579.          indr := ind + 2;
  580.          indd := ind + 8 * 2;
  581.          if j < 6 then
  582.             AddSpringForce(bodies[ind], b2Vec2_Zero, bodies[indr], b2Vec2_Zero, spring, damp, 2.0);
  583.          if i < 6 then
  584.             AddSpringForce(bodies[ind], b2Vec2_Zero, bodies[indd], b2Vec2_Zero, spring, damp, 2.0);
  585.          inddr := indd + 2;
  586.          inddl := indd - 2;
  587.          if (i < 6) and (j < 6) then
  588.             AddSpringForce(bodies[ind], b2Vec2_Zero, bodies[inddr], b2Vec2_Zero, spring, damp, drdist2);
  589.          if (i < 6) and (j > 1) then
  590.             AddSpringForce(bodies[ind], b2Vec2_Zero, bodies[inddl], b2Vec2_Zero, spring, damp, drdist2);
  591.       end;
  592.    /// Check if bodies are near elevator
  593.    /// Look if the body to lift is near the elevator
  594.    p1 := bodies[0].GetWorldCenter;
  595.    p2 := bodies[63].GetWorldCenter;
  596.    /// m_elev:   elevator prism. joint
  597.    {$IFDEF OP_OVERLOAD}
  598.    e := m_elev.GetWorldCenter + MakeVector(0.0, 7.0);
  599.    {$ELSE}
  600.    e := Add(m_elev.GetWorldCenter, MakeVector(0.0, 7.0));
  601.    {$ENDIF}
  602.    // maybe not the best way to do it...
  603.    // Bodies reached the elevator side
  604.    if (p1.x > e.x) or (p2.x > e.x) then // go up
  605.       if ((p1.y < e.y) or (p2.y < e.y)) and (m_joint_elev.GetJointTranslation <= m_joint_elev.GetLowerLimit + 1.0) then
  606.          m_joint_elev.m_motorSpeed := 20.0;
  607.    // go down
  608.    if (m_joint_elev.GetJointTranslation >= m_joint_elev.GetUpperLimit - 2.0) then
  609.       m_joint_elev.m_motorSpeed := -15.0;
  610. end;
  611. procedure TElasticBody.AddSpringForce(bA: Tb2Body; const localA: TVector2;
  612.    bB: Tb2Body; const localB: TVector2; const k, friction, desiredDist: Float);
  613. var
  614.    diff, vA, vB, vdiff: TVector2;
  615.    dx, vrel, forceMag: Float;
  616. begin
  617.    {$IFDEF OP_OVERLOAD}
  618.    diff := bB.GetWorldPoint(localB) - bA.GetWorldPoint(localA);
  619.    //Find velocities of attach points
  620.    vA := bA.GetLinearVelocity - b2Cross(bA.GetWorldVector(localA), bA.GetAngularVelocity);
  621.    vB := bB.GetLinearVelocity - b2Cross(bB.GetWorldVector(localB), bB.GetAngularVelocity);
  622.    vdiff := vB - vA;
  623.    dx := diff.Normalize; //normalizes diff and puts length into dx
  624.    {$ELSE}
  625.    diff := Subtract(bB.GetWorldPoint(localB), bA.GetWorldPoint(localA));
  626.    //Find velocities of attach points
  627.    vA := Subtract(bA.GetLinearVelocity, b2Cross(bA.GetWorldVector(localA), bA.GetAngularVelocity));
  628.    vB := Subtract(bB.GetLinearVelocity, b2Cross(bB.GetWorldVector(localB), bB.GetAngularVelocity));
  629.    vdiff := Subtract(vB, vA);
  630.    dx := Normalize(diff); //normalizes diff and puts length into dx
  631.    {$ENDIF}
  632.    vrel := vdiff.x * diff.x + vdiff.y * diff.y;
  633.    forceMag := -k * (dx - desiredDist) - friction * vrel;
  634.    {$IFDEF OP_OVERLOAD}
  635.    diff := diff * forceMag;
  636.    {$ELSE}
  637.    diff := Multiply(diff, forceMag);
  638.    {$ENDIF}
  639.    bB.ApplyForce(diff, bA.GetWorldPoint(localA));
  640.    {$IFDEF OP_OVERLOAD}
  641.    diff := -diff;
  642.    {$ELSE}
  643.    diff := Negative(diff);
  644.    {$ENDIF}
  645.    bA.ApplyForce(diff, bB.GetWorldPoint(localB));
  646. end;
  647. initialization
  648.    RegisterTestEntry('Elastic Body', TElasticBody);
  649. end.