Created
June 11, 2012 01:59
-
-
Save od0x0/2908087 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#pragma once | |
#include "KGStage.h" | |
typedef struct KGStagePlayerComponent KGStagePlayerComponent; | |
struct KGStagePlayerComponent { | |
AEFloat | |
contactDampenAmount, | |
jumpImpulseAmount, | |
walkForceAmount, | |
holdDistance; | |
AEUInt32 | |
heldObject, | |
contactCount; | |
bool | |
hasContactWithGround, | |
jumpKeyWasDown, | |
pickUpKeyIsDown; | |
AEVec3 | |
summedSurfaceDirection, | |
movementVelocity, | |
impulseAddedLastFrame, | |
heldObjectOffset; | |
}; | |
KGStagePlayerComponent* KGStagePlayerComponentNew(void); | |
void KGStagePlayerComponentDelete(KGStagePlayerComponent* self); | |
KEValue KGStagePlayerComponentSendEntityMessage(KGStagePlayerComponent* self, KGStage* stage, AEUInt32 entityID, KGStageMessageID messageID, const KEValue* arguments, AEUInt32 argumentCount); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "KGStagePlayerComponent.h" | |
#include "glfw.h" | |
KGStagePlayerComponent* KGStagePlayerComponentNew(void){ | |
KGStagePlayerComponent* self = calloc(1, sizeof(KGStagePlayerComponent)); | |
return self; | |
} | |
void KGStagePlayerComponentDelete(KGStagePlayerComponent* self){ | |
if(not self) return; | |
free(self); | |
} | |
typedef struct { | |
KGStagePlayerComponent* player; | |
AEVec3 start; | |
}SelectionRayCollisionHandler_userarg; | |
static bool SelectionRayCollisionHandler(KEStage* self, AEUInt32 entityID, AEVec3 hitLocation, AEVec3 hitNormal, void* userarg_uncasted){ | |
SelectionRayCollisionHandler_userarg* userarg = userarg_uncasted; | |
KGStagePlayerComponent* player = userarg->player; | |
player->heldObject = entityID; | |
player->holdDistance = AEFloatSquareRoot(AEVec3LengthSquared(AEVec3Sub(hitLocation, userarg->start))); | |
player->heldObjectOffset = AEVec3Sub(hitLocation, KEValueAsVec3(KEStageGetEntitySlot(self, entityID, KEStageEntitySlotPosition))); | |
return false; | |
} | |
static void PickUpObject(KGStagePlayerComponent* self, KEStage* stage){ | |
//KEStageEntityRayCollisionHandler | |
KECamera* camera = KEStageGetCamera(stage); | |
AEVec3 from = KECameraGetPosition(camera); | |
AEQuat rotationQuaternion = AEQuatFromEuler(KECameraGetRotation(camera)); | |
AEVec3 to = AEVec3Add(from, AEQuatMulVec3(rotationQuaternion, AEVec3From3(0, 0, -10))); | |
SelectionRayCollisionHandler_userarg userarg; | |
userarg.player = self; | |
userarg.start = from; | |
KEStageIterateEntitiesCollidingWithRay(stage, from, to, true, SelectionRayCollisionHandler, & userarg); | |
} | |
static void DropObject(KGStagePlayerComponent* self){self->heldObject = 0;} | |
static void KGStagePlayerComponentMove(KGStagePlayerComponent* self, AEUInt32 selfEntityID, KGStage* stage, AEVec3 by, AEVec3 jumpBy){ | |
if(not self->hasContactWithGround) return; | |
//puts("Sup, I be plannin' to do stuff, yo."); | |
if(by.x or by.y or by.z) { | |
//Spring-Damper System: F = -kx + -bv | |
KGStageSetEntitySlot(stage, selfEntityID, KGStageIsActivatedSlotID, KEValueFromBool(true)); | |
KGStageApplyEntityCentralForce(stage, selfEntityID, by); | |
self->hasContactWithGround = false; | |
//puts("Sup, I be movin', yo."); | |
} | |
if(jumpBy.x or jumpBy.y or jumpBy.z) { | |
KGStageSetEntitySlot(stage, selfEntityID, KGStageIsActivatedSlotID, KEValueFromBool(true)); | |
KGStageApplyEntityCentralImpulse(stage, selfEntityID, jumpBy); | |
self->hasContactWithGround = false; | |
//puts("Sup, I be jumpin', yo."); | |
} | |
} | |
KEValue KGStagePlayerComponentSendEntityMessage(KGStagePlayerComponent* self, KGStage* stage, AEUInt32 selfEntityID, KGStageMessageID messageID, const KEValue* arguments, AEUInt32 argumentCount){ | |
KEStage* engineStage = KGStageGetEngineStage(stage); | |
switch (messageID) { | |
case KGStageOnCreationMessageID: | |
self->contactDampenAmount = -500; | |
KGStageSetEntitySlot(stage, selfEntityID, KGStageCollisionCapsuleBoundsSlotID, KEValueFromVec3(AEVec3From3(1, 2.5, 1))); | |
KGStageSetEntitySlot(stage, selfEntityID, KGStageMassSlotID, KEValueFromFloat(90)); | |
KGStageSetEntitySlot(stage, selfEntityID, KGStageDeactivationTimeSlotID, KEValueFromFloat(0)); | |
KGStageSetEntitySlot(stage, selfEntityID, KGStageIsActivatedSlotID, KEValueFromBool(true)); | |
//KGStageSetEntitySlot(stage, selfEntityID, KGStageEntitySlotRespondsToCollisionMessage, KEValueFromBool(true)); | |
KEStageSetEntitySlot(KGStageGetEngineStage(stage), selfEntityID, KEStageEntitySlotRespondsToCollisionMessage, KEValueFromBool(true)); | |
KGStageSetEntitySlot(stage, selfEntityID, KGStageFrictionSlotID, KEValueFromFloat(AEInfinity)); | |
break; | |
case KGStageOnDestructionMessageID: | |
break; | |
case KGStageOnCollisionMessageID:{ | |
AEUInt32 entity2ID = KEValueAsUInt32(arguments[0]); | |
AEVec3 pointOfContact = KEValueAsVec3(arguments[1]); | |
AEVec3 normalOfContact = KEValueAsVec3(arguments[2]); | |
//puts("Sup, I hit stuff, yo."); | |
self->hasContactWithGround = true; | |
self->summedSurfaceDirection = AEVec3Add(self->summedSurfaceDirection, (normalOfContact)); | |
self->contactCount++; | |
AEVec3 linearVelocity = KEValueAsVec3(KGStageGetEntitySlot(stage, selfEntityID, KGStageLinearVelocitySlotID)); | |
KGStageApplyEntityCentralForce(stage, selfEntityID, AEVec3Mul(linearVelocity, AEVec3From1(self->contactDampenAmount))); | |
}break; | |
case KGStageOnUpdateMessageID:{ | |
//(AEFloat seconds) | |
AEFloat seconds = KEValueAsFloat(arguments[0]); | |
KECamera* camera = KGStageGetCamera(stage); | |
int mouseX, mouseY; | |
glfwGetMousePos(& mouseX, & mouseY); | |
int width, height; | |
glfwGetWindowSize(& width, & height); | |
AEVec3 turn = AEVec3From1(0); | |
turn.y = -(mouseX - (width / 2.0f)); | |
turn.x = -(mouseY - (height / 2.0f)); | |
glfwSetMousePos(width / 2.0f, height / 2.0f); | |
AEVec3 rotation = AEVec3Add(KECameraGetRotation(camera), turn); | |
if(rotation.x > 90) rotation.x = 90; | |
if(rotation.x < -90) rotation.x = -90; | |
KECameraSetRotation(camera, rotation); | |
AEVec3 move = AEVec3From1(0); | |
float speed = 4000 * 2;// * seconds;//8000 is good for running | |
float jumpSpeed = 1000; | |
move.x = (glfwGetKey('D')-glfwGetKey('A')) * speed; | |
move.z = (glfwGetKey('S')-glfwGetKey('W')) * speed; | |
AEQuat rotationQuaternion = AEQuatFromEuler(rotation); | |
move = AEQuatMulVec3(rotationQuaternion, move); | |
bool jumpKeyIsDown = glfwGetKey(' '); | |
AEVec3 jumpBy = AEVec3From1(0); | |
if(jumpKeyIsDown and not self->jumpKeyWasDown and self->contactCount) { | |
AEVec3 averageSurfaceDirection = AEVec3Mul(AEVec3Neg(self->summedSurfaceDirection), AEVec3From1(1.0f/self->contactCount)); | |
jumpBy = (AEVec3Mul(averageSurfaceDirection, AEVec3From1(jumpSpeed))); | |
} | |
self->jumpKeyWasDown = jumpKeyIsDown; | |
KGStagePlayerComponentMove(self, selfEntityID, stage, move, jumpBy); | |
AEVec3 position = KEValueAsVec3(KGStageGetEntitySlot(stage, selfEntityID, KGStagePositionSlotID)); | |
KECameraSetPosition(camera, position); | |
AEQuat playerRotationQuaternion = AEQuatFromEuler(AEVec3From3(0, rotation.y, 0)); | |
KGStageSetEntitySlot(stage, selfEntityID, KGStageRotationSlotID, KEValueFromVec4(playerRotationQuaternion)); | |
//PickUpObject | |
bool pickUpKeyIsDown = glfwGetMouseButton(0); | |
if(pickUpKeyIsDown and not self->pickUpKeyIsDown) PickUpObject(self, engineStage); | |
if(pickUpKeyIsDown) { | |
AEVec3 holdPosition = AEQuatMulVec3(rotationQuaternion, AEVec3From3(0, 0, -self->holdDistance)); | |
holdPosition = AEVec3Add(holdPosition, KECameraGetPosition(camera)); | |
if(self->heldObject) { | |
//F = -kx + -bv | |
AEVec3 heldObjectPosition = AEVec3Add(KEValueAsVec3(KGStageGetEntitySlot(stage, self->heldObject, KGStagePositionSlotID)), self->heldObjectOffset); | |
AEVec3 heldObjectLinearVelocity = KEValueAsVec3(KEStageGetEntitySlot(engineStage, self->heldObject, KGStageLinearVelocitySlotID)); | |
AEVec3 cameraLinearVelocity = KEValueAsVec3(KEStageGetEntitySlot(engineStage, selfEntityID, KEStageEntitySlotLinearVelocity)); | |
AEVec3 positionDifference = AEVec3Mul(AEVec3Sub(holdPosition, heldObjectPosition), AEVec3From1(400)); | |
AEVec3 velocityDifference = AEVec3Mul(AEVec3Sub(cameraLinearVelocity, heldObjectLinearVelocity), AEVec3From1(120)); | |
KEStageSetEntitySlot(engineStage, self->heldObject, KEStageEntitySlotIsActivated, KEValueFromBool(true)); | |
KEStageApplyEntityCentralForce(engineStage, self->heldObject, AEVec3Add(velocityDifference, positionDifference)); | |
KEStageApplyEntityCentralForce(engineStage, selfEntityID, AEVec3Add(AEVec3Neg(velocityDifference), AEVec3Neg(AEVec3Mul(positionDifference, AEVec3From1(1))))); | |
//AEVec4 heldObjectRotation = KEValueAsVec4(KEStageGetEntitySlot(stage, self->heldObject, KEStageEntitySlotRotation)); | |
AEVec3 heldObjectAngularVelocity = KEValueAsVec3(KEStageGetEntitySlot(engineStage, self->heldObject, KEStageEntitySlotAngularVelocity)); | |
//AEVec3 rotationDifference = AEVec3Mul(AEVec3Sub(AEVec3From3(0, 0, 0), heldObjectAngle), AEVec3From1(300)); | |
// AEVec3 angularVelocityDifference = AEVec3Mul(AEVec3Sub(AEVec3From3(0, 0, 0), heldObjectAngularVelocity), AEVec3From1(100)); | |
KEStageSetEntitySlot(engineStage, self->heldObject, KEStageEntitySlotAngularVelocity, KEValueFromVec3(AEVec3Mul(heldObjectAngularVelocity, AEVec3From1(1-seconds)))); | |
//KEStageSetEntitySlot(stage, self->heldObject, KEStageEntitySlotPosition, KEValueFromVec3(holdPosition)); | |
} | |
} | |
else DropObject(self); | |
self->pickUpKeyIsDown = pickUpKeyIsDown; | |
self->summedSurfaceDirection = AEVec3From3(0, -1, 0); | |
self->contactCount = 1; | |
}break; | |
default: | |
break; | |
} | |
return KEValueFromNothing(); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment