-- 物理エンジンを使う 8, ボディー同士を一定の距離で拘束する, PinJoint -- 拘束条件を定義して、それを addConstraint(constraint) メソッドでスペースへ投入する。 require "physics" dt = 0.01 ZERO = physics.Vect(0, 0) pos1x, pos1y = 55, 5 -- ボール 1 の座標 pos2x, pos2y = 120, 55 -- ボール 2 の座標 mass = 1 -- ボールの重さ radius = 10 -- ボールの半径 angle1 = 0 -- ボール 1 の角度 angle2 = 0 -- ボール 2 の角度 leftx, lefty = 70, 100 -- 床の左端座標 rightx, righty = 250, 120 -- 床の右端座標 gravity = 150 elasticity = 0.8 friction = 0.9 inertia = physics.misc.momentForCircle(mass, 0, radius, ZERO) -- ボールを作る。 ballBody1 = physics.Body(mass, inertia) :setVel(ZERO) :setPos(physics.Vect(pos1x, pos1y)) :setAngle(angle1) ballShape1 = physics.CircleShape(ballBody1, radius, ZERO) :setRestitution(elasticity) :setFriction(friction) -- もうひとつ同じボールを作る。 ballBody2 = physics.Body(mass, inertia) :setVel(ZERO) :setPos(physics.Vect(pos2x, pos2y)) :setAngle(angle2) ballShape2 = physics.CircleShape(ballBody2, radius, ZERO) :setRestitution(elasticity) :setFriction(friction) -- static な壁を作る。 wallShape = physics.SegmentShape(nil, physics.Vect(leftx, lefty), physics.Vect(rightx, righty), 1) :setRestitution(elasticity) :setFriction(friction) -- PinJoint の拘束条件を定義する。 -- 引数は(ボディー a, ボディー b, ボディー a のどこ, ボディー b のどこ) -- ここでは両方のボールの重心同士を拘束する。 constraint = physics.PinJoint(ballBody1, ballBody2, ZERO, ZERO) space = physics.Space() :setGravity(physics.Vect(0, gravity)) :addBody(ballBody1) :addShape(ballShape1) :addBody(ballBody2) :addShape(ballShape2) :addShape(wallShape) -- 拘束条件をスペースへ投入する。 :addConstraint(constraint) function on.paint(gc) gc:drawLine(leftx, lefty, rightx, righty) fillCircleCenter(pos1x, pos1y, radius, angle1, 0x71C671, gc) fillCircleCenter(pos2x, pos2y, radius, angle2, 0x71C671, gc) gc:setColorRGB(0x8E8E38) gc:setPen("thin", "dashed") gc:drawLine(pos1x, pos1y, pos2x, pos2y) end function on.timer() space:step(dt) pos1 = ballBody1:pos() pos1x, pos1y = pos1:x(), pos1:y() pos2 = ballBody2:pos() pos2x, pos2y = pos2:x(), pos2:y() angle1 = ballBody1:angle() angle2 = ballBody2:angle() platform.window:invalidate() end function on.enterKey() timer.start(dt) end ----------------------- -- general functions -- ----------------------- function fillCircleCenter(cx, cy, radius, angle, color, gc) gc:setColorRGB(color) gc:fillArc(cx - radius, cy - radius, radius + radius, radius + radius, 0, 360) gc:setColorRGB(0x000000) gc:drawArc(cx - radius, cy - radius, radius + radius, radius + radius, 0, 360) gc:drawLine(cx, cy, cx + radius * math.cos(angle), cy + radius * math.sin(angle)) end