diff --git a/docs/kit-reference.md b/docs/kit-reference.md index 1d23d3a..ec1ef60 100644 --- a/docs/kit-reference.md +++ b/docs/kit-reference.md @@ -123,6 +123,8 @@ dynamic/static where a handler takes an optional `dyn` flag. | `b2kSetGravityScale ctrl, s` | Per-body gravity multiplier. | | `b2kSetDamping ctrl, lin [,ang]` | Linear (and optional angular) damping. | | `b2kWake ctrl` | Wake a sleeping body. | +| `b2kSleep ctrl` | Send a body to sleep until something wakes it. | +| `b2kSetSleepThreshold ctrl, pxPerSec` | Speed below which a body may fall asleep. | | `b2kSetStatic ctrl` / `b2kSetDynamic ctrl` / `b2kSetKinematic ctrl` | Change body type at runtime (freeze/unfreeze, moving platforms). | | `b2kSetType ctrl, "static"\|"kinematic"\|"dynamic"` | Set body type by name. | | `b2kDisable ctrl` / `b2kEnable ctrl` | Take a body out of / put it back into the simulation. | @@ -133,6 +135,8 @@ dynamic/static where a handler takes an optional `dyn` flag. |---------|---------| | `b2kPush ctrl, dvx, dvy` | Add a one-shot impulse (change in velocity, px/s). | | `b2kForce ctrl, fx, fy` | Apply a continuous force (call each frame for thrust/wind). | +| `b2kImpulse ctrl, ix, iy` | One-shot impulse, mass-aware (heavier bodies move less). | +| `b2kTorque ctrl, torque` | Continuous turning force (call each frame); +/- sets direction. | | `b2kSetVelocity ctrl, vx, vy` | Set linear velocity (px/s). | | `b2kSpin ctrl, degPerSec` | Set angular velocity. | | `b2kSpinBy ctrl, degPerSec` | Add to the current angular velocity. | @@ -153,6 +157,9 @@ dynamic/static where a handler takes an optional `dyn` flag. | `b2kBodyCount()` | How many bodies the Kit is tracking. | | `b2kAwakeCount()` | How many dynamic bodies are currently awake (active). | | `b2kIsAwake(ctrl)` | Whether the body is awake. | +| `b2kSpinRate(ctrl)` | Rotation speed in degrees/sec (getter for `b2kSpin`). | +| `b2kIsBullet(ctrl)` | Whether continuous (CCD) collision is on. | +| `b2kIsEnabled(ctrl)` | Whether the body is in the simulation. | | `b2kControlAt(x, y)` | The control whose body covers a screen point. | | `b2kRayHit(x1, y1, x2, y2)` | True if a ray hits; then read the result functions below. | | `b2kRayHitX()` / `b2kRayHitY()` | Hit point in screen pixels. | @@ -187,6 +194,7 @@ helpers or to `b2kRemoveJoint`. | `b2kWheelSpring joint, hertz [,damping]` | Tune wheel suspension. | | `b2kRopeRange joint, minPx, maxPx` | Set a distance joint's min/max length. | | `b2kRopeLength(joint)` → pixels | Current distance-joint length. | +| `b2kRopeSetLength joint, px` | Set a distance joint's exact rest length. | | `b2kSpring joint, hertz [,damping]` | Make a rope (distance) joint springy. | | `b2kWeldSpring joint, hertz [,damping]` | Make a weld springy (0 hertz = rigid). | | `b2kMotorOff joint` | Turn a hinge motor off (free swing). | diff --git a/examples/box2dxt-contraption-builder.livecodescript b/examples/box2dxt-contraption-builder.livecodescript index d58fb0f..ffd045c 100644 --- a/examples/box2dxt-contraption-builder.livecodescript +++ b/examples/box2dxt-contraption-builder.livecodescript @@ -513,15 +513,15 @@ end b2kSpawnCapsule -- Materials & body properties -- ===================================================================== command b2kSetBounce pControl, pRestitution - b2SetShapeRestitution sShapeH[the long id of pControl], pRestitution + if sShapeH[the long id of pControl] is not empty then b2SetShapeRestitution sShapeH[the long id of pControl], pRestitution end b2kSetBounce command b2kSetFriction pControl, pFriction - b2SetShapeFriction sShapeH[the long id of pControl], pFriction + if sShapeH[the long id of pControl] is not empty then b2SetShapeFriction sShapeH[the long id of pControl], pFriction end b2kSetFriction command b2kSetDensity pControl, pDensity - b2SetShapeDensity sShapeH[the long id of pControl], pDensity + if sShapeH[the long id of pControl] is not empty then b2SetShapeDensity sShapeH[the long id of pControl], pDensity end b2kSetDensity -- Re-fit a body's collision shape to the control's CURRENT size, in place on the @@ -607,6 +607,17 @@ command b2kWake pControl b2SetAwake sBody[the long id of pControl], true end b2kWake +-- Send a body to sleep (it stops simulating until something wakes it). +command b2kSleep pControl + b2SetAwake sBody[the long id of pControl], false +end b2kSleep + +-- Below this speed (pixels/sec) a body may fall asleep. Lower = stays awake +-- longer; higher = sleeps sooner (saves CPU). +command b2kSetSleepThreshold pControl, pPxPerSec + b2SetSleepThreshold sBody[the long id of pControl], pPxPerSec / sScale +end b2kSetSleepThreshold + -- ===================================================================== -- Acting on bodies (velocities/kicks are in PIXELS/sec, screen-oriented) -- ===================================================================== @@ -639,6 +650,18 @@ command b2kForce pControl, pFxPx, pFyPx b2ApplyForce sBody[the long id of pControl], pFxPx / sScale, - pFyPx / sScale, true end b2kForce +-- A one-shot impulse (a sharp kick), screen-oriented. Mass-aware: heavier bodies +-- move less. b2kPush changes velocity directly; this is the impulse equivalent. +command b2kImpulse pControl, pIxPx, pIyPx + b2ApplyImpulse sBody[the long id of pControl], pIxPx / sScale, - pIyPx / sScale, true +end b2kImpulse + +-- A continuous turning force (same units as motor torque). Positive turns one way, +-- negative the other. Apply each frame for a sustained twist; pairs with b2kForce. +command b2kTorque pControl, pTorque + b2ApplyTorque sBody[the long id of pControl], pTorque, true +end b2kTorque + -- Change a body's type at runtime: "static", "kinematic", or "dynamic". command b2kSetType pControl, pType local tRef, tCode @@ -759,6 +782,19 @@ function b2kIsAwake pControl return b2BodyIsAwake(sBody[the long id of pControl]) end b2kIsAwake +-- Current rotation speed in DEGREES/sec (the getter for b2kSpin / b2kSpinBy). +function b2kSpinRate pControl + return b2BodyAngularVelocity(sBody[the long id of pControl]) * 180 / kPI +end b2kSpinRate + +function b2kIsBullet pControl + return b2BodyIsBullet(sBody[the long id of pControl]) +end b2kIsBullet + +function b2kIsEnabled pControl + return b2BodyIsEnabled(sBody[the long id of pControl]) +end b2kIsEnabled + function b2kMass pControl return b2BodyMass(sBody[the long id of pControl]) end b2kMass @@ -905,6 +941,11 @@ function b2kRopeLength pJoint return b2DistanceLength(pJoint) * sScale end b2kRopeLength +-- Set a rope (distance) joint's exact rest length, in pixels. +command b2kRopeSetLength pJoint, pLengthPx + b2DistanceSetLength pJoint, pLengthPx / sScale +end b2kRopeSetLength + command b2kRopeRange pJoint, pMinPx, pMaxPx b2DistanceSetLengthRange pJoint, pMinPx / sScale, pMaxPx / sScale end b2kRopeRange @@ -1288,8 +1329,8 @@ constant kShapeTools = "drag,box,ball,capsule,poly,image,anchor,delete,duplica constant kShapeLabels = "Drag,Box,Ball,Capsule,Poly,Image,Anchor,Delete,Duplicate" constant kSpecialTools = "balloon,bomb,plate,fan,magnet" constant kSpecialLabels = "Balloon,Bomb,Pressure Plate,Fan,Magnet" -constant kJointTools = "hinge,weld,rope,slider,wheel" -constant kJointLabels = "Hinge,Weld,Rope,Slider,Wheel" +constant kJointTools = "hinge,weld,rope,slider,wheel,bridge,chain" +constant kJointLabels = "Hinge,Weld,Rope,Slider,Wheel,Bridge,Chain" constant kHingeTorque = 1500, kWheelTorque = 320 -- Layout, in screen pixels. Derived edges (canvas L/R/T/B) are computed from the @@ -1298,7 +1339,7 @@ constant kStackW = 1180, kStackH = 760 constant kTopBarH = 54, kAccentH = 3 constant kPaletteW = 196, kInspectorW = 248, kStatusH = 26 constant kCanvasInset = 2, kGroundBarH = 22 -constant kPalPadX = 12, kPalBtnH = 26, kPalBtnGap = 4 +constant kPalPadX = 12, kPalBtnH = 24, kPalBtnGap = 3 constant kPalSectionGap = 8, kPalHeaderH = 18 -- Materials, motors, feedback timing, and default part sizes (were magic numbers). @@ -2144,6 +2185,8 @@ on tagPart pCtrl, pKind, pColor, pFile set the uKind of pCtrl to pKind set the uColor of pCtrl to pColor set the uFile of pCtrl to pFile + set the uW of pCtrl to the width of pCtrl -- design size (the graphic rect inflates when rotated) + set the uH of pCtrl to the height of pCtrl add 1 to gNextPid put pCtrl & cr after gParts put true into gDynDirty -- the dynamic-part cache must be rebuilt @@ -2298,8 +2341,8 @@ on jointClick pX, pY end if -- second click: the part under the cursor, ignoring A (so overlaps work) put otherPartAt(pX, pY, gPendCtrl) into tHit - if tHit is empty and gJointTool is not "hinge" then - put "Part B must be a part for a " & gJointTool & " joint (only Hinge pins to the world)." into gStatus + if tHit is empty and gJointTool is not "hinge" and gJointTool is not "bridge" and gJointTool is not "chain" then + put "Part B must be a part for a " & gJointTool & " joint (Hinge, Bridge and Chain can pin to the world)." into gStatus resetPend updateHud exit jointClick @@ -2309,7 +2352,7 @@ on jointClick pX, pY end jointClick function jointBHint - if gJointTool is "hinge" then return " (or empty space to pin to the world)." + if gJointTool is "hinge" or gJointTool is "bridge" or gJointTool is "chain" then return " (or empty space to anchor to the world)." return "." end jointBHint @@ -2338,6 +2381,12 @@ end unflashSelect -- Interactive joint: build it, then add the motor if the Motor toggle is on. on makeJoint pKind, pA, pB, pX, pY + if pKind is "bridge" or pKind is "chain" then + buildSpan pKind, pA, pB, pX, pY + renderBuild + updateHud + exit makeJoint + end if local tMotor put 0 into tMotor if gMotorOn and (pKind is "hinge" or pKind is "wheel") then put gMotorSpeed into tMotor @@ -2354,6 +2403,58 @@ on makeJoint pKind, pA, pB, pX, pY updateHud end makeJoint +-- Build a span of hinged segments from the first click point to the second, in +-- the demo's bridge style: a "bridge" is stiff planks, a "chain" is a draping +-- rope of small links. Each segment is a normal part and each link an exact-pivot +-- "pin" joint, so the whole span renders, saves/loads and deletes like anything else. +on buildSpan pKind, pA, pB, pEx, pEy + local tSx, tSy, tD, tN, tHt, tColor, tDens, tSag + local tI, tT, tJx0, tJy0, tJx1, tJy1, tCx, tCy, tLen, tAng, tSeg, tPrev + put gPendX into tSx + put gPendY into tSy + put sqrt((pEx - tSx) ^ 2 + (pEy - tSy) ^ 2) into tD + if tD < 50 then + put "That span is too short — click two points further apart." into gStatus + exit buildSpan + end if + if pKind is "bridge" then + put max(2, min(20, round(tD / 60))) into tN + put 12 into tHt + put "168,146,98" into tColor + put 1 into tDens + put 0 into tSag -- straight; sags under load + else + put max(4, min(28, round(tD / 24))) into tN + put 8 into tHt + put "150,154,170" into tColor + put 0.4 into tDens + put tD * 0.16 into tSag -- a gentle initial drape + end if + put tSx into tJx0 + put tSy into tJy0 + put empty into tPrev + repeat with tI = 1 to tN + put tI / tN into tT + put tSx + tT * (pEx - tSx) into tJx1 + put tSy + tT * (pEy - tSy) + tSag * sin(kPI * tT) into tJy1 + put (tJx0 + tJx1) / 2 into tCx + put (tJy0 + tJy1) / 2 into tCy + put sqrt((tJx1 - tJx0) ^ 2 + (tJy1 - tJy0) ^ 2) into tLen + put atan2(tJy1 - tJy0, tJx1 - tJx0) * 180 / kPI into tAng + put placeBox(round(tCx), round(tCy), max(8, round(tLen)), tHt, tColor) into tSeg + set the uDensity of tSeg to tDens + b2kSetDensity tSeg, tDens + b2kMoveTo tSeg, round(tCx), round(tCy), tAng + if tI is 1 then get connectJoint("pin", pA, tSeg, round(tJx0), round(tJy0), 0) + else get connectJoint("pin", tPrev, tSeg, round(tJx0), round(tJy0), 0) + put tSeg into tPrev + put tJx1 into tJx0 + put tJy1 into tJy0 + end repeat + get connectJoint("pin", tPrev, pB, round(pEx), round(pEy), 0) + put (niceName(pKind) & " built from " & tN & " segments. Press Run to test it.") into gStatus +end buildSpan + -- The shared joint builder. Picks a sensible pivot per kind, records the joint -- and its marker, and motorises it when pMotorSpeed > 0. Returns true on success. function connectJoint pKind, pA, pB, pX, pY, pMotorSpeed @@ -2416,6 +2517,11 @@ function connectJoint pKind, pA, pB, pX, pY, pMotorSpeed if tJ > 0 then b2kWheelSpring tJ, 5, 0.7 put "dot" into tVis break + case "pin" + b2kHinge pA, pB, pX, pY -- exact-pivot hinge for spans (no marker) + put the result into tJ + put "none" into tVis + break default return false end switch @@ -2459,7 +2565,9 @@ on recordJoint pKind, pJoint, pA, pB, pX, pY, pVis put empty into gJEnd[gJN] put "cb_joint_" & gJN into tG create graphic tG - if pVis is "dot" then + if pVis is "none" then + set the visible of graphic tG to false -- internal structural pin: no marker + else if pVis is "dot" then set the style of graphic tG to "oval" set the filled of graphic tG to true set the backgroundColor of graphic tG to "250,210,90" @@ -2499,7 +2607,7 @@ on renderJoints if gJN < 1 then exit renderJoints repeat with tI = 1 to gJN put gJVis[tI] into tVis - if tVis is empty then next repeat + if tVis is empty or tVis is "none" then next repeat put "cb_joint_" & tI into tG if there is not a graphic tG then next repeat try @@ -2787,7 +2895,7 @@ function partLine pCtrl put the loc of pCtrl into tLoc return "part" & tab & (the uPartId of pCtrl) & tab & (the uKind of pCtrl) & tab & \ (item 1 of tLoc) & tab & (item 2 of tLoc) & tab & \ - (the width of pCtrl) & tab & (the height of pCtrl) & tab & \ + numOr(the uW of pCtrl, the width of pCtrl) & tab & numOr(the uH of pCtrl, the height of pCtrl) & tab & \ (the uBounce of pCtrl) & tab & (the uColor of pCtrl) & tab & (the uFile of pCtrl) & tab & \ partSpecial(pCtrl) end partLine @@ -2941,7 +3049,7 @@ on rebuildFromText pData put tMap[tIdA] into tA if tIdB is 0 then put empty into tB else put tMap[tIdB] into tB - if tA is not empty and (tB is not empty or tKind is "hinge") then + if tA is not empty and (tB is not empty or tKind is "hinge" or tKind is "pin") then if connectJoint(tKind, tA, tB, tPx, tPy, tMotor) then applyJointSpecial gJN, tJSpecial end if else if tRec is "world" then @@ -3648,15 +3756,15 @@ function propLabel pCtrl, pKey case "size" return "Size: " & (the width of pCtrl) & " px" case "width" - return "Width: " & (the width of pCtrl) & " px" + return "Width: " & numOr(the uW of pCtrl, the width of pCtrl) & " px" case "height" - return "Height: " & (the height of pCtrl) & " px" + return "Height: " & numOr(the uH of pCtrl, the height of pCtrl) & " px" case "length" - return "Length: " & (the width of pCtrl) & " px" + return "Length: " & numOr(the uW of pCtrl, the width of pCtrl) & " px" case "thickness" - return "Thickness: " & (the height of pCtrl) & " px" + return "Thickness: " & numOr(the uH of pCtrl, the height of pCtrl) & " px" case "diameter" - return "Diameter: " & (the width of pCtrl) & " px" + return "Diameter: " & numOr(the uW of pCtrl, the width of pCtrl) & " px" case "angle" return "Angle: " & round(b2kAngle(pCtrl)) & " deg" case "color" @@ -3947,6 +4055,8 @@ on resizePart pCtrl, pFactor set the height of pCtrl to tH set the loc of pCtrl to tCx & "," & tCy end if + set the uW of pCtrl to the width of pCtrl + set the uH of pCtrl to the height of pCtrl if kindHasBody(tKind) then b2kReshape pCtrl, shapeOfKind(tKind) reapplyMaterial pCtrl @@ -4113,12 +4223,20 @@ end clampDim -- Set ONE axis of a part to an exact pixel size, then re-fit its physics shape on -- the same body so joints survive. pAxis is "w", "h", or "d" (both, for balls). on setPartDimension pCtrl, pAxis, pValue - local tKind, tCx, tCy, tW, tH + local tKind, tCx, tCy, tW, tH, tAng put the uKind of pCtrl into tKind put item 1 of the loc of pCtrl into tCx put item 2 of the loc of pCtrl into tCy - put the width of pCtrl into tW - put the height of pCtrl into tH + -- A rotated graphic's rect is its (inflated) bounding box, so resize in an + -- upright frame, then restore the angle. Axis-aligned parts skip this entirely. + put 0 into tAng + if kindHasBody(tKind) then put round(b2kAngle(pCtrl)) into tAng + if tAng is not 0 then + b2kMoveTo pCtrl, tCx, tCy, 0 + renderBuild + end if + put numOr(the uW of pCtrl, the width of pCtrl) into tW + put numOr(the uH of pCtrl, the height of pCtrl) into tH put clampDim(pValue) into pValue if pAxis is "w" then put pValue into tW else if pAxis is "h" then put pValue into tH @@ -4129,9 +4247,12 @@ on setPartDimension pCtrl, pAxis, pValue set the width of pCtrl to tW set the height of pCtrl to tH set the loc of pCtrl to tCx & "," & tCy + set the uW of pCtrl to tW + set the uH of pCtrl to tH if kindHasBody(tKind) then b2kReshape pCtrl, shapeOfKind(tKind) reapplyMaterial pCtrl + if tAng is not 0 then b2kMoveTo pCtrl, tCx, tCy, tAng end if end setPartDimension @@ -4171,10 +4292,10 @@ function currentPropValue pCtrl, pKey case "length" case "diameter" case "size" - return the width of pCtrl + return numOr(the uW of pCtrl, the width of pCtrl) case "height" case "thickness" - return the height of pCtrl + return numOr(the uH of pCtrl, the height of pCtrl) case "angle" return round(b2kAngle(pCtrl)) case "bounce" @@ -4326,6 +4447,7 @@ function jointUnderClick pX, pY if gJN < 1 then return empty repeat with tI = 1 to gJN if gJKind[tI] is empty then next repeat + if gJVis[tI] is "none" then next repeat put jointHandleLoc(tI) into tH if tH is empty then next repeat put sqrt((pX - item 1 of tH)^2 + (pY - item 2 of tH)^2) into tD @@ -4985,7 +5107,7 @@ function niceName pId & "balloon=Helium Balloon" & cr & "bomb=Bomb" & cr & "plate=Pressure Plate" & cr \ & "fan=Fan / Wind" & cr & "magnet=Magnet" & cr & "hinge=Hinge Joint" & cr \ & "weld=Weld Joint" & cr & "rope=Rope Joint" & cr & "slider=Slider Joint" & cr \ - & "wheel=Wheel Joint" into tNames + & "wheel=Wheel Joint" & cr & "bridge=Bridge" & cr & "chain=Chain (rope)" into tNames local tLine set the itemDelimiter to "=" repeat for each line tLine in tNames @@ -5005,7 +5127,7 @@ function toolGlyph pId put "drag=✥" & cr & "box=■" & cr & "ball=●" & cr & "capsule=▬" & cr & "poly=◆" & cr \ & "image=▦" & cr & "anchor=▼" & cr & "delete=✕" & cr & "duplicate=▣" & cr & "balloon=◯" & cr & "bomb=◉" & cr \ & "plate=▭" & cr & "fan=▷" & cr & "magnet=◐" & cr & "hinge=○" & cr & "weld=▰" & cr \ - & "rope=∿" & cr & "slider=↔" & cr & "wheel=◎" into tGlyphs + & "rope=∿" & cr & "slider=↔" & cr & "wheel=◎" & cr & "bridge=◠" & cr & "chain=∾" into tGlyphs local tLine set the itemDelimiter to "=" repeat for each line tLine in tGlyphs @@ -5059,6 +5181,10 @@ function toolHelp pId return "Let one part slide along a line." & cr & "A slider lets one part slide in a straight line relative to another — like a piston or a drawer." case "wheel" return "Add a springy, spinning wheel." & cr & "A wheel joint carries a wheel with springy suspension and lets it spin freely — switch Motor on to drive a vehicle." + case "bridge" + return "Span a plank bridge between two points." & cr & "Bridge tool. Click a part (or empty space), then a second point: a row of hinged planks spans the gap and sags under weight. Anchor the ends to Anchors or the world." + case "chain" + return "Hang a flexible segmented rope." & cr & "Chain tool. Click two points and a rope of small hinged links drapes between them. Unlike the rigid Rope joint, it bends, coils and swings — great for swings and tethers." end switch return niceName(pId) & cr & "Select this tool, then click the stage." end toolHelp diff --git a/src/box2dxt-kit.livecodescript b/src/box2dxt-kit.livecodescript index 8a2518b..4f0d1dc 100644 --- a/src/box2dxt-kit.livecodescript +++ b/src/box2dxt-kit.livecodescript @@ -484,15 +484,15 @@ end b2kSpawnCapsule -- Materials & body properties -- ===================================================================== command b2kSetBounce pControl, pRestitution - b2SetShapeRestitution sShapeH[the long id of pControl], pRestitution + if sShapeH[the long id of pControl] is not empty then b2SetShapeRestitution sShapeH[the long id of pControl], pRestitution end b2kSetBounce command b2kSetFriction pControl, pFriction - b2SetShapeFriction sShapeH[the long id of pControl], pFriction + if sShapeH[the long id of pControl] is not empty then b2SetShapeFriction sShapeH[the long id of pControl], pFriction end b2kSetFriction command b2kSetDensity pControl, pDensity - b2SetShapeDensity sShapeH[the long id of pControl], pDensity + if sShapeH[the long id of pControl] is not empty then b2SetShapeDensity sShapeH[the long id of pControl], pDensity end b2kSetDensity -- Re-fit a body's collision shape to the control's CURRENT size, in place on the @@ -578,6 +578,17 @@ command b2kWake pControl b2SetAwake sBody[the long id of pControl], true end b2kWake +-- Send a body to sleep (it stops simulating until something wakes it). +command b2kSleep pControl + b2SetAwake sBody[the long id of pControl], false +end b2kSleep + +-- Below this speed (pixels/sec) a body may fall asleep. Lower = stays awake +-- longer; higher = sleeps sooner (saves CPU). +command b2kSetSleepThreshold pControl, pPxPerSec + b2SetSleepThreshold sBody[the long id of pControl], pPxPerSec / sScale +end b2kSetSleepThreshold + -- ===================================================================== -- Acting on bodies (velocities/kicks are in PIXELS/sec, screen-oriented) -- ===================================================================== @@ -610,6 +621,18 @@ command b2kForce pControl, pFxPx, pFyPx b2ApplyForce sBody[the long id of pControl], pFxPx / sScale, - pFyPx / sScale, true end b2kForce +-- A one-shot impulse (a sharp kick), screen-oriented. Mass-aware: heavier bodies +-- move less. b2kPush changes velocity directly; this is the impulse equivalent. +command b2kImpulse pControl, pIxPx, pIyPx + b2ApplyImpulse sBody[the long id of pControl], pIxPx / sScale, - pIyPx / sScale, true +end b2kImpulse + +-- A continuous turning force (same units as motor torque). Positive turns one way, +-- negative the other. Apply each frame for a sustained twist; pairs with b2kForce. +command b2kTorque pControl, pTorque + b2ApplyTorque sBody[the long id of pControl], pTorque, true +end b2kTorque + -- Change a body's type at runtime: "static", "kinematic", or "dynamic". command b2kSetType pControl, pType local tRef, tCode @@ -730,6 +753,19 @@ function b2kIsAwake pControl return b2BodyIsAwake(sBody[the long id of pControl]) end b2kIsAwake +-- Current rotation speed in DEGREES/sec (the getter for b2kSpin / b2kSpinBy). +function b2kSpinRate pControl + return b2BodyAngularVelocity(sBody[the long id of pControl]) * 180 / kPI +end b2kSpinRate + +function b2kIsBullet pControl + return b2BodyIsBullet(sBody[the long id of pControl]) +end b2kIsBullet + +function b2kIsEnabled pControl + return b2BodyIsEnabled(sBody[the long id of pControl]) +end b2kIsEnabled + function b2kMass pControl return b2BodyMass(sBody[the long id of pControl]) end b2kMass @@ -876,6 +912,11 @@ function b2kRopeLength pJoint return b2DistanceLength(pJoint) * sScale end b2kRopeLength +-- Set a rope (distance) joint's exact rest length, in pixels. +command b2kRopeSetLength pJoint, pLengthPx + b2DistanceSetLength pJoint, pLengthPx / sScale +end b2kRopeSetLength + command b2kRopeRange pJoint, pMinPx, pMaxPx b2DistanceSetLengthRange pJoint, pMinPx / sScale, pMaxPx / sScale end b2kRopeRange