// 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(); }
// Check collisions between physic models, and apply gravity to them protected override void Update(PhysicWorldModel world) { PhysicPointModel pointModel; PhysicPointController pointController; // Get all planes to check collisions List <PhysicPlaneModel> allPlanes = GetAllPlanes(world); foreach (uint pointModelId in world.pointModels) { pointModel = StateManager.state.GetModel(pointModelId) as PhysicPointModel; if (pointModel == null) { // someone removed it in some other way!! RetroBread.Debug.LogWarning("Point model removed outside world"); continue; } pointController = pointModel.Controller() as PhysicPointController; if (pointController == null) { // not controlled, can't react to anything continue; } // apply gravity if (pointModel.isActive || PhysicPointController.IsGrounded(pointModel)) { ApplyGravityToPoint(world, pointModel, pointController); } CheckCollisionsAgainstPlanes(world, pointModel, pointController, allPlanes); } }
// ---------------------- // Ground and Wall checks public static bool IsGrounded(GameEntityModel model) { PhysicPointModel pointModel = GameEntityController.GetPointModel(model); if (pointModel == null) { return(false); } return(PhysicPointController.IsGrounded(pointModel)); }
// 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); } } }
// 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); } } }
// Grounded private static EventCondition <GameEntityModel> .EvaluationDelegate BuildGrounded(Storage.GenericParameter parameter, out int keyFrame, Storage.CharacterAnimation animation) { keyFrame = InvalidKeyframe; // Read negation bool positiveCheck = !parameter.SafeBool(0); // Return delegate return(delegate(GameEntityModel mainModel, List <GameEntityModel>[] subjectModels){ PhysicPointModel pointModel; pointModel = StateManager.state.GetModel(mainModel.physicsModelId) as PhysicPointModel; if (pointModel == null) { return false; } return PhysicPointController.IsGrounded(pointModel) == positiveCheck; }); }
// 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); }); }
// 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(); }
// 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); } }
// This will take effect on next frame only private void ApplyGravityToPoint(PhysicWorldModel world, PhysicPointModel pointModel, PhysicPointController pointController) { pointController.AddVelocityAffector(pointModel, PhysicPointModel.defaultVelocityAffectorName, world.gravity); }