private static EventAction <GameEntityModel> .ExecutionDelegate BuildAddInpulse(Storage.GenericParameter parameter) { FixedVector3 impulse = BuildFixedVector3(parameter, 0); bool asPercentage = parameter.SafeBool(0); if (asPercentage) { impulse /= 100; } return(delegate(GameEntityModel model, List <GameEntityModel>[] subjectModels){ PhysicPointModel pointModel = StateManager.state.GetModel(model.physicsModelId) as PhysicPointModel; if (pointModel == null) { return; } FixedVector3 finalImpulse = impulse; if (asPercentage) { finalImpulse = pointModel.velocityAffectors[PhysicPointModel.defaultVelocityAffectorName]; finalImpulse = new FixedVector3( finalImpulse.X * impulse.X, finalImpulse.Y * impulse.Y, finalImpulse.Z * impulse.Z ); } else { finalImpulse = impulse; } pointModel.velocityAffectors[PhysicPointModel.defaultVelocityAffectorName] += finalImpulse; }); }
// Release event may be accompained by a set animation event and set anchored position. // It safely releases at the relative position to parent, taking physics in consideration public static void ReleaseAnchoredEntity(GameEntityModel model, GameEntityModel anchoredEntityModel){ int anchorId = -1; for (int i = 0; i < model.anchoredEntities.Count ; ++i){ if (model.anchoredEntities[i] == anchoredEntityModel.Index){ anchorId = i; break; } } if (anchorId == -1){ // entity is not grabbed, return return; } anchoredEntityModel.parentEntity = new ModelReference(); PhysicPointModel pointModel = GameEntityController.GetPointModel(anchoredEntityModel); if (pointModel != null){ pointModel.isActive = true; PhysicPointModel parentPointModel = GameEntityController.GetPointModel(model); PhysicPointController pointController = pointModel.Controller() as PhysicPointController; if (pointController != null && parentPointModel != null){ // Set position directly pointModel.position = parentPointModel.position; if (!model.IsFacingRight()) anchoredEntityModel.positionRelativeToParent.X *= -1; pointController.SetVelocityAffector(pointModel, PhysicPointController.setPositionffectorName, anchoredEntityModel.positionRelativeToParent); anchoredEntityModel.positionRelativeToParent = FixedVector3.Zero; } } model.anchoredEntities[anchorId] = new ModelReference(); }
// Filter hit by hitter entity location private static GameEntityModel getHitEntityIfConformingOrientationOptions(HitInformation hit, OrientationOptions orientationOptions, GameEntityModel model) { GameEntityModel hitterModel = StateManager.state.GetModel(hit.entityId) as GameEntityModel; if (orientationOptions == OrientationOptions.any) { return(hitterModel); } PhysicPointModel modelPoint = GameEntityController.GetPointModel(model); PhysicPointModel hitterPoint = GameEntityController.GetPointModel(hitterModel); bool isFrontal; if (model.IsFacingRight()) { isFrontal = hitterPoint.position.X >= modelPoint.position.X; } else { isFrontal = hitterPoint.position.X <= modelPoint.position.X; } if (isFrontal == (orientationOptions == OrientationOptions.fromFront)) { return(hitterModel); } return(null); }
public GameEntityModel( State state, PhysicWorldModel worldModel, PhysicPointModel physicsModel, AnimationModel animationModel, Model inputModel, string controllerFactoryId, string viewFactoryId, int updatingOrder ) : base(controllerFactoryId, viewFactoryId, updatingOrder) { animationModel.ownerId = this.Index; physicsModel.ownerId = this.Index; physicsModelId = state.AddModel(physicsModel); worldModel.pointModels.Add(physicsModelId); animationModelId = state.AddModel(animationModel); if (inputModel != null) { inputModelId = state.AddModel(inputModel); } else { inputModelId = new ModelReference(ModelReference.InvalidModelIndex); } anchoredEntities = new List <ModelReference>(); ownedEntities = new List <ModelReference>(); customVariables = new Dictionary <string, int>(); mIsFacingRight = true; }
// Anchor a model to it public static void AnchorEntity(GameEntityModel model, GameEntityModel modelToBeAnchored, int anchorId){ if (IsAnchored(modelToBeAnchored)){ Debug.LogWarning("Trying to anchor an entity that is already anchored"); return; } if (model.parentEntity != null && model.parentEntity == modelToBeAnchored.Index){ Debug.LogWarning("Cyclic anchoring attempt"); return; } if (model.anchoredEntities == null) model.anchoredEntities = new List<ModelReference>(anchorId); while (model.anchoredEntities.Count <= anchorId) { model.anchoredEntities.Add(null); } if (model.anchoredEntities[anchorId] != null && model.anchoredEntities[anchorId] != ModelReference.InvalidModelIndex){ Debug.LogWarning("Trying to anchor an entity to a busy anchor"); return; } model.anchoredEntities[anchorId] = modelToBeAnchored.Index; modelToBeAnchored.parentEntity = model.Index; modelToBeAnchored.positionRelativeToParent = FixedVector3.Zero; PhysicPointModel pointModel = GameEntityController.GetPointModel(modelToBeAnchored); if (pointModel != null){ pointModel.isActive = false; } }
// Update the input velocity affector multiplying input axis and max input velocity private static void UpdateInputVelocityAffector(GameEntityModel model) { PhysicPointModel pointModel = GetPointModel(model); if (pointModel == null) { return; } FixedVector3 newInputVel = FixedVector3.Zero; if (model.maxInputVelocity.X != 0 || model.maxInputVelocity.Y != 0) { Model inputModel = GetInputProvider(model); if (inputModel == null) { return; } GameEntityInputProvider inputController = inputModel.Controller() as GameEntityInputProvider; if (inputController == null) { return; } FixedVector3 axis = inputController.GetInputAxis(inputModel); newInputVel = new FixedVector3(axis.X * model.maxInputVelocity.X, axis.Y * model.maxInputVelocity.Y, axis.Z * model.maxInputVelocity.Z); } pointModel.velocityAffectors[inputVelocityAffector] = newInputVel; }
// Find collisions between a point model and a set of world planes // For each collision found, notify point and plane controllers so that they can react to the collision private void CheckCollisionsAgainstPlanes(PhysicWorldModel world, PhysicPointModel pointModel, PhysicPointController pointController, List <PhysicPlaneModel> planes) { PhysicPlaneController planeController; FixedVector3 intersection; // Do a few iterations until collisions get stable, or we reach a limit on iterations bool collisionsAreStable = false; for (int i = 0; i < collisionIterationsCount && !collisionsAreStable; ++i) { collisionsAreStable = true; int numCollisions = 0; foreach (PhysicPlaneModel planeModel in planes) { if (PhysicPlaneController.CheckIntersection(planeModel, pointModel, out intersection)) { ++numCollisions; collisionsAreStable &= pointController.OnCollision(world, pointModel, planeModel, intersection); planeController = planeModel.Controller() as PhysicPlaneController; collisionsAreStable &= planeController == null || planeController.OnCollision(world, pointModel, planeModel, intersection); } } //Debug.Log("Collisions: " + numCollisions); } }
// Compute the intersection point against a line segment public static bool CheckIntersection(PhysicPlaneModel planeModel, PhysicPointModel pointModel, out FixedVector3 intersection) { // plane may be moving, sum velocity to initial point position FixedVector3 pos1 = pointModel.lastPosition; FixedVector3 pos2 = pointModel.position; pos1 += planeModel.GetVelocity(); return(CheckIntersection(planeModel, pos1, pos2, pointModel.stepTolerance, out intersection)); }
// Apply a force on the physics velocity affector public static FixedFloat GetVerticalImpulse(GameEntityModel model) { PhysicPointModel pointModel = GameEntityController.GetPointModel(model); if (pointModel == null) { return(FixedFloat.Zero); } return(pointModel.velocityAffectors[PhysicPointModel.defaultVelocityAffectorName].Y); }
public static bool IsHittingFarWall(GameEntityModel model) { PhysicPointModel pointModel = GameEntityController.GetPointModel(model); if (pointModel == null) { return(false); } return(pointModel.collisionInpact.Z > 0); }
public static FixedFloat CollisionZForce(GameEntityModel model) { PhysicPointModel pointModel = GameEntityController.GetPointModel(model); if (pointModel == null) { return(FixedFloat.Zero); } return(FixedFloat.Abs(pointModel.collisionInpact.Z)); }
// ---------------------- // Ground and Wall checks public static bool IsGrounded(GameEntityModel model) { PhysicPointModel pointModel = GameEntityController.GetPointModel(model); if (pointModel == null) { return(false); } return(PhysicPointController.IsGrounded(pointModel)); }
// Safelly set position relative to self (e.g. vault), taking physics collisions in consideration public static void MoveEntity(GameEntityModel model, FixedVector3 relativePosition) { PhysicPointModel pointModel = GameEntityController.GetPointModel(model); if (pointModel != null) { PhysicPointController pointController = pointModel.Controller() as PhysicPointController; if (pointController != null) { pointController.SetVelocityAffector(pointModel, PhysicPointController.setPositionffectorName, relativePosition); } } }
// Anchor a model to it, and optionally move the parent relative to the entity being anchored (e.g. move back a little when grabbing) public static void AnchorEntity(GameEntityModel model, GameEntityModel modelToBeAnchored, int anchorId, FixedVector3 deltaPosRelativeToAnched){ AnchorEntity(model, modelToBeAnchored, anchorId); PhysicPointModel pointModel = GameEntityController.GetPointModel(model); PhysicPointModel anchoredPointModel = GameEntityController.GetPointModel(modelToBeAnchored); if (pointModel != null && anchoredPointModel != null){ PhysicPointController pointController = pointModel.Controller() as PhysicPointController; if (pointController != null){ if (!model.IsFacingRight()) deltaPosRelativeToAnched.X *= -1; FixedVector3 deltaPos = (anchoredPointModel.position + deltaPosRelativeToAnched) - pointModel.position; pointController.SetVelocityAffector(pointModel, PhysicPointController.setPositionffectorName, deltaPos); } } }
// Set the velocity affector bound to animation velocity control public static void SetAnimationVelocity(GameEntityModel model, FixedVector3 velocity) { PhysicPointModel pointModel = GameEntityController.GetPointModel(model); if (pointModel == null) { return; } if (!model.IsFacingRight()) { velocity.X *= -1; } pointModel.velocityAffectors[GameEntityController.animVelocityAffector] = velocity; }
protected override void PostUpdate(GameEntityModel model) { if (nextPauseTimer > 0) { // Pause physics and animation PhysicPointModel pointModel = GetPointModel(model); if (pointModel != null) { pointModel.isActive = false; model.pauseTimer = nextPauseTimer; } nextPauseTimer = 0; } }
// Reset X and Z force components on the physics velocity affector public static void ResetPlanarImpulse(GameEntityModel model) { PhysicPointModel pointModel = GameEntityController.GetPointModel(model); if (pointModel == null) { return; } FixedVector3 originalImpulse; pointModel.velocityAffectors.TryGetValue(PhysicPointModel.defaultVelocityAffectorName, out originalImpulse); pointModel.velocityAffectors[PhysicPointModel.defaultVelocityAffectorName] = new FixedVector3(0, originalImpulse.Y, 0) ; }
// Apply a force on the physics velocity affector public static void AddImpulse(GameEntityModel model, FixedVector3 impulse) { PhysicPointModel pointModel = GameEntityController.GetPointModel(model); if (pointModel == null) { return; } if (!model.IsFacingRight()) { impulse.X *= -1; } pointModel.velocityAffectors[PhysicPointModel.defaultVelocityAffectorName] += impulse; // pointModel.velocityAffectors[PhysicPointModel.defaultVelocityAffectorName] += new FixedVector3(0, impulse.Y, 0); // pointModel.velocityAffectors[GameEntityController.animVelocityAffector] += new FixedVector3(impulse.X, 0, impulse.Z); }
// If automatic flip is on, flip automatically if input velocity is going against entity direction private static void CheckAutomaticFlip(GameEntityModel model) { if (model.automaticFlip) { PhysicPointModel pointModel = GetPointModel(model); if (pointModel == null) { return; } FixedVector3 inputVelocity = pointModel.velocityAffectors[inputVelocityAffector]; if (inputVelocity.X != 0 && (inputVelocity.X > 0 != model.IsFacingRight())) { Flip(model); } } }
// Face to same direction as hitter is facing public static void FaceToHitterDirection(GameEntityModel model, bool oppositeFacing) { GameEntityController controller = model.Controller() as GameEntityController; PhysicPointModel pointModel = GameEntityController.GetPointModel(model); if (pointModel != null && controller.lastHurts.Count > 0) { HitInformation info = controller.lastHurts[0]; GameEntityModel hitter = StateManager.state.GetModel(info.entityId) as GameEntityModel; model.mIsFacingRight = hitter.IsFacingRight(); if (oppositeFacing) { model.mIsFacingRight = !model.IsFacingRight(); } } }
// Get Position used in collision checks public static FixedVector3 GetRealPosition(GameEntityModel model) { if (model.parentEntity == null || model.parentEntity == ModelReference.InvalidModelIndex) { // Normal position PhysicPointModel pointModel = StateManager.state.GetModel(model.physicsModelId) as PhysicPointModel; return(pointModel.position); } else { // Anchored, use parent position GameEntityModel parentModel = StateManager.state.GetModel(model.parentEntity) as GameEntityModel; FixedVector3 parentPosition = GetRealPosition(parentModel); return(parentPosition + new FixedVector3((parentModel.IsFacingRight() ? 1 : -1) * model.positionRelativeToParent.X, model.positionRelativeToParent.Y, model.positionRelativeToParent.Z)); } }
// pos(2.1, 4.2, 5.3) private static EventAction <GameEntityModel> .ExecutionDelegate BuildSetDeltaPosition(Storage.GenericParameter parameter) { int relativeSubjectId = parameter.SafeInt(1); FixedVector3 deltaPos = BuildFixedVector3(parameter, 0); return(delegate(GameEntityModel model, List <GameEntityModel>[] subjectModels){ List <GameEntityModel> refSubjects = ConditionUtils <GameEntityModel> .GetNonEmptySubjectOrNil(subjectModels, relativeSubjectId); if (refSubjects == null || refSubjects.Count == 0) { return; } // Select one randomly GameEntityModel refModel = refSubjects[StateManager.state.Random.NextInt(0, refSubjects.Count - 1)]; FixedVector3 realDelta; if (!refModel.IsFacingRight()) { deltaPos.X *= -1; } PhysicPointModel mainPoint = StateManager.state.GetModel(model.physicsModelId) as PhysicPointModel; if (mainPoint == null) { return; } if (refModel != model) { PhysicPointModel refPoint = StateManager.state.GetModel(refModel.physicsModelId) as PhysicPointModel; if (refPoint == null) { return; } realDelta = (refPoint.position + deltaPos) - mainPoint.position; } else { realDelta = deltaPos; } PhysicPointController pointController = mainPoint.Controller() as PhysicPointController; if (pointController == null) { return; } pointController.SetVelocityAffector(mainPoint, PhysicPointController.setPositionffectorName, realDelta); }); }
// Delegate for when a point is removed, it redirects to the caller delegate private void OnPointRemoved(Model model, object context) { Eppy.Tuple <OnPointModelChanged, object> callbackTuple; PhysicPointModel pointModel = model as PhysicPointModel; PhysicWorldModel worldModel = context as PhysicWorldModel; if (pointModel == null || worldModel == null) { // Something went wrong! return; } if (removePointCallbacks.TryGetValue(pointModel, out callbackTuple)) { if (callbackTuple.Item1 != null) { callbackTuple.Item1(pointModel, callbackTuple.Item2); } removePointCallbacks.Remove(pointModel); worldModel.pointModels.Remove(model.Index); } }
// Update automated stuff protected override void Update(GameEntityModel model) { // first update the input velocity UpdateInputVelocityAffector(model); // if input velocity goes against current direction, flip CheckAutomaticFlip(model); // Built in pause timer if (model.pauseTimer > 0) { PhysicPointModel pointModel = GetPointModel(model); if (pointModel != null) { if (--model.pauseTimer == 0 && (model.parentEntity == null || model.parentEntity == ModelReference.InvalidModelIndex)) { pointModel.isActive = true; } } } }
// Release event may be accompained by a set animation event and set anchored position. // It safely releases at the relative position to parent, taking physics in consideration public static void ReleaseAnchoredEntity(GameEntityModel model, int anchorId){ if (model.anchoredEntities == null || model.anchoredEntities.Count <= anchorId) return; GameEntityModel anchoredEntityModel = StateManager.state.GetModel(model.anchoredEntities[anchorId]) as GameEntityModel; if (anchoredEntityModel != null){ anchoredEntityModel.parentEntity = new ModelReference(); PhysicPointModel pointModel = GameEntityController.GetPointModel(anchoredEntityModel); if (pointModel != null){ pointModel.isActive = true; PhysicPointModel parentPointModel = GameEntityController.GetPointModel(model); PhysicPointController pointController = pointModel.Controller() as PhysicPointController; if (pointController != null && parentPointModel != null){ // Set position directly pointModel.position = parentPointModel.position; if (!model.IsFacingRight()) anchoredEntityModel.positionRelativeToParent.X *= -1; pointController.SetVelocityAffector(pointModel, PhysicPointController.setPositionffectorName, anchoredEntityModel.positionRelativeToParent); anchoredEntityModel.positionRelativeToParent = FixedVector3.Zero; } } } model.anchoredEntities[anchorId] = new ModelReference(); }
// Velocity private static EventCondition <GameEntityModel> .EvaluationDelegate BuildVelocity(Storage.GenericParameter parameter, out int keyFrame, Storage.CharacterAnimation animation) { keyFrame = InvalidKeyframe; // Read orientation, operator, numerator subject, numerator var, number, module Orientation orientation = (Orientation)parameter.SafeInt(1); ConditionUtils <GameEntityModel> .ComparisonOperation comparisonOperator = (ConditionUtils <GameEntityModel> .ComparisonOperation)parameter.SafeInt(2); int numeratorSubjectId = parameter.SafeInt(3); string numeratorSubjectVarName = parameter.SafeString(0); FixedFloat staticComparisonValue = parameter.SafeFloat(0); bool useModule = parameter.SafeBool(1); // return delegate return(delegate(GameEntityModel mainModel, List <GameEntityModel>[] subjectModels){ PhysicPointModel pointModel = StateManager.state.GetModel(mainModel.physicsModelId) as PhysicPointModel; if (pointModel == null) { return false; } FixedFloat velocityValue = getOrientedAxisValue(pointModel.GetVelocity(), orientation, useModule); return CompareWithNumerator(mainModel, numeratorSubjectId, numeratorSubjectVarName, velocityValue, staticComparisonValue, comparisonOperator, subjectModels); }); }
public static bool IsHurtFrontal(GameEntityModel model, bool frontal) { GameEntityController controller = model.Controller() as GameEntityController; if (controller.lastHurts.Count == 0) { return(false); } GameEntityModel hitter = StateManager.state.GetModel(controller.lastHurts[0].entityId) as GameEntityModel; PhysicPointModel modelPoint = GameEntityController.GetPointModel(model); PhysicPointModel hitterPoint = GameEntityController.GetPointModel(hitter); bool isFrontal; if (model.IsFacingRight()) { isFrontal = hitterPoint.position.X >= modelPoint.position.X; } else { isFrontal = hitterPoint.position.X <= modelPoint.position.X; } return(isFrontal == frontal); }
private static EventAction <GameEntityModel> .ExecutionDelegate BuildSetVelocity(Storage.GenericParameter parameter) { int mask = parameter.SafeInt(1); FixedVector3 velocity = BuildFixedVector3(parameter, 0); bool hasX = mask == 0 || mask == 3 || mask == 4 || mask == 6; bool hasY = mask == 1 || mask == 3 || mask == 5 || mask == 6; bool hasZ = mask == 2 || mask == 4 || mask == 5 || mask == 6; return(delegate(GameEntityModel model, List <GameEntityModel>[] subjectModels){ PhysicPointModel pointModel = StateManager.state.GetModel(model.physicsModelId) as PhysicPointModel; if (pointModel == null) { return; } FixedVector3 originalVelocity = pointModel.GetVelocity(); FixedVector3 finalVelocity = new FixedVector3( hasX ? velocity.X : originalVelocity.X, hasY ? velocity.Y : originalVelocity.Y, hasZ ? velocity.Z : originalVelocity.Z ); pointModel.velocityAffectors[GameEntityController.animVelocityAffector] = finalVelocity; }); }
// Remove a Physic Point from the world public void RemovePoint(PhysicWorldModel world, PhysicPointModel pointModel, OnPointModelChanged callback = null, object context = null) { removePointCallbacks[pointModel] = new Eppy.Tuple <OnPointModelChanged, object>(callback, context); StateManager.state.RemoveModel(pointModel, OnPointRemoved, world); }
// This will take effect on next frame only private void ApplyGravityToPoint(PhysicWorldModel world, PhysicPointModel pointModel, PhysicPointController pointController) { pointController.AddVelocityAffector(pointModel, PhysicPointModel.defaultVelocityAffectorName, world.gravity); }