public static void Control(PhysicsValues physicsValues, GameDuration elapsedDuration, Entity entity) { // initialize Behavior stores if necessary if (!_activeBehavior.ContainsKey(entity)) { Behavior defaultBehavior = InitializeBehaviors(entity); _activeBehavior.Add(entity, defaultBehavior); } Behavior current = _activeBehavior[entity]; // update the duration the active Behavior has been running current.AddToActiveDuration(elapsedDuration); // store all relevant data in BehaviorContext var context = new BehaviorContext(physicsValues, elapsedDuration); // if the minimum running duration of the current Behavior has passed, look for another applicable Behavior if (current.ActiveDuration > current.MinimumDuration()) { foreach (Behavior b in _possibleBehaviors[entity]) { // we only look for *other* Behaviors if (current.Equals(b)) { continue; } // determine the other Behavior's current priority var otherPrio = b.DeterminePriority(context); // only consider other Behavior if it's applicable if (otherPrio == BehaviorPriority.NA) { continue; } // switch to other Behavior depending on relation between priorities var currentPrio = current.DeterminePriority(context); if (otherPrio / (currentPrio + otherPrio) > Rng.NextDouble()) { // reset the current Behavior, as it might become active again later current.Reset(); // change active Behavior to new one _activeBehavior[entity] = b; current = b; ////Console.WriteLine("Entity {0} switched to behavior {1}", entity, b); } } } // let the active Behavior control the entity var position = entity.Get <PositionComponent>(); current.Behave(context, position); entity.Set(position); }
private void SetNewPlayerPosition() { Vector2 oldPosition = GetLevelProgression().CurrentPlayerPosition; Vector2 newPosition = gamePhysics.DoPlayerPhysics(oldPosition); if (!LevelAnalysis.IsVectorOnGround(levelAttempt.Level, newPosition)) { bool isPlayerStanding = GetLevelProgression().IsPlayerStanding; Ground groundCollidedWith = collisions.GetPlayerGroundCollision(newPosition, isPlayerStanding); if (groundCollidedWith != null) { Vector2 rightFoot = PhysicsValues.GetRightFootPosition(newPosition); float deltaX = Math.Abs(rightFoot.X - groundCollidedWith.LeftX); float deltaY = Math.Abs(groundCollidedWith.TopY - rightFoot.Y); if (deltaY > deltaX) { AddPlayerFail(); } newPosition = new Vector2(newPosition.X, groundCollidedWith.TopY); gamePhysics.ResetVerticalVelocity(); } } GetLevelProgression().CurrentPlayerPosition = newPosition; }
public static float GetChasmYDifference(float hangTime) { int iterations = (int)Math.Round(hangTime * GeneralValues.FPS); float jumpDistance = iterations * PhysicsValues.GetJumpAcceleration(); float gravityDistance = (iterations * (iterations + 1)) / 2 * PhysicsValues.GetGravityAccelerationPerFrame(); return(jumpDistance - gravityDistance); }
public Vector2 GetProjectilePosition(float time, float groundY) { float hitXPosition = GetPlayerRightEdgeXByTime(time); float startingXPosition = GeneralValues.MusicStartPositionX + hitXPosition + time * PhysicsValues.GetProjectileVelocity() + (PhysicsValues.ProjectileHitboxWidth / 2.0f); float startingYPosition = groundY + LevelGenerationValues.GetProjectileYOffset(); return(new Vector2(startingXPosition, startingYPosition)); }
private static void SetPositionFromCollisionPosition(PhysicsValues physicsValues, World world, PositionData positionData) { if (positionData.IsFalling) { positionData.Placement.Pos = positionData.InternalPos; return; } var entityPos = positionData.InternalPos; var blockPos = (BlockPos)entityPos; /* * When standing on an edge, the entities bottom center might be hanging in the air. * Find the true floor position by iterating downward and looking for the floor. */ if (world[blockPos] == 0 && world[blockPos - BlockOffset.UnitY] == 0) { blockPos -= BlockOffset.UnitY; entityPos -= EntityOffset.UnitY; if (world[blockPos - new BlockOffset(0, 2, 0)] == 0) { blockPos -= BlockOffset.UnitY; entityPos -= EntityOffset.UnitY; } } var entityOffset = entityPos - blockPos; double yOffset = 0; /* * Take the integral of all floor heights in a 2 by 2 area around the center. * Since the height is piecewise constant, this is a weighted sum of the heights around the entity position. */ yOffset += (1 - entityOffset.X) * FindHeight(world, blockPos - BlockOffset.UnitX); yOffset += entityOffset.X * FindHeight(world, blockPos + BlockOffset.UnitX); yOffset += (1 - entityOffset.Z) * FindHeight(world, blockPos - BlockOffset.UnitZ); yOffset += entityOffset.Z * FindHeight(world, blockPos + BlockOffset.UnitZ); yOffset += (1 - entityOffset.X) * (1 - entityOffset.Z) * FindHeight(world, blockPos + new BlockOffset(-1, 0, -1)); yOffset += (1 - entityOffset.X) * entityOffset.Z * FindHeight(world, blockPos + new BlockOffset(-1, 0, 1)); yOffset += entityOffset.X * (1 - entityOffset.Z) * FindHeight(world, blockPos + new BlockOffset(1, 0, -1)); yOffset += entityOffset.X * entityOffset.Z * FindHeight(world, blockPos + new BlockOffset(1, 0, 1)); // Normalize. yOffset *= 0.25; entityPos += new EntityOffset(0, yOffset, 0); positionData.Placement.Pos = entityPos; }
public Obstacle CreateJumpObstacle(LevelElementPlacement placement, float groundY) { float centerOfObstacle = GetXPositionByTime(placement.SynchroStartTime) + PhysicsValues.GetPlainJumpLength() / 2.0f; float halfObstacleWidth = LevelGenerationValues.GetJumpObstacleWidth() / 2.0f; float leftX = centerOfObstacle - halfObstacleWidth; float rightX = centerOfObstacle + halfObstacleWidth; float topY = groundY + LevelGenerationValues.GetJumpObstacleHeight(); return(new Obstacle(new Vector2(leftX, topY), new Vector2(rightX, groundY))); }
private static bool MoveY(PhysicsValues physicsValues, World world, PositionComponent positionData, double distance) { EntityPos position = positionData.InternalPos; long p = position.Y; int cx0 = GetBlockCoordinate(position.X - (long)(0.5 * physicsValues.PlayerWidth * (1L << 32)) + 1); int cx1 = GetBlockCoordinate(position.X + (long)(0.5 * physicsValues.PlayerWidth * (1L << 32)) - 1); int cz0 = GetBlockCoordinate(position.Z - (long)(0.5 * physicsValues.PlayerWidth * (1L << 32)) + 1); int cz1 = GetBlockCoordinate(position.Z + (long)(0.5 * physicsValues.PlayerWidth * (1L << 32)) - 1); bool hasCollided = MoveInternal(p, distance > 0 ? physicsValues.PlayerHeight : 0, distance, cy => AllPassable(world, new BlockPos(cx0, cy, cz0), new BlockPos(cx1, cy, cz1)), out p); position.Y = p; positionData.InternalPos = position; return(hasCollided); }
private static bool MoveZ(PhysicsValues physicsValues, World world, PositionData positionData, double distance) { EntityPos position = positionData.InternalPos; long p = position.Z; int cx0 = GetBlockCoordinate(position.X - (long)(0.5 * physicsValues.PlayerWidth * (1L << 32)) + 1); int cx1 = GetBlockCoordinate(position.X + (long)(0.5 * physicsValues.PlayerWidth * (1L << 32)) - 1); int cy0 = GetBlockCoordinate(position.Y + 1); int cy1 = GetBlockCoordinate(position.Y + (long)(physicsValues.PlayerHeight * (1L << 32)) - 1); bool hasCollided = MoveInternal(p, physicsValues.PlayerWidth * 0.5, distance, cz => AllPassable(world, new BlockPos(cx0, cy0, cz), new BlockPos(cx1, cy1, cz)), out p); position.Z = p; positionData.InternalPos = position; return(hasCollided); }
private void DeflectProjectile(Projectile projectile) { float yVelocity = MyMath.GetRandomNumber() * PhysicsValues.ProjectileMaximumYVelocity; if (MyMath.GetRandomNumber() > 0.5f) { yVelocity *= -1; } float xVelocity = (float)Math.Sqrt(Math.Pow(PhysicsValues.GetProjectileVelocity() * 3, 2) - Math.Pow(yVelocity, 2)); Vector2 deflectionDirection = new Vector2(xVelocity, yVelocity); GetLevelProgression().DeflectProjectile(projectile, deflectionDirection); }
private void SetNewProjectilePositions() { LevelProgression levelProgression = GetLevelProgression(); foreach (Projectile projectile in levelAttempt.Level.Projectiles) { Vector2 movementDelta; if (levelProgression.IsProjectileDeflected(projectile)) { movementDelta = levelProgression.GetProjectileDeflectionDirection(projectile) / GeneralValues.FPS; } else { movementDelta = new Vector2(-PhysicsValues.GetProjectileVelocityPerFrame(), 0); } levelProgression.MoveProjectile(projectile, movementDelta); } }
public static float GetJumpObstacleWidth() { float minimumHorizontalDistanceRequired = 0; for (float time = 0; time < 100; time += 1.0f / GeneralValues.FPS) { if (GetYDifferenceAfterJump(time) > GetJumpObstacleHeight()) { minimumHorizontalDistanceRequired = time * PhysicsValues.GetHorizontalPlayerVelocity(); break; } } float halfJumpObstacleWidth = PhysicsValues.GetPlainJumpLength() / 2.0f; halfJumpObstacleWidth -= MaximumJumpObstacleJumpTimingOffset * PhysicsValues.GetHorizontalPlayerVelocity(); halfJumpObstacleWidth -= minimumHorizontalDistanceRequired; halfJumpObstacleWidth -= PhysicsValues.GetHalfPlayerHitboxWidth(); return(halfJumpObstacleWidth * 2 * GeneralValues.DifficultyFactor); }
public void HandleGameEvent(GameEvent gameEvent) { if (gameEvent == null) { return; } if (gameEvent.IsDisconnected) { return; } if (gameEvent.EntityInfos != null) { EntityInfos = gameEvent.EntityInfos; } if (gameEvent.PhysicsValues != null) { PhysicsValues = gameEvent.PhysicsValues; } if (gameEvent.ChunkDataList != null) { foreach (var chunkData in gameEvent.ChunkDataList) { World.PasteChunkData(chunkData); } } if (gameEvent.BlockUpdates != null) { foreach (var blockUpdate in gameEvent.BlockUpdates) { World[blockUpdate.Pos] = blockUpdate.Material; } } }
public static float GetPlainJumpDuration() { return(PhysicsValues.GetPlainJumpDuration()); }
public BehaviorContext(PhysicsValues physicsValues, GameDuration elapsedDuration) { PhysicsValues = physicsValues; ElapsedDuration = elapsedDuration; }
public BehaviorContext(PhysicsValues physicsValues, GameDuration elapsedDuration, IEnumerable <Entity> otherEntities) { PhysicsValues = physicsValues; ElapsedDuration = elapsedDuration; OtherEntities = otherEntities; }
public static void MoveEntity(PhysicsValues physicsValues, World world, PositionData positionData, GameDuration elapsedDuration, EntityOffset offset) { offset.Y -= 0.5 * elapsedDuration.Seconds * physicsValues.Gravity; if (MoveY(physicsValues, world, positionData, offset.Y * elapsedDuration.Seconds)) { positionData.IsFalling = false; } else { if (!positionData.IsFalling) { /* Re-evaluate the fall from the apparent position. */ positionData.InternalPos = positionData.Placement.Pos; MoveY(physicsValues, world, positionData, offset.Y * elapsedDuration.Seconds); positionData.IsFalling = true; } } if (positionData.IsFalling) { offset.Y -= 0.5 * elapsedDuration.Seconds * physicsValues.Gravity; } else { if (Math.Abs(offset.Y) > Math.Sqrt(2 * physicsValues.Gravity * physicsValues.TerminalHeight)) { Respawn(positionData); } offset.Y = 0; } if (offset.X != 0 || offset.Z != 0) { long savedY = positionData.InternalPos.Y; if (!positionData.IsFalling && world[(BlockPos)positionData.InternalPos - BlockOffset.UnitY] != 0) { // Temporarily move the character up a block so that it can climb up stairs. MoveY(physicsValues, world, positionData, 1); } EntityPos positionBeforeMovement = positionData.InternalPos; double moveX = offset.X * elapsedDuration.Seconds; double moveZ = offset.Z * elapsedDuration.Seconds; if (offset.X > offset.Z) { MoveX(physicsValues, world, positionData, moveX); MoveZ(physicsValues, world, positionData, moveZ); } else { MoveZ(physicsValues, world, positionData, moveZ); MoveX(physicsValues, world, positionData, moveX); } var moveDelta = positionData.InternalPos - positionBeforeMovement; moveX -= moveDelta.X; moveZ -= moveDelta.Z; if (!positionData.IsFalling) { // Attempt to move the character back down to the ground in case we didn't climb a stair. MoveY(physicsValues, world, positionData, (savedY - positionData.InternalPos.Y) / (double)(1L << 32)); savedY = positionData.InternalPos.Y; // Attempt to move the caracter down an additional block so that it can walk down stairs. if (!MoveY(physicsValues, world, positionData, -((1L << 32) + 1) / (double)(1L << 32))) { positionData.InternalPos.Y = savedY; positionData.IsFalling = true; } } // Attempt to continue movement at this new (lower) Y position. if (offset.X > offset.Z) { if (MoveX(physicsValues, world, positionData, moveX)) { offset.X = 0; } if (MoveZ(physicsValues, world, positionData, moveZ)) { offset.Z = 0; } } else { if (MoveZ(physicsValues, world, positionData, moveZ)) { offset.Z = 0; } if (MoveX(physicsValues, world, positionData, moveX)) { offset.X = 0; } } } positionData.Velocity = offset; SetPositionFromCollisionPosition(physicsValues, world, positionData); }
public static float GetHighCollectibleYOffset() { return(PhysicsValues.GetPlainJumpHeight() + PhysicsValues.PlayerHitboxHeight * 0.8f); }
public static float GetPlayerVelocity() { return(PhysicsValues.GetHorizontalPlayerVelocity()); }
private float GetPlayerRightEdgeXByTime(float time) { return(GetXPositionByTime(time) + PhysicsValues.GetHalfPlayerHitboxWidth()); }