/// //Allows the parkour controller to vertically wallrun // //Parameters: // obj: A pointer to the object attached to the parkourController state // state: The parkourController state updating the object static void State_ParkourController_VerticalWallrun(GObject* obj, State* state) { //Get the members of this state struct State_ParkourController_Members* members = (struct State_ParkourController_Members*)state->members; Vector impulse; Vector_INIT_ON_STACK(impulse, 3); impulse.components[1] = members->jumpMag; RigidBody_ApplyImpulse(obj->body, &impulse, &Vector_ZERO); //Cap max upward speed if(obj->body->velocity->components[1] > members->maxVelocity) { obj->body->velocity->components[1] = members->maxVelocity; } if(obj->body->velocity->components[0] != 0.0f || obj->body->velocity->components[2]) { Vector_Copy(&impulse, &Vector_ZERO); impulse.components[0] -= obj->body->velocity->components[0]; impulse.components[2] -= obj->body->velocity->components[2]; RigidBody_ApplyImpulse(obj->body, &impulse, &Vector_ZERO); } }
/// //Lets the runner jump off of a wall // obj: A pointer to the object // state: A pointer to the runner controller state which is allowing the object to wall jump void State_RunnerController_WallJump(GObject* obj, State* state) { //Get the members of this state struct State_RunnerController_Members* members = (struct State_RunnerController_Members*)state->members; Vector impulse; Vector_INIT_ON_STACK(impulse, 3); Vector_Copy(&impulse, members->wallNormal); Vector_Scale(&impulse, members->jumpMag * 2); RigidBody_ApplyImpulse(obj->body, &impulse, &Vector_ZERO); Vector_Copy(&impulse, &Vector_E2); Vector_Scale(&impulse, members->jumpMag); RigidBody_ApplyImpulse(obj->body, &impulse, &Vector_ZERO); }
/// //Allows the parkour controller to jump // //Parameters: // obj: A pointer to the object attached to the ParkourController state // state: The parkour state updating the object static void State_ParkourController_Jump(GObject* obj, State* state) { struct State_ParkourController_Members* members = (struct State_ParkourController_Members*)state->members; Vector jumpImpulse; Vector_INIT_ON_STACK(jumpImpulse, 3); jumpImpulse.components[1] = members->jumpMag; RigidBody_ApplyImpulse(obj->body, &jumpImpulse, &Vector_E1); }
/// //Lets the ParkourController vault over a wall // //Parameters: // obj: A pointer to the object attached to the ParkourController state // state: void State_ParkourController_WallVault(GObject* obj, State* state) { //Get the members of this state struct State_ParkourController_Members* members = (struct State_ParkourController_Members*)state->members; Vector impulse; Vector_INIT_ON_STACK(impulse, 3); Vector_Copy(&impulse, members->wallNormal); Vector_Scale(&impulse, -members->maxVelocity); RigidBody_ApplyImpulse(obj->body, &impulse, &Vector_ZERO); }
/// //Lets the runner vault off of a wall // obj: A pointer to the object // state: A pointer to the runner controller state which is allowing the object to wall vault void State_RunnerController_WallVault(GObject* obj, State* state) { //Get the members of this state struct State_RunnerController_Members* members = (struct State_RunnerController_Members*)state->members; Vector impulse; Vector_INIT_ON_STACK(impulse, 3); Vector_Copy(&impulse, members->wallNormal); float mag = obj->body->velocity->components[1]; Vector_Scale(&impulse, -mag * 1.0f); RigidBody_ApplyImpulse(obj->body, &impulse, &Vector_ZERO); Vector_Copy(&impulse, &Vector_E2); obj->body->velocity->components[1] = 0; Vector_Scale(&impulse, members->jumpMag); RigidBody_ApplyImpulse(obj->body, &impulse, &Vector_ZERO); }
/// //Allows the runner controller to jump if necessary conditions are met // //Parameters: // obj: A pointer to the object jumping // state: A pointer to the runner controller state which is jumping the object void State_RunnerController_Jump(GObject* obj, State* state) { //If the object is allowed to jump if(State_RunnerController_IsOnGround(obj, state)) { //Grab the state members struct State_RunnerController_Members* members = (struct State_RunnerController_Members*)state->members; Vector jumpImpulse; Vector_INIT_ON_STACK(jumpImpulse, 3); jumpImpulse.components[1] = members->jumpMag; RigidBody_ApplyImpulse(obj->body, &jumpImpulse, &Vector_ZERO); } }
/// //Allows the runner controller to wallrun if necessary conditions are met // //Parameters: // obj: A pointer to the object which is running on walls // state: A pointer to the runner controller state which is allowing the object to wallrun void State_RunnerController_Wallrun(GObject* obj, State* state) { //Get the members of this state struct State_RunnerController_Members* members = (struct State_RunnerController_Members*)state->members; //Get the first collision this object is involved in Collision* first = (Collision*)obj->collider->currentCollisions->head->data; //If we are not wallrunning yet if(members->horizontalRunning == 0 && members->verticalRunning == 0) { //Make sure this is a wall if(first->minimumTranslationVector->components[0] != 0.0 || first->minimumTranslationVector->components[2] != 0.0f) { //Save the normal Vector_Copy(members->wallNormal, first->minimumTranslationVector); if(first->obj1 != obj) { Vector_Scale(members->wallNormal, -1.0f); } //Determine what kind of wallrun is occurring //First get the forward vector of the camera Camera* cam = RenderingManager_GetRenderingBuffer()->camera; Vector forward; Vector_INIT_ON_STACK(forward, 3); Matrix_SliceRow(&forward, cam->rotationMatrix, 2, 0, 3); //Project the forward vector onto the XY Plane Vector perp; Vector_INIT_ON_STACK(perp, 3); Vector_GetProjection(&perp, &forward, &Vector_E2); Vector_Decrement(&forward, &perp); Vector_Normalize(&forward); //Get dot product of forward vector and collision normal float dotProd = fabs(Vector_DotProduct(&forward, first->minimumTranslationVector)); //If the dot product is closer to 0 we are horizontal running, else we are vertical running if(dotProd < 0.75) { members->horizontalRunning = 1; } else { members->verticalRunning = 1; } } } //If we are horizontal running if(members->horizontalRunning == 1) { printf("Horizontal Wallrunnin\n"); //combat the force of gravity Vector antiGravity; Vector_INIT_ON_STACK(antiGravity, 3); antiGravity.components[1] = 9.81f; RigidBody_ApplyForce(obj->body, &antiGravity, &Vector_ZERO); //Zero downward velocity if(obj->body->velocity->components[1] < 0.0f) { Vector_Copy(&antiGravity, &Vector_ZERO); antiGravity.components[1] = -obj->body->velocity->components[1]; RigidBody_ApplyImpulse(obj->body, &antiGravity, &Vector_ZERO); } State_RunnerController_Accelerate(obj, state); } else if(members->verticalRunning == 1) { printf("Vertical Wallrunnin\n"); //combat the force of gravity Vector antiGravity; Vector_INIT_ON_STACK(antiGravity, 3); Vector_Copy(&antiGravity, &Vector_E2); //go up! Vector_Scale(&antiGravity, 9.81); RigidBody_ApplyForce(obj->body, &antiGravity, &Vector_ZERO); //If we aren't jumping too fast yet if(Vector_DotProduct(obj->body->velocity, &Vector_E2) < members->maxVelocity) { Vector_Copy(&antiGravity, &Vector_E2); Vector_Scale(&antiGravity, members->acceleration); RigidBody_ApplyForce(obj->body, &antiGravity, &Vector_ZERO); } } }
void State_ParkourController_Shoot(GObject* obj, State* state) { //Get the members of the state struct State_ParkourController_Members* members = (struct State_ParkourController_Members*)state->members; //Get a reference to the camera Camera* cam = RenderingManager_GetRenderingBuffer()->camera; if(InputManager_GetInputBuffer().mouseLock) { //IF we can shoot again if(members->shootTimer >= members->shootCooldown) { //Get the forward vector of the camera Vector direction; Vector_INIT_ON_STACK(direction, 3); Matrix_SliceRow(&direction, cam->rotationMatrix, 2, 0, 3); Vector_Scale(&direction, -1.0f); //Create the bullet object GObject* bullet = GObject_Allocate(); GObject_Initialize(bullet); //Set the appearance bullet->mesh = AssetManager_LookupMesh("Cube"); //bullet->texture = AssetManager_LookupTexture("White"); bullet->material = Material_Allocate(); Material_Initialize(bullet->material, AssetManager_LookupTexture("Jacob")); //*Matrix_Index(bullet->material->colorMatrix, 1, 1) = 0.0f; //*Matrix_Index(bullet->material->colorMatrix, 2, 2) = 0.0f; //Create ridgid body bullet->body = RigidBody_Allocate(); RigidBody_Initialize(bullet->body, bullet->frameOfReference, 1.0f); bullet->body->coefficientOfRestitution = 0.2f; bullet->body->rollingResistance = 0.2f; bullet->body->staticFriction = 0.4f; bullet->body->dynamicFriction = 0.2f; //Create collider bullet->collider = Collider_Allocate(); ConvexHullCollider_Initialize(bullet->collider); ConvexHullCollider_MakeRectangularCollider(bullet->collider->data->convexHullData, 2.0f, 2.0f, 2.0f); //Position bullet Vector transform; Vector_INIT_ON_STACK(transform, 3); Vector_GetScalarProduct(&transform, &direction, 2.8243f); Vector_Increment(&transform, obj->frameOfReference->position); GObject_Translate(bullet, &transform); Vector_Copy(&transform, &Vector_ZERO); transform.components[2] = 1.0f; GObject_Rotate(bullet, &transform, 3.14159f); //Scale bullet Vector_Copy(&transform, &Vector_ZERO); transform.components[0] = transform.components[1] = transform.components[2] = 0.5f; GObject_Scale(bullet, &transform); //Apply impulse Vector_Scale(&direction, 25.0f); RigidBody_ApplyImpulse(bullet->body, &direction, &Vector_ZERO); //Add the remove state State* state = State_Allocate(); State_Remove_Initialize(state, 7.0f); GObject_AddState(bullet, state); //Add the bullet to the world ObjectManager_AddObject(bullet); //Set shoot timer to 0 members->shootTimer = 0.0f; } } }
/// //Allows the parkour controller to horizontally wallrun // //Parameters: // obj: A pointer to the object attached to the parkourController state // state: The parkourController state updating the object static void State_ParkourController_HorizontalWallrun(GObject* obj, State* state) { printf("Horizontal\n"); //Get the members of this state struct State_ParkourController_Members* members = (struct State_ParkourController_Members*)state->members; //Zero downward velocity if(obj->body->velocity->components[1] < 0.0f) { Vector impulse; Vector_INIT_ON_STACK(impulse, 3); impulse.components[1] = -obj->body->velocity->components[1]; RigidBody_ApplyImpulse(obj->body, &impulse, &Vector_ZERO); } //Accelerate along wall //Get the projection of the forward vector onto the wall's plane //Start by getting for forward vector of the camera Camera* cam = RenderingManager_GetRenderingBuffer()->camera; Vector forward; Vector_INIT_ON_STACK(forward, 3); Matrix_SliceRow(&forward, cam->rotationMatrix, 2, 0, 3); //Forward of camera is back of object... Vector_Scale(&forward, -1.0f); //Project the forward vector onto the wall plane Vector perp; Vector_INIT_ON_STACK(perp, 3); Vector_GetProjection(&perp, &forward, members->wallNormal); Vector_Decrement(&forward, &perp); //Set the Y component to 0 to get horizontal vector along wall! forward.components[1] = 0.0f; Vector_Normalize(&forward); //MAke sure the velocity in this direction is not too much float magVelAlongWall = Vector_DotProduct(&forward, obj->body->velocity); if(magVelAlongWall < members->maxVelocity) { RigidBody_ApplyImpulse(obj->body, &forward, &Vector_ZERO); } //Apply a cohesive force to the wall to make sure you do not fall off float mag = Vector_DotProduct(obj->body->velocity, members->wallNormal); Vector cohesive; Vector_INIT_ON_STACK(cohesive, 3); if(mag > FLT_EPSILON) { Vector_GetScalarProduct(&cohesive, members->wallNormal, -mag); } else if(mag < FLT_EPSILON) { Vector_GetScalarProduct(&cohesive, members->wallNormal, mag); } RigidBody_ApplyImpulse(obj->body, &cohesive, members->wallNormal); }
// Create an object in front of the character and fire // Parameters: // GO: The object getting passed in, in this case the character // State: Needed to grab members void State_CharacterController_ShootBullet(GObject* GO, State* state) { //Get members struct State_CharacterController_Members* members = (struct State_CharacterController_Members*)state->members; // Camera local Camera* cam = RenderingManager_GetRenderingBuffer()->camera; // Gets the time per second float dt = TimeManager_GetDeltaSec(); members->timer += dt; if(InputManager_GetInputBuffer().mouseLock) { // Create a net movement vector Vector direction; Vector_INIT_ON_STACK(direction, 3); if (InputManager_IsMouseButtonPressed(0) && members->timer >= members->coolDown) { //Get "forward" Vector Matrix_SliceRow(&direction, cam->rotationMatrix, 2, 0, 3); Vector_Scale(&direction,-1.0f); // Create the bullet object GObject* bullet = GObject_Allocate(); GObject_Initialize(bullet); //bullet->mesh = AssetManager_LookupMesh("Sphere"); bullet->mesh = AssetManager_LookupMesh("Arrow"); bullet->texture = AssetManager_LookupTexture("Arrow"); bullet->body = RigidBody_Allocate(); RigidBody_Initialize(bullet->body, bullet->frameOfReference, 0.45f); bullet->body->coefficientOfRestitution = 0.2f; bullet->collider = Collider_Allocate(); ConvexHullCollider_Initialize(bullet->collider); ConvexHullCollider_MakeRectangularCollider(bullet->collider->data->convexHullData, 0.1f, 2.0f, 0.1f); //AABBCollider_Initialize(bullet->collider, 2.0f, 2.0f, 2.0f, &Vector_ZERO); //Lay arrow flat GObject_Rotate(bullet, &Vector_E1, -3.14159f / 2.0f); //Construct a rotation matrix to orient bullet Matrix rot; Matrix_INIT_ON_STACK(rot, 3, 3); //Grab 4,4 minor to get 3x3 rotation matrix of camera Matrix_GetMinor(&rot, cam->rotationMatrix, 3, 3); //Transpose it to get correct direction Matrix_Transpose(&rot); //Rotate the bullet Matrix_TransformMatrix(&rot, bullet->frameOfReference->rotation); Matrix_TransformMatrix(&rot, bullet->body->frame->rotation); Vector vector; Vector_INIT_ON_STACK(vector,3); vector.components[0] = 0.9f; vector.components[1] = 1.0f; vector.components[2] = 0.9f; GObject_Scale(bullet, &vector); Vector translation; Vector_INIT_ON_STACK(translation, 3); Vector_GetScalarProduct(&translation, &direction, 2.82843); GObject_Translate(bullet, GO->frameOfReference->position); GObject_Translate(bullet, &translation); Vector_Scale(&direction, 25.0f); //Vector_Increment(bullet->body->velocity,&direction); RigidBody_ApplyImpulse(bullet->body,&direction,&Vector_ZERO); //Add remove state State* state = State_Allocate(); State_Remove_Initialize(state, 5.0f); GObject_AddState(bullet, state); ObjectManager_AddObject(bullet); members->timer = 0; } } }
// translate the character and his bounding box. // Parameters: // GO: The game object this state is attached to (Used for translating the bounding box) // state: The first person camera state updating the gameObject void State_CharacterController_Translate(GObject* GO, State* state) { Camera* cam = RenderingManager_GetRenderingBuffer()->camera; //Get members struct State_CharacterController_Members* members = (struct State_CharacterController_Members*)state->members; if(InputManager_GetInputBuffer().mouseLock) { // Gets the time per second float dt = TimeManager_GetDeltaSec(); Vector netMvmtVec; Vector partialMvmtVec; Vector_INIT_ON_STACK(netMvmtVec, 3); Vector_INIT_ON_STACK(partialMvmtVec, 3); if (InputManager_IsKeyDown('w')) { //Get "back" Vector Matrix_SliceRow(&partialMvmtVec, cam->rotationMatrix, 2, 0, 3); //Subtract "back" Vector from netMvmtVec Vector_Decrement(&netMvmtVec, &partialMvmtVec); //Or in one step but less pretty... Faster though. I think I want readable here for now though. //Vector_DecrementArray(netMvmtVec.components, Matrix_Index(cam->rotationMatrix, 2, 0), 3); } if (InputManager_IsKeyDown('s')) { //Get "back" Vector Matrix_SliceRow(&partialMvmtVec, cam->rotationMatrix, 2, 0, 3); //Add "back" Vector to netMvmtVec Vector_Increment(&netMvmtVec, &partialMvmtVec); } if (InputManager_IsKeyDown('a')) { //Get "Right" Vector Matrix_SliceRow(&partialMvmtVec, cam->rotationMatrix, 0, 0, 3); //Subtract "Right" Vector From netMvmtVec Vector_Decrement(&netMvmtVec, &partialMvmtVec); } if (InputManager_IsKeyDown('d')) { //Get "Right" Vector Matrix_SliceRow(&partialMvmtVec, cam->rotationMatrix, 0, 0, 3); //Add "Right" Vector to netMvmtVec Vector_Increment(&netMvmtVec, &partialMvmtVec); } if (Vector_GetMag(&netMvmtVec) > 0.0f) { // Get the projection and keep player grounded Vector perpMvmtVec; Vector_INIT_ON_STACK(perpMvmtVec, 3); Vector_GetProjection(&perpMvmtVec, &netMvmtVec, &Vector_E2); Vector_Decrement(&netMvmtVec, &perpMvmtVec); // Normalize vector and scale Vector_Normalize(&netMvmtVec); Vector_Scale(&netMvmtVec, members->movementSpeed); //Apply Impulse RigidBody_ApplyImpulse(GO->body, &netMvmtVec, &Vector_ZERO); } } // If vector is going too fast, the maxspeed will keep it from going faster, by scaling it by maxspeed. if(Vector_GetMag(GO->body->velocity) >= members->maxSpeed) { Vector_Normalize(GO->body->velocity); Vector_Scale(GO->body->velocity,members->maxSpeed); } // Set position of Camera to the body Camera_SetPosition(cam,GO->body->frame->position); }