1 module testbed.character; 2 3 import std.math; 4 5 import dlib.core.memory; 6 import dlib.math.vector; 7 import dlib.math.matrix; 8 import dlib.math.transformation; 9 import dlib.math.utils; 10 11 import dmech.world; 12 import dmech.rigidbody; 13 import dmech.geometry; 14 import dmech.shape; 15 import dmech.contact; 16 import dmech.raycast; 17 18 /* 19 * CharacterController implements kinematic body 20 * on top of dmech dynamics: it allows direct 21 * velocity changes for a RigidBody. 22 * CharacterController is intended for 23 * generic action game character movement. 24 */ 25 class CharacterController 26 { 27 PhysicsWorld world; 28 RigidBody rbody; 29 bool onGround = false; 30 Vector3f direction = Vector3f(0, 0, 1); 31 float speed = 0.0f; 32 float jumpSpeed = 0.0f; 33 float artificalGravity = 50.0f; 34 float boundingSphereRadius; 35 RigidBody floorBody; 36 37 this(PhysicsWorld world, Vector3f pos, float mass, Geometry geom) 38 { 39 this.world = world; 40 rbody = world.addDynamicBody(pos); 41 rbody.bounce = 0.0f; 42 rbody.friction = 1.0f; 43 rbody.enableRotation = false; 44 rbody.useOwnGravity = true; 45 rbody.gravity = Vector3f(0.0f, -artificalGravity, 0.0f); 46 rbody.raycastable = false; 47 world.addShapeComponent(rbody, geom, Vector3f(0, 0, 0), mass); 48 boundingSphereRadius = 1.0f; 49 } 50 51 void update(bool clampY = true) 52 { 53 Vector3f targetVelocity = direction * speed; 54 Vector3f velocityChange = targetVelocity - rbody.linearVelocity; 55 velocityChange.y = jumpSpeed; 56 rbody.linearVelocity += velocityChange; 57 58 onGround = checkOnGround(); 59 60 if (onGround && floorBody && speed == 0.0f && jumpSpeed == 0.0f) 61 rbody.linearVelocity = floorBody.linearVelocity; 62 63 speed = 0.0f; 64 jumpSpeed = 0.0f; 65 } 66 67 bool checkOnGround() 68 { 69 floorBody = null; 70 CastResult cr; 71 bool hit = world.raycast(rbody.position, Vector3f(0, -1, 0), 10, cr, true, true); 72 if (hit) 73 { 74 if (distance(cr.point, rbody.position) <= boundingSphereRadius) 75 { 76 floorBody = cr.rbody; 77 return true; 78 } 79 } 80 return false; 81 } 82 83 void move(Vector3f direction, float spd) 84 { 85 this.direction = direction; 86 this.speed = spd; 87 } 88 89 void jump(float height) 90 { 91 if (onGround) 92 { 93 //rbody.linearVelocity.y = jumpSpeed(height); 94 jumpSpeed = calcJumpSpeed(height); 95 onGround = false; 96 } 97 } 98 99 float calcJumpSpeed(float jumpHeight) 100 { 101 return sqrt(2.0f * jumpHeight * artificalGravity); 102 } 103 104 void free() 105 { 106 Delete(this); 107 } 108 }