ktx.box2d.worlds.kt Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of ktx-box2d Show documentation
Show all versions of ktx-box2d Show documentation
Box2D physics engine utilities for Kotlin libGDX applications.
The newest version!
package ktx.box2d
import com.badlogic.gdx.math.Vector2
import com.badlogic.gdx.physics.box2d.Body
import com.badlogic.gdx.physics.box2d.BodyDef.BodyType
import com.badlogic.gdx.physics.box2d.Fixture
import com.badlogic.gdx.physics.box2d.World
import kotlin.contracts.ExperimentalContracts
import kotlin.contracts.InvocationKind
import kotlin.contracts.contract
/**
* [World] factory function.
* @param gravity world's gravity applied to bodies on each step. Defaults to no gravity (0f, 0f).
* @param allowSleep if true, inactive bodies will not be simulated. Improves performance. Defaults to true.
* @return a new [World] instance with given parameters.
*/
fun createWorld(gravity: Vector2 = Vector2.Zero, allowSleep: Boolean = true) = World(gravity, allowSleep)
/**
* Type-safe [Body] building DSL.
* @param type [BodyType] of the constructed [Body]. Matches libGDX default of [BodyType.StaticBody].
* @param init inlined. Invoked on a [BodyDefinition] instance, which provides access to [Body] properties, as well as
* fixture building DSL. Defaults to no-op.
* @return a fully constructed [Body] instance with all defined fixtures.
* @see BodyDefinition
* @see FixtureDefinition
*/
@Box2DDsl
@OptIn(ExperimentalContracts::class)
inline fun World.body(type: BodyType = BodyType.StaticBody, init: BodyDefinition.() -> Unit = {}): Body {
contract { callsInPlace(init, InvocationKind.EXACTLY_ONCE) }
val bodyDefinition = BodyDefinition()
bodyDefinition.type = type
bodyDefinition.init()
return create(bodyDefinition)
}
/**
* Handles additional building properties provided by [BodyDefinition] and [FixtureDefinition]. Prefer this method
* over [World.createBody] when using [BodyDefinition] directly.
* @param bodyDefinition stores [Body] properties and optional [Fixture] definitions.
* @return a fully constructed [Body] instance with all defined fixtures.
* @see BodyDefinition
* @see FixtureDefinition
* @see body
*/
fun World.create(bodyDefinition: BodyDefinition): Body {
val body = createBody(bodyDefinition)
body.userData = bodyDefinition.userData
for (fixtureDefinition in bodyDefinition.fixtureDefinitions) {
val fixture = body.createFixture(fixtureDefinition)
fixture.userData = fixtureDefinition.userData
fixtureDefinition.creationCallback?.let { it(fixture) }
if (fixtureDefinition.disposeOfShape) {
fixtureDefinition.shape.dispose()
}
}
bodyDefinition.creationCallback?.let { it(body) }
return body
}
/**
* Roughly matches Earth gravity of 9.80665 m/s^2. Moves bodies down on the Y axis.
*
* Note that [Vector2] class is mutable, so this vector can be modified. Use this property in read-only mode.
*
* Usage example:
* val world = createWorld(gravity = earthGravity)
* @see createWorld
*/
val earthGravity = Vector2(0f, -9.8f)
/**
* Callback lambda for ray-casts.
*
* This lambda is called for each fixture the ray-cast hits.
*
* There is no guarantee on the order of the callback is called, e.g. the first call to the lambda
* is not necessarily the nearest to the start point of the ray.
*
* The lambda accepts these parameters:
* - [Fixture], the fixture hit by the ray.
* - [Vector2], the point of initial intersection.
* - [Vector2], the normal vector at the point of intersection.
* - [Float], the fraction of the distance from `start` to `end` that the intersection point is at.
*
* The lambda returns the new length of the ray as a fraction of the distance between the start and
* end or the ray. Common values are:
* - `-1f`, ignore this fixture and continue.
* - `0f`, terminate the ray cast.
* - A fraction, clip the length of the ray to this point.
* - `1f`, don't clip the ray and continue.
*
* Can be used in place of [com.badlogic.gdx.physics.box2d.RayCastCallback] via Kotlin SAM conversion.
*
* @see RayCast
* @see rayCast
*/
typealias KtxRayCastCallback = (
fixture: Fixture,
point: Vector2,
normal: Vector2,
fraction: Float,
) -> Float
/**
* Stores constants that can be returned by [KtxRayCastCallback] to control its behavior.
* @see rayCast
*/
object RayCast {
/**
* Indicates to ignore the hit fixture and continue.
* @see KtxRayCastCallback
*/
const val IGNORE = -1f
/**
* Indicates to terminate the ray cast.
* @see KtxRayCastCallback
*/
const val TERMINATE = 0f
/**
* Indicates to not clip the ray and continue.
* @see KtxRayCastCallback
*/
const val CONTINUE = 1f
}
/**
* Ray-cast the world for all fixtures in the path of the ray.
*
* The ray-cast ignores shapes that contain the starting point.
*
* @param start the ray starting point.
* @param end the ray ending point.
* @param callback a user implemented callback called on every fixture hit.
* @see RayCast
*/
fun World.rayCast(
start: Vector2,
end: Vector2,
callback: KtxRayCastCallback,
) {
rayCast(callback, start, end)
}
/**
* Ray-cast the world for all fixtures in the path of the ray.
*
* The ray-cast ignores shapes that contain the starting point.
*
* @param startX the ray starting point X.
* @param startY the ray starting point Y.
* @param endX the ray ending point X.
* @param endY the ray ending point Y.
* @param callback a user implemented callback called on every fixture hit.
* @see RayCast
*/
fun World.rayCast(
startX: Float,
startY: Float,
endX: Float,
endY: Float,
callback: KtxRayCastCallback,
) {
rayCast(callback, startX, startY, endX, endY)
}
/**
* Query the world for all fixtures that potentially overlap the provided AABB (Axis-Aligned Bounding Box).
*
* @param lowerX the x coordinate of the lower left corner
* @param lowerY the y coordinate of the lower left corner
* @param upperX the x coordinate of the upper right corner
* @param upperY the y coordinate of the upper right corner
* @param callback a user implemented callback that is called for every fixture overlapping the AABB.
* @see Query
*/
fun World.query(
lowerX: Float,
lowerY: Float,
upperX: Float,
upperY: Float,
callback: KtxQueryCallback,
) {
QueryAABB(callback, lowerX, lowerY, upperX, upperY)
}
/**
* Stores constants that can be returned by [KtxQueryCallback] to control its behavior.
* @see query
*/
object Query {
/**
* Stop querying the world.
* @see KtxQueryCallback
*/
const val STOP = false
/**
* Continue querying for the next match.
* @see KtxQueryCallback
*/
const val CONTINUE = true
}
/**
* Callback lambda for querying with an AABB.
*
* This lambda is called for each fixture the AABB overlaps.
*
* There is no guarantee on the order of the callback is called.
*
* The lambda returns whether to terminate the query.
*
* Can be used in place of [com.badlogic.gdx.physics.box2d.QueryCallback] via Kotlin SAM conversion.
*
* @see Query
* @see query
*/
typealias KtxQueryCallback = (fixture: Fixture) -> Boolean