// Create a default Game Entity model public GameEntityModel( State state, string characterName, string animationName, string viewModelName, PhysicWorldModel worldModel, Model inputModel, FixedVector3 position, FixedVector3 stepTolerance, string controllerFactoryId, string viewFactoryId, int updatingOrder ) : base(controllerFactoryId, viewFactoryId, updatingOrder) { physicsModelId = state.AddModel(new PhysicPointModel(this.Index, position, stepTolerance)); worldModel.pointModels.Add(physicsModelId); animationModelId = state.AddModel(new AnimationModel(this.Index, characterName, animationName, viewModelName)); 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; // default face objects to the right }
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; }
// Natural reaction: slide along the plane protected bool CollisionNaturalReaction(PhysicWorldModel world, PhysicPointModel pointModel, PhysicPlaneModel planeModel, FixedVector3 intersection) { bool intersectionChanged = false; if (pointModel.position != intersection) { // Project remaining velocity against the plane FixedVector3 normal = planeModel.normal; FixedVector3 pos1 = pointModel.position; FixedVector3 pos2 = pointModel.position + normal; FixedVector3 pointDeltaPos = pos2 - pos1; FixedVector3 pos1ToOrigin = planeModel.origin - pos1; FixedFloat dotDeltaPosNormal = FixedVector3.Dot(pointDeltaPos, normal); FixedFloat t = FixedVector3.Dot(pos1ToOrigin, normal) / dotDeltaPosNormal; FixedVector3 newIntersection = pos1 + t * pointDeltaPos; if (newIntersection != intersection) { intersection = newIntersection; intersectionChanged = true; } // finally, our new position is the intersection point pointModel.position = intersection; } // in the end, also sum the plane velocity, essential for platforms GainPlaneVelocity(world, pointModel, planeModel); return(!intersectionChanged); // if intersection didn't change, it's considered stable }
// Note: objects over elevators may behave in a weird way if gravity isn't enough to keep them grounded // with increased gravity or slower elevators everything seems smoother protected void KillGravityEffectAgainstPlane(PhysicWorldModel world, PhysicPointModel pointModel, PhysicPlaneModel planeModel) { FixedVector3 normal = planeModel.normal; FixedVector3 defaultVel = pointModel.GetDefaultVelocityAffector(); //FixedVector3 velToAdd = FixedVector3.Zero; if ((world.gravity.X < 0 && defaultVel.X < world.gravity.X && normal.X > 0) || (world.gravity.X > 0 && defaultVel.X > world.gravity.X && normal.X < 0)) { defaultVel.X = world.gravity.X; //velToAdd.X = world.gravity.X - defaultVel.X; } if ((world.gravity.Y < 0 && defaultVel.Y < world.gravity.X && normal.Y > 0) || (world.gravity.Y > 0 && defaultVel.Y > world.gravity.Y && normal.Y < 0)) { defaultVel.Y = world.gravity.Y; //velToAdd.Y = world.gravity.Y - defaultVel.Y; } if ((world.gravity.Z < 0 && defaultVel.Z < world.gravity.Z && normal.Z > 0) || (world.gravity.Z > 0 && defaultVel.Z > world.gravity.Z && normal.Z < 0)) { defaultVel.Z = world.gravity.Z; //velToAdd.Z = world.gravity.Z - defaultVel.Z; } //UnityEngine.Debug.Log("Setting default velocity affector: " + defaultVel); pointModel.velocityAffectors[PhysicPointModel.defaultVelocityAffectorName] = defaultVel; //SetDefaultVelocityAffector(defaultVel); //AddDefaultVelocityAffector(velToAdd); }
// Collision reaction. // Return true if collision is considered stable (no position modifications occured) public virtual bool OnCollision(PhysicWorldModel world, PhysicPointModel pointModel, PhysicPlaneModel planeModel, FixedVector3 intersection) { // if (pointModel.position == intersection){ // // Nothing to change // return true; // } // Pick one of two methods depending on the plane's normal angle against up vector FixedFloat planeAngle = FixedVector3.Angle(planeModel.normal, FixedVector3.Up); // If it's too much inclined, use natural reaction if (planeAngle > FixedFloat.PI * 0.4) { // check direction against 4 walls FixedFloat maxDelta = FixedFloat.PI * 0.4; planeAngle = FixedVector3.Angle(planeModel.normal, FixedVector3.Left); if (planeAngle <= maxDelta || planeAngle >= FixedFloat.PI - maxDelta) { // collision in the X axis FixedFloat inpactX = pointModel.GetVelocity().X - planeModel.GetVelocity().X; if (FixedFloat.Abs(inpactX) > FixedFloat.Abs(newCollisionInpact.X)) { newCollisionInpact.X = inpactX; } } planeAngle = FixedVector3.Angle(planeModel.normal, FixedVector3.Forward); if (planeAngle <= maxDelta || planeAngle >= FixedFloat.PI - maxDelta) { // collision in the Z axis FixedFloat inpactZ = pointModel.GetVelocity().Z - planeModel.GetVelocity().Z; if (FixedFloat.Abs(inpactZ) > FixedFloat.Abs(newCollisionInpact.Z)) { newCollisionInpact.Z = inpactZ; } } return(CollisionNaturalReaction(world, pointModel, planeModel, intersection)); } else { // Otherwise we're hitting the ground, do not slide FixedFloat inpactY = pointModel.GetVelocity().Y - planeModel.GetVelocity().Y; if (FixedFloat.Abs(inpactY) > FixedFloat.Abs(newCollisionInpact.Y)) { newCollisionInpact.Y = inpactY; } // We use a lot of arguments here just to avoid recalculating them return(CollisionGroundReaction(world, pointModel, planeModel, intersection)); } }
protected void GainPlaneVelocity(PhysicWorldModel world, PhysicPointModel pointModel, PhysicPlaneModel planeModel) { FixedVector3 velocityToAdd = planeModel.GetVelocity(); // Only add velocity that doesn't conflict with gravity, otherwise it starts flickering if (velocityToAdd.X > 0 && world.gravity.X < 0 || velocityToAdd.X < 0 && world.gravity.X > 0) { velocityToAdd.X = 0; } if (velocityToAdd.Y > 0 && world.gravity.Y < 0 || velocityToAdd.Y < 0 && world.gravity.Y > 0) { velocityToAdd.Y = 0; } if (velocityToAdd.Z > 0 && world.gravity.Z < 0 || velocityToAdd.Z < 0 && world.gravity.Z > 0) { velocityToAdd.Z = 0; } AddVelocityAffector(pointModel, collisionVelocityAffectorName, velocityToAdd); }
public GameEntityModel( State state, string characterName, string animationName, string viewModelName, PhysicWorldModel worldModel, Model inputModel, FixedVector3 position, FixedVector3 stepTolerance ) : this(state, characterName, animationName, viewModelName, worldModel, inputModel, position, stepTolerance, DefaultVCFactoryIds.GameEntityControllerFactoryId, DefaultVCFactoryIds.GameEntityViewFactoryId, DefaultUpdateOrder.EntitiesUpdateOrder ) { }
// Collision reaction, return true if collision is considered stable (no position modifications occured) public virtual bool OnCollision(PhysicWorldModel world, PhysicPointModel pointModel, PhysicPlaneModel planeModel, FixedVector3 intersection) { // Nothing by default return(true); }