mirror of
https://github.com/GayPizzaSpecifications/voxelotl-engine.git
synced 2025-08-03 05:10:57 +00:00
player physics overhaul
This commit is contained in:
@ -2,7 +2,7 @@ import simd
|
||||
|
||||
struct Player {
|
||||
static let height: Float = 1.8
|
||||
static let radius: Float = 0.4
|
||||
static let radius: Float = 0.22
|
||||
static let bounds = AABB(
|
||||
from: .init(-Self.radius, 0, -Self.radius),
|
||||
to: .init(Self.radius, Self.height, Self.radius))
|
||||
@ -10,9 +10,12 @@ struct Player {
|
||||
static let eyeLevel: Float = 1.4
|
||||
static let epsilon = Float.ulpOfOne * 10
|
||||
|
||||
static let accelerationCoeff: Float = 7.5
|
||||
static let gravityCoeff: Float = 12
|
||||
static let jumpVelocity: Float = 9
|
||||
static let accelerationCoeff: Float = 75
|
||||
static let airAccelCoeff: Float = 3
|
||||
static let gravityCoeff: Float = 20
|
||||
static let frictionCoeff: Float = 22
|
||||
static let jumpVelocity: Float = 7
|
||||
static let maxVelocity: Float = 160
|
||||
|
||||
private var _position = SIMD3<Float>.zero
|
||||
private var _velocity = SIMD3<Float>.zero
|
||||
@ -24,11 +27,14 @@ struct Player {
|
||||
public var velocity: SIMD3<Float> { get { self._velocity } set { self._velocity = newValue } }
|
||||
public var rotation: SIMD2<Float> { get { self._rotation } set { self._rotation = newValue } }
|
||||
|
||||
public var eyePosition: SIMD3<Float> { self._position + .init(0, Self.eyeLevel, 0) }
|
||||
public var eyePosition: SIMD3<Float> { self._position + .up * Self.eyeLevel }
|
||||
public var eyeRotation: simd_quatf {
|
||||
.init(angle: self._rotation.y, axis: .right) *
|
||||
.init(angle: self._rotation.x, axis: .up)
|
||||
}
|
||||
|
||||
mutating func update(deltaTime: Float, boxes: [Box]) {
|
||||
if let pad = GameController.current?.state {
|
||||
|
||||
// Turning input
|
||||
let turning = pad.rightStick.radialDeadzone(min: 0.1, max: 1)
|
||||
_rotation += turning * deltaTime * 3.0
|
||||
@ -39,25 +45,21 @@ struct Player {
|
||||
}
|
||||
self._rotation.y = self._rotation.y.clamp(-.pi * 0.5, .pi * 0.5)
|
||||
|
||||
// Movement (slower in air than on ground)
|
||||
let movement = pad.leftStick.cardinalDeadzone(min: 0.1, max: 1)
|
||||
let rotc = cos(self._rotation.x), rots = sin(self._rotation.x)
|
||||
let movementScale: Float = self._onGround ? 1.0 : 0.4
|
||||
self._velocity.x = (
|
||||
movement.x * rotc - movement.y * rots
|
||||
) * Self.accelerationCoeff * movementScale
|
||||
self._velocity.z = (
|
||||
movement.y * rotc + movement.x * rots
|
||||
) * Self.accelerationCoeff * movementScale
|
||||
|
||||
// Jumping
|
||||
if self._onGround {
|
||||
// Jumping
|
||||
if pad.pressed(.east) {
|
||||
self._velocity.y = Self.jumpVelocity
|
||||
self._onGround = false
|
||||
}
|
||||
}
|
||||
|
||||
// Movement (slower in air than on ground)
|
||||
let movement = pad.leftStick.cardinalDeadzone(min: 0.1, max: 1)
|
||||
let rotc = cos(self._rotation.x), rots = sin(self._rotation.x)
|
||||
let coeff = self._onGround ? Self.accelerationCoeff : Self.airAccelCoeff
|
||||
self._velocity.x += (movement.x * rotc - movement.y * rots) * coeff * deltaTime
|
||||
self._velocity.z += (movement.y * rotc + movement.x * rots) * coeff * deltaTime
|
||||
|
||||
// Flying and unflying
|
||||
self._velocity.y += (pad.rightTrigger - pad.leftTrigger) * 36 * deltaTime
|
||||
}
|
||||
@ -75,27 +77,27 @@ struct Player {
|
||||
}
|
||||
return nil
|
||||
}
|
||||
self._position.x += _velocity.x * deltaTime
|
||||
self._position.x += self._velocity.x * deltaTime
|
||||
if let aabb = checkCollision(self._position) {
|
||||
if _velocity.x < 0 {
|
||||
if self._velocity.x < 0 {
|
||||
self._position.x = aabb.right + Self.radius + Self.epsilon
|
||||
} else {
|
||||
self._position.x = aabb.left - Self.radius - Self.epsilon
|
||||
}
|
||||
self._velocity.x = 0
|
||||
}
|
||||
self._position.z += _velocity.z * deltaTime
|
||||
self._position.z += self._velocity.z * deltaTime
|
||||
if let aabb = checkCollision(self._position) {
|
||||
if _velocity.z < 0 {
|
||||
if self._velocity.z < 0 {
|
||||
self._position.z = aabb.near + Self.radius + Self.epsilon
|
||||
} else {
|
||||
self._position.z = aabb.far - Self.radius - Self.epsilon
|
||||
}
|
||||
self._velocity.z = 0
|
||||
}
|
||||
self._position.y += _velocity.y * deltaTime
|
||||
if let aabb = checkCollision(self._position) {
|
||||
if _velocity.y < 0 {
|
||||
self._position.y += self._velocity.y * deltaTime
|
||||
if let aabb = checkCollision(self._velocity.y > 0 ? self._position + .down * Self.epsilon : self.position) {
|
||||
if self._velocity.y < 0 {
|
||||
self._position.y = aabb.top + Self.epsilon
|
||||
self._onGround = true
|
||||
} else {
|
||||
@ -109,20 +111,14 @@ struct Player {
|
||||
|
||||
// Ground friction
|
||||
if self._onGround {
|
||||
self._velocity.x = 0
|
||||
self._velocity.z = 0
|
||||
self._velocity.x /= 1.0 + Self.frictionCoeff * deltaTime
|
||||
self._velocity.z /= 1.0 + Self.frictionCoeff * deltaTime
|
||||
}
|
||||
|
||||
if self._velocity.x > 10 {
|
||||
self._velocity.x = 10
|
||||
}
|
||||
|
||||
if self._velocity.y > 10 {
|
||||
self._velocity.y = 10
|
||||
}
|
||||
|
||||
if abs(self._velocity.y) > 40 {
|
||||
self._velocity.y = Float(signOf: self._velocity.y, magnitudeOf: 40.0)
|
||||
// Limit maximum velocity
|
||||
let velocityLen = simd_length(self._velocity)
|
||||
if velocityLen > Self.maxVelocity {
|
||||
self._velocity = self._velocity / velocityLen * Self.maxVelocity
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user