Skip to content

Instantly share code, notes, and snippets.

@od0x0
Created June 11, 2012 01:59
Show Gist options
  • Save od0x0/2908087 to your computer and use it in GitHub Desktop.
Save od0x0/2908087 to your computer and use it in GitHub Desktop.
#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);
#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