-
Notifications
You must be signed in to change notification settings - Fork 0
physics lib
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")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.
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).
| Parameter | Type | Description |
|---|---|---|
stiffness |
Double |
How strongly the item springs back to its resting position. Higher = snappier return. Typical range: 0.01 – 0.05
|
damping |
Double |
How quickly oscillation dies out. Higher = less bouncy. Typical range: 0.1 – 0.5
|
moveRes |
Double |
How strongly player movement acceleration affects the angles. Use a negative value to invert the sway direction. Typical range: -1.0 – 3.0
|
lookRes |
Double |
How strongly camera rotation affects the angles. Higher = more tilt when turning. Typical range: 0.3 – 0.36
|
vertRes |
Double |
How strongly vertical movement (jumping/falling) affects the X angle. Typical range: 0.45 – 0.5
|
inertial |
Double |
Global inertia multiplier. Scales both wind forces and movement/look impulses. Higher = heavier, more sluggish feel. Typical range: 0.8 – 1.0
|
maxAngle |
Double |
Maximum angle clamp in degrees. The simulation will not exceed this in either direction. Typical range: 15 – 60
|
windMult |
Double |
Wind effect strength. Set to 0 to disable wind entirely. Typical range: 0 – 0.1
|
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
endimportScript("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
endUses 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
endAdds 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| 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
|
- 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.
-
angleXandangleZare 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/angleZto both.
GET IN TOUCH - omar@merakistudios.dev
© 2026 Omar Mohamed. All Rights Reserved.