コード例 #1
0
ファイル: MatchTest.cs プロジェクト: DrPandemic/EraParadox
        public void TestStateClone()
        {
			MatchState state = new MatchState(new PhysicsEngine(new GameWorld(null)));

			IEntity e = new IEntity(IDGenerator.GenerateID(), new Vec2(100f, -99f), 1f, 1f, 1f);
			state.AddEntity(e);

			Assert.True(state.ContainsEntity(e.ID), "entity1 added to match");

			IEntity e2 = new IEntity(IDGenerator.GenerateID(), new Vec2(42f, 24f), 1f, 1f, 1f);
			state.AddEntity(e2);

			Assert.True(state.ContainsEntity(e2.ID), "entity2 added to match");


			MatchState clone = state.Clone() as MatchState;

			Assert.True(clone.ContainsEntity(e.ID), "clone contains entity1");
			Assert.True(clone.ContainsEntity(e2.ID), "clone contains entity2");

			IEntity clonedE = clone.GetEntity(e.ID);
			TestClonedEntityValues(e, clonedE, true, "after clone (e1)");

			ChangeClonedEntity(clonedE, new Vec2(11f, 111f), new Vec2(22f, 222f), 1000f, 2000f, 333f);
			TestClonedEntityValues(e, clonedE, false, "after clone modif (e1)");

			IEntity clonedE2 = clone.GetEntity(e2.ID);
			TestClonedEntityValues(e2, clonedE2, true, "after clone (e2)");

			ChangeClonedEntity(clonedE2, new Vec2(87f, 78f), new Vec2(52f, 25f), 76f, 88f, 2121f);
			TestClonedEntityValues(e2, clonedE2, false, "after clone modif (e2)");
        }
コード例 #2
0
		public bool HasCollisionBelow(IEntity entity)
		{
			Debug.Assert(entity != null);

			Rect r = entity.CreateCollisionRectangle();
			float initialMid = r.Top + r.Height / 2f;
			r.X -= JUMP_X_TOLERANCE / 2f;
			r.Width += JUMP_X_TOLERANCE;
			r.Y += JUMP_Y_TOLERANCE; // move it down a bit

			var tiles = World.Map.GetTouchedTiles(r);
			foreach (var tile in tiles) {
				if (tile.Key.Intersects(r) && // we have a collision
					(tile.Value == CollisionType.Block ||
					tile.Value == CollisionType.Platform) && // it is a blocking collision
				    tile.Key.Top >= initialMid) { // the block is below us (below our feet)

					int x = World.Map.GetTileXIndex(tile.Key);
					int y = World.Map.GetTileYIndex(tile.Key);

					// If the tile above the current tile is passable, we may jump !
					if (World.Map.IsValidXIndex(x) && World.Map.IsValidYIndex(y) &&
					    World.Map.GetCollision(x, y - 1) == CollisionType.Passable)
						return true;
				}
			}
			return false;
		}
コード例 #3
0
		/// <summary>
		/// Resolves the collisions between an entity and the world it is in.
		/// </summary>
		public void UndoCollisions(IEntity entity)
		{
			Debug.Assert(entity != null);

			var collisions = World.GetTouchedObjects(entity.CreateCollisionRectangle());

			HandleCollisionGroup(entity, collisions);
		}
コード例 #4
0
ファイル: ICharacter.cs プロジェクト: DrPandemic/EraParadox
		public override void Clone(IEntity e)
		{
			ICharacter c = (ICharacter)e;
			base.Clone(c);
			JumpForce = c.JumpForce;
			HorizontalAcceleration = c.HorizontalAcceleration;
			Animation = c.Animation;
			FacingLeft = c.FacingLeft;
		}
コード例 #5
0
ファイル: IEntity.cs プロジェクト: DrPandemic/EraParadox
		/// <summary>
		/// Clone the specified entity to copy its values.
		/// </summary>
		public virtual void Clone(IEntity e)
		{
			CollisionWidth = e.CollisionWidth;
            CollisionHeight = e.CollisionHeight;
            ID = e.ID;
            MoveSpeed = e.MoveSpeed;
            Position = e.Position.Clone() as Vec2;
            Velocity = e.Velocity.Clone() as Vec2;
		}
コード例 #6
0
ファイル: MatchTest.cs プロジェクト: DrPandemic/EraParadox
		void ChangeClonedEntity(IEntity e, Vec2 pos, Vec2 vel, float colW, float colH, float moveSpeed)
		{
			e.Position.X = pos.X;
			e.Position.Y = pos.Y;
			e.Velocity.X = vel.X;
			e.Velocity.Y = vel.Y;
			e.CollisionWidth = colW;
			e.CollisionHeight = colH;
			e.MoveSpeed = moveSpeed;
		}
コード例 #7
0
		public bool HasCollisions(IEntity entity)
		{
			Debug.Assert(entity != null);

			var rect = entity.CreateCollisionRectangle();
			var collisions = World.GetTouchedObjects(rect);

			foreach (var collision in collisions) {
				if (collision.Value != CollisionType.Passable &&
				    rect.Intersects(collision.Key)) {
					return true;
				}
			}

			return false;
		}
コード例 #8
0
		/// <summary>
		/// Runs a physics update on the given entity with a given delta seconds.
		/// Internally, this function calls the physics update with a fixed timestep.
		/// Therefore, if the delta seconds is not a 
		/// </summary>
		public void Update(double deltaSeconds, IEntity entity)
		{
			Debug.Assert(deltaSeconds > 0.0);
			Debug.Assert(entity != null 
			             && entity.Position != null
			             && entity.Velocity != null);

			while (deltaSeconds >= FIXED_TIMESTEP.TotalSeconds) {
				ApplyUpdate(entity);
				deltaSeconds -= FIXED_TIMESTEP.TotalSeconds;
			}

			if (deltaSeconds > 0.0) { // we have leftover time to simulate
				float progress = (float)(deltaSeconds / FIXED_TIMESTEP.TotalSeconds);

				InterpolateUpdate(entity, progress);
			}
		}
コード例 #9
0
ファイル: MatchTest.cs プロジェクト: DrPandemic/EraParadox
		void TestClonedEntityValues(IEntity original, IEntity clone, bool equal, string message)
		{
			string eql_msg = equal ? " same " : " different ";
			string intro = "cloned value" + eql_msg;
			Action<object, object, string> assert;
			if (equal) {
				assert = Assert.AreEqual;
			} else {
				assert = Assert.AreNotEqual;
			}

			Assert.AreEqual(original.ID, clone.ID, intro + "ID " + message); // must stay the same

			assert(original.Position.X, clone.Position.X, intro + "position " + message);
			assert(original.Velocity.Y, clone.Velocity.Y, intro + "velocity " + message);
			assert(original.CollisionHeight, clone.CollisionHeight, intro + "collision height " + message);
			assert(original.CollisionWidth, clone.CollisionWidth, intro + "collision width " + message);
			assert(original.MoveSpeed, clone.MoveSpeed, intro + "move speed " + message);
		}
コード例 #10
0
		void ApplyMovement(IEntity e, Action onPhysicsPass)
		{
			// Multiple physics passes to reduce the chance of "going through" obstacles when we're too fast.
			Vec2 passMovement = (e.Velocity * DELTA_S) / PHYSICS_PASSES;
			for (int pass = 0; pass < PHYSICS_PASSES; ++pass) {
				e.Position += passMovement;
				if (onPhysicsPass != null) onPhysicsPass();
			}
		}
コード例 #11
0
		/// <summary>
		/// Fixes a collision between an entity and a single object.
		/// </summary>
		static void UndoCollision(IEntity entity, Rect entityRect, Rect collided)
		{
			Debug.Assert(entity != null);
			Debug.Assert(entityRect != null);
			Debug.Assert(collided != null);

			Vec2 intersection = Utilities.GetIntersectionDepth(entityRect, collided);

			if (intersection != Vec2.Zero)
			{
				float abs_dept_x = Math.Abs(intersection.X);
				float abs_dept_y = Math.Abs(intersection.Y);

				// Resolve the collision on the axis where it will be less noticeable (the smallest collision amount)
				if (abs_dept_y < abs_dept_x) // collision on the y axis
				{
					entity.Position.Y += intersection.Y;
					//TODO: only undo collision for platforms if we hit the ground

					// Only stop our movement if we're going straigth into the obstacle.
					if (Math.Sign(intersection.Y) == -Math.Sign(entity.Velocity.Y))
						entity.Velocity.Y = 0f; // stop our Y movement
				}
				else // collision on the x axis
				{
					entity.Position.X += intersection.X;
					entity.Velocity.X = 0f; // stop our X movement
				}
			}
		}
コード例 #12
0
		/// <summary>
		/// Handles the collision of an object with multiple entities.
		/// </summary>
		void HandleCollisionGroup(
			IEntity entity,
			List<KeyValuePair<Rect, CollisionType>> collisions)
		{
			Debug.Assert(entity != null);
			Debug.Assert(collisions != null);

			foreach (KeyValuePair<Rect, CollisionType> collision in collisions)
			{
				// We recreate an entity rectangle on every loop
				// because multiple collisions might affect the entity in the same frame.
				Rect entityRect = entity.CreateCollisionRectangle();
				Rect rect = collision.Key;
				CollisionType type = collision.Value;

				switch (type)
				{
					case CollisionType.Block:
						UndoCollision(entity, entityRect, rect);
						break;

						case CollisionType.Passable: break; // do nothing then

						default:
						throw new NotImplementedException("Collision type not implemented.");
				}
			}
		}
コード例 #13
0
ファイル: ServerGame.cs プロジェクト: DrPandemic/EraParadox
		static Vec2 ValidateActionPosition(IEntity player, PlayerAction action)
		{
			Vec2 position = action.Position;
			// If the position provided by the client seems legit, we take it. Otherwise, we ignore it
			// and log it (might be a hacker).
			if (Vec2.DistanceSquared(player.Position, position) >= MAX_TOLERATED_OFF_DISTANCE * MAX_TOLERATED_OFF_DISTANCE) {
				position = player.Position;
			}

			return position;
		}
コード例 #14
0
		void RestrictSpeed(IEntity entity)
		{
			// Restrict movement speed
			if (entity.Velocity.GetLengthSquared() > IEntity.MAX_SPEED * IEntity.MAX_SPEED)
				entity.Velocity = Vec2.Normalize(entity.Velocity) * IEntity.MAX_SPEED;
		}
コード例 #15
0
ファイル: IEntity.cs プロジェクト: DrPandemic/EraParadox
		public virtual object Clone()
		{
			IEntity clone = new IEntity(ID, Position, MoveSpeed, CollisionWidth, CollisionHeight);
			clone.Clone(this);
			return clone;
		}
コード例 #16
0
		/// <summary>
		/// Makes the specified entity move in a certain direction for the current frame.
		/// </summary>
		public void Move(IEntity entity, HorizontalDirection direction)
		{
			Debug.Assert(entity != null
			             && entity.Velocity != null);
			Debug.Assert(Utilities.MakeList(HorizontalDirection.Left, HorizontalDirection.None, HorizontalDirection.Right)
			             	.Contains(direction));

			if (direction != HorizontalDirection.None) { // we want to move
				Debug.Assert(Utilities.MakeList(HorizontalDirection.Left, HorizontalDirection.Right).Contains(direction));

				// Find in what direction we should apply the force
				float moveForce = (int)direction * entity.MoveSpeed;

				// Apply the movement
				entity.Velocity.X += moveForce;
			}
		}
コード例 #17
0
		/// <summary>
		/// Resets the movement of the entity.
		/// </summary>
		public void ResetMovement(IEntity entity)
		{
			entity.Velocity = Vec2.Zero;
		}
コード例 #18
0
		void UpdateEntity(IEntity entity)
		{
			Debug.Assert(entity != null
			             && entity.Position != null
			             && entity.Velocity != null);

			ApplyMovement(entity, null);
		}
コード例 #19
0
		public bool IsOnGround(IEntity entity)
		{
			return Collisions.HasCollisionBelow(entity);
		}
コード例 #20
0
		/// <summary>
		/// Interpolates between the current entity state and its future state (with one
		/// more physics update).
		/// </summary>
		void InterpolateUpdate(IEntity entity, float progress)
		{
			Debug.Assert(entity != null
						 && entity.Position != null
						 && entity.Velocity != null);
			Debug.Assert(progress + double.Epsilon >= 0.0 && progress <= 1.0 + double.Epsilon);

			// Keep some values that will be interpolated
			Vec2 initialPos = entity.Position;
			Vec2 initialVel = entity.Velocity;

			// Simulate the next step
			ApplyUpdate(entity);

			// interpolate some elements
			entity.Position = Vec2.Lerp(initialPos, entity.Position, progress);
			entity.Velocity = Vec2.Lerp(initialVel, entity.Velocity, progress);
		}
コード例 #21
0
		public bool CollidesWithWorld(IEntity e)
		{
			return Collisions.HasCollisions(e);
		}
コード例 #22
0
		public override void Clone(IEntity champ)
		{
			ServerChampion c = (ServerChampion)champ;
			base.Clone(c);
		}
コード例 #23
0
		void ApplyUpdate(IEntity e)
		{
			if (e is ICharacter)
				UpdateCharacter((ICharacter)e);
			else
				UpdateEntity(e);
		}