Skip to content

physics lib

Omar Mohamed edited this page Mar 11, 2026 · 5 revisions

Physics Engine

InteractiveStuff ships with a built-in Physics Engine script library written in Vyn. It simulates spring-based item rotation that reacts to player movement, camera rotation, and wind — giving held items a natural, physical feel without you having to write the math yourself.

Import it in any script with:

importScript("interactivestuff:interactive_resourcepack","physics_lib")

How It Works

The physics engine maintains a spring-damper simulation on two rotation axes. Each frame, it accumulates forces from:

  • Player movement — acceleration when you walk, sprint, or strafe
  • Camera rotation — impulses from looking around
  • Vertical movement — jumping, falling, landing
  • Wind — a procedural layered sine wave that adds subtle organic drift

After calling runPhysicsEngine(...), the results are written to two global variables you can read directly:

Variable Description
angleX Current rotation angle on the X axis (pitch-like sway)
angleZ Current rotation angle on the Z axis (roll-like sway)

Apply these to your item using rotateX and rotateZ.


runPhysicsEngine(stiffness, damping, moveRes, lookRes, vertRes, inertial, maxAngle, windMult)

Runs one tick of the physics simulation. Call this once per frame at the top of your script before applying the resulting angles.

Returns 0 early (no-op) if called more than once in the same tick, or if the frame delta is too large (e.g. after a freeze or lag spike — in that case velocities are also reset for stability).

Parameters

Parameter Type Description
stiffness Double How strongly the item springs back to its resting position. Higher = snappier return. Typical range: 0.010.05
damping Double How quickly oscillation dies out. Higher = less bouncy. Typical range: 0.10.5
moveRes Double How strongly player movement acceleration affects the angles. Use a negative value to invert the sway direction. Typical range: -1.03.0
lookRes Double How strongly camera rotation affects the angles. Higher = more tilt when turning. Typical range: 0.30.36
vertRes Double How strongly vertical movement (jumping/falling) affects the X angle. Typical range: 0.450.5
inertial Double Global inertia multiplier. Scales both wind forces and movement/look impulses. Higher = heavier, more sluggish feel. Typical range: 0.81.0
maxAngle Double Maximum angle clamp in degrees. The simulation will not exceed this in either direction. Typical range: 1560
windMult Double Wind effect strength. Set to 0 to disable wind entirely. Typical range: 00.1

Usage Example

Basic plant sway (flowers, grasses)

importScript("interactivestuff:interactive_resourcepack", "physics_lib")

task onItemUpdate takes itemRendered do
    check !modLoader.isModLoaded("holdmyitems") do
        runPhysicsEngine(0.01, 0.15, -1.0, 0.3, 0.5, 1.0, 45, 0.1)

        itemRendered.setPivot(0.0, -0.01, 0.0)
        itemRendered.rotate(angleX, 0, angleZ)
    end
end

Stiff shrub (azalea, flowering azalea)

importScript("interactivestuff:interactive_resourcepack", "physics_lib")

task onItemUpdate takes itemRendered do
    check !modLoader.isModLoaded("holdmyitems") do
        ~ Stiffer, more damped — less floppy than a flower
        runPhysicsEngine(0.05, 0.5, -1.0, 0.3, 0.5, 1.0, 15, 0.1)

        itemRendered.setPivot(0.005, 0.21, 0.12)
        itemRendered.rotate(angleX, 0, angleZ)
    end
end

Item with separate handle and body (basket-style)

Uses select() and setParent() to apply different physics multipliers to different parts of the same model.

importScript("interactivestuff:interactive_resourcepack", "physics_lib")

task onItemUpdate takes itemRendered do
    check !modLoader.isModLoaded("holdmyitems") do
        runPhysicsEngine(0.01, 0.1, 3.0, 0.36, 0.45, 0.8, 60, 0)

        ~ Handle swings with full physics
        make handle = itemRendered.copy()
        handle.select(27, 43)
        handle.setPivot(0, 0.3, 0)
        handle.rotate(angleX, 0, -angleZ)

        ~ Body follows but at 25% intensity
        itemRendered.setParent(handle)
        itemRendered.select(0, 27)
        itemRendered.setPivot(0, 0.15, 0)
        itemRendered.rotate(angleX * 0.25, 0, -angleZ * 0.25)
    end
end

Plant with dynamic shear (organic stretch effect)

Adds squash-and-stretch on top of rotation — scales with how much the item is swaying.

importScript("interactivestuff:interactive_resourcepack", "physics_lib")

task onItemUpdate takes itemRendered do
    check !modLoader.isModLoaded("holdmyitems") do
        runPhysicsEngine(0.01, 0.15, -1.0, 0.3, 0.5, 1.0, 45, 0.1)

        itemRendered.setPivot(0.005, 0.21, 0.12)
        itemRendered.rotate(angleX, 0, angleZ)

        ~ Stretch more the further it's swinging
        make motionSq = angleX * angleX + angleZ * angleZ
        make dynamicScale = 1.0 + motionSq * 0.0005
        check dynamicScale > 1.2 do make dynamicScale = 1.2 end

        make shearXY = angleZ * 0.006 * dynamicScale
        make shearXZ = (angleX * 0.006 + angleZ * 0.006 * 0.35) * dynamicScale
        make shearYX = angleX * 0.003 * dynamicScale
        make shearYZ = angleZ * 0.003 * dynamicScale
        make shearZX = angleZ * 0.0066 * dynamicScale
        make shearZY = angleX * 0.0072 * dynamicScale

        itemRendered.shear(shearXY, shearXZ, shearYX, shearYZ, shearZX, shearZY)
    end
end

Parameter Reference Summary

Goal Adjust
Snappier return to rest Increase stiffness (e.g. 0.05)
Less bouncy / more stable Increase damping (e.g. 0.5)
More sway when walking Increase moveRes (e.g. 3.0)
Invert sway direction Use negative moveRes (e.g. -1.0)
More tilt when turning Increase lookRes (e.g. 0.36)
Stronger jump/fall reaction Increase vertRes (e.g. 0.5)
Heavier, more inertial feel Keep inertial at 1.0
Limit maximum lean angle Decrease maxAngle (e.g. 15)
Wide, dramatic sway Increase maxAngle (e.g. 60)
Remove wind drift Set windMult to 0
Subtle wind Set windMult to 0.1

Notes

  • The simulation is framerate-independent — it uses getDelta() internally so results are consistent at any FPS.
  • The engine resets automatically if a large frame spike is detected (delta > 5.0), preventing the item from flying off-screen after a freeze.
  • angleX and angleZ are global variables — they persist between frames and are updated in-place each call.
  • Only one physics simulation can run per script. If you need independent physics on multiple items (e.g. a parent and overlay), apply the same angleX/angleZ to both.

📖 InteractiveStuff Docs


🧱 Types


⚙️ Scripting

📃 Built-in Library

Clone this wiki locally