PhysicsBox
Compose Multiplatform physics-enabled layout powered by boks2d. Simply add composables, enable physics, and watch them fall! The Compose equivalent of PhysicsLayout.

Supported Platforms
- Android
- JVM (Desktop)
- iOS (arm64, simulator arm64)
Gradle
Multiplatform
For Compose Multiplatform projects, add the dependency in your commonMain source set:
commonMain.dependencies {
implementation("com.jawnnypoo:physicsbox:latest.release.here")
}
Android
For Android-only projects:
dependencies {
implementation("com.jawnnypoo:physicsbox-android:latest.release.here")
}
JVM (Desktop)
For JVM-only projects:
dependencies {
implementation("com.jawnnypoo:physicsbox-jvm:latest.release.here")
}
Basic Usage
Wrap your composables in a PhysicsBox and they'll start falling with gravity:
val state = rememberPhysicsBoxState()
PhysicsBox(
modifier = Modifier
.fillMaxWidth()
.height(320.dp),
state = state,
) {
Text("Hello world, I have physics!")
}
PhysicsBoxState Configuration
You can customize the behavior of your PhysicsBox through PhysicsBoxState:
val state = rememberPhysicsBoxState().apply {
isPhysicsEnabled = true
isFlingEnabled = true
hasBounds = true
gravityX = 0f
gravityY = PhysicsBoxState.EARTH_GRAVITY
subStepCount = 4
}
Gravity constants are provided for convenience:
PhysicsBoxState.NO_GRAVITY — 0.0
PhysicsBoxState.MOON_GRAVITY — 1.6
PhysicsBoxState.EARTH_GRAVITY — 9.8
PhysicsBoxState.JUPITER_GRAVITY — 24.8
Custom Physics Configuration
Each child composable can have its own physics configuration via Modifier.physicsBody(...). This defines its collision shape, mass, bounciness, and other physics properties:
Box(
modifier = Modifier
.size(48.dp)
.physicsBody(
shape = Shape.CIRCLE,
bodyType = PhysicsBodyType.DYNAMIC,
friction = 0.3f,
restitution = 0.2f,
density = 0.2f,
fixedRotation = false,
)
.background(Color.Red, CircleShape)
)
This is especially useful for circular composables, since the default collision shape for all children is RECTANGLE. For most rectangular views, the defaults work fine.
Tilt / Gimbal Gravity
Hook your device's sensor data into gravity for a tilt-controlled experience:
state.setGravity(x = sensorX, y = sensorY)
This updates boks2d gravity in real time.
Sample App
Check out the sample modules to see these features in action:
- Android: Build and run the
:androidApp module
- Desktop:
./gradlew :composeApp:run
The sample includes gravity sliders, bounds toggle, fling/drag interactions, and mixed shapes. On Android, tilt/gimbal control is also available via the device accelerometer.
Making a Game?
This library was designed with the intention of allowing for playful physics animations within normal apps. It is not built to be a game engine or meant to compete with the likes. If you are looking to do more intense mobile games, we recommend libraries such as libGDX or Unity
License
Copyright 2026 John Carlson
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance the License.
You may obtain a copy of the License at
http:
Unless applicable law agreed to writing, software
distributed under the License distributed an BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express implied.
See the License the specific language governing permissions
limitations under the License.