public void GetPercentFromCenter_AtCenter_IsZero() { var bounds = new CircleBounds(Vector3.one, 10.0f); var percentFromCenter = bounds.GetPercentFromCenter(Vector3.one); Assert.That(percentFromCenter, Is.EqualTo(0.0f)); }
private void HandleStaticDynamic(uint staticID, uint dynamicID) { Bounds b = _game.CollisionComponent[staticID].Bounds; Position dynamicPos = _game.PositionComponent[dynamicID]; if (b.GetType() == typeof(RectangleBounds)) { //Get the closest point on the rectangle Vector2 closestPos = ((RectangleBounds)b).GetClosestPoint(dynamicPos.Center); double angle = Math.Atan2(closestPos.Y - dynamicPos.Center.Y, closestPos.X - dynamicPos.Center.X); double x = closestPos.X - (Math.Cos(angle) * (dynamicPos.Radius)); double y = closestPos.Y - (Math.Sin(angle) * (dynamicPos.Radius)); dynamicPos.Center = new Vector2((float)x, (float)y); _game.PositionComponent[dynamicID] = dynamicPos; } else //is circle { CircleBounds circle = ((CircleBounds)b); double angle = Math.Atan2(circle.Center.Y - dynamicPos.Center.Y, circle.Center.X - dynamicPos.Center.X); double x = circle.Center.X - (Math.Cos(angle) * (dynamicPos.Radius + circle.Radius)); double y = circle.Center.Y - (Math.Sin(angle) * (dynamicPos.Radius + circle.Radius)); dynamicPos.Center = new Vector2((float)x, (float)y); _game.PositionComponent[dynamicID] = dynamicPos; } }
public void GetPercentFromCenter_OutOfBounds_IsGreaterThanOne() { var radius = 10.0f; var startPosition = Vector3.zero; var bounds = new CircleBounds(startPosition, radius); var percentFromCenter = bounds.GetPercentFromCenter( startPosition + new Vector3(1.0f, 0.0f, 0.0f) * radius * 2.0f); Assert.That(percentFromCenter, Is.EqualTo(2.0f)); }
/// <summary> /// Handles Player/Static collisions. /// </summary> /// <param name="p">First entityID</param> /// <param name="p_2">Second entityID</param> private void PlayerStaticCollision(uint p, uint p_2) { //Stop player movement. //Get closest point on the rectangle, angle between player and point, and push back radius amount uint staticId, playerId; if (_game.PlayerComponent.Contains(p)) { playerId = p; staticId = p_2; } else { staticId = p; playerId = p_2; } Bounds b = _game.CollisionComponent[staticId].Bounds; Position playerPos = _game.PositionComponent[playerId]; if (b.GetType() == typeof(RectangleBounds)) { //Get the closest point on the rectangle Vector2 closestPos = ((RectangleBounds)b).GetClosestPoint(playerPos.Center); double angle = Math.Atan2(closestPos.Y - playerPos.Center.Y, closestPos.X - playerPos.Center.X); double x = closestPos.X - (Math.Cos(angle) * (playerPos.Radius)); double y = closestPos.Y - (Math.Sin(angle) * (playerPos.Radius)); playerPos.Center = new Vector2((float)x, (float)y); _game.PositionComponent[playerId] = playerPos; } else //is circle { //static won't move, so just place player out there CircleBounds circle = ((CircleBounds)b); double angle = Math.Atan2(circle.Center.Y - playerPos.Center.Y, circle.Center.X - playerPos.Center.X); double x = circle.Center.X - (Math.Cos(angle) * (playerPos.Radius + circle.Radius)); double y = circle.Center.Y - (Math.Sin(angle) * (playerPos.Radius + circle.Radius)); playerPos.Center = new Vector2((float)x, (float)y); _game.PositionComponent[playerId] = playerPos; } }
/// <summary> /// Handles Player/Enemy collisions. /// </summary> /// <param name="p">First entityID</param> /// <param name="p_2">Second entityID</param> private void PlayerEnemyCollision(uint p, uint p_2) { //Need to separate into 4 types: stationary&painless, stationary&painful, moving&painless, moving&painful uint enemyId, playerId; if (_game.EnemyComponent.Contains(p)) { enemyId = p; playerId = p_2; } else { playerId = p; enemyId = p_2; } Enemy enemy = _game.EnemyComponent[enemyId]; bool moving = _game.MovementComponent.Contains(enemyId); if (!enemy.HurtOnTouch && !moving) { //Stationary & Painless //Act like a static Bounds b = _game.CollisionComponent[enemyId].Bounds; Position playerPos = _game.PositionComponent[playerId]; if (b.GetType() == typeof(RectangleBounds)) { //Get the closest point on the rectangle Vector2 closestPos = ((RectangleBounds)b).GetClosestPoint(playerPos.Center); double angle = Math.Atan2(closestPos.Y - playerPos.Center.Y, closestPos.X - playerPos.Center.X); double x = closestPos.X - (Math.Cos(angle) * (playerPos.Radius)); double y = closestPos.Y - (Math.Sin(angle) * (playerPos.Radius)); playerPos.Center = new Vector2((float)x, (float)y); _game.PositionComponent[playerId] = playerPos; } else //is circle { //static won't move, so just place player out there CircleBounds circle = ((CircleBounds)b); double angle = Math.Atan2(circle.Center.Y - playerPos.Center.Y, circle.Center.X - playerPos.Center.X); double x = circle.Center.X - (Math.Cos(angle) * (playerPos.Radius + circle.Radius)); double y = circle.Center.Y - (Math.Sin(angle) * (playerPos.Radius + circle.Radius)); playerPos.Center = new Vector2((float)x, (float)y); _game.PositionComponent[playerId] = playerPos; } } else if (enemy.HurtOnTouch && !moving) { //Stationary & Painful DoDamage(_game.PlayerComponent[playerId], 10); //Replace 10 with something dynamic. } else if (!enemy.HurtOnTouch && moving) { //For now, let's have it just push the person around. But we need to make sure eventually that //complicated nonviolent collisions is handled. That way pushing blocks/people walking into each other //will be done properly. //Act like a static Bounds b = _game.CollisionComponent[enemyId].Bounds; Position playerPos = _game.PositionComponent[playerId]; if (b.GetType() == typeof(RectangleBounds)) { //Get the closest point on the rectangle Vector2 closestPos = ((RectangleBounds)b).GetClosestPoint(playerPos.Center); double angle = Math.Atan2(closestPos.Y - playerPos.Center.Y, closestPos.X - playerPos.Center.X); double x = closestPos.X - (Math.Cos(angle) * (playerPos.Radius)); double y = closestPos.Y - (Math.Sin(angle) * (playerPos.Radius)); playerPos.Center = new Vector2((float)x, (float)y); _game.PositionComponent[playerId] = playerPos; } else //is circle { //static won't move, so just place player out there CircleBounds circle = ((CircleBounds)b); double angle = Math.Atan2(circle.Center.Y - playerPos.Center.Y, circle.Center.X - playerPos.Center.X); double x = circle.Center.X - (Math.Cos(angle) * (playerPos.Radius + circle.Radius)); double y = circle.Center.Y - (Math.Sin(angle) * (playerPos.Radius + circle.Radius)); playerPos.Center = new Vector2((float)x, (float)y); _game.PositionComponent[playerId] = playerPos; } } else { //Moving & Painful DoDamage(_game.PlayerComponent[playerId], 10); //Replace 10 with something dynamic. } }
/// <summary> /// Renders the game world /// </summary> /// <param name="elapsedTime"> /// The time between this and the previous frame. /// </param> public void Draw(float elapsedTime) { spriteBatch.Begin(SpriteSortMode.BackToFront, null, SamplerState.PointClamp, null, null, null); uint roomId; try { roomId = DungeonCrawlerGame.LevelManager.getCurrentRoom().EntityID; } catch { roomId = uint.MaxValue; //should change this no room should not have an id } // Draw all Sprites List <Sprite> sprites = new List <Sprite>(); foreach (Sprite sprite in game.SpriteComponent.All) { sprites.Add(sprite); } foreach (Sprite sprite in sprites) { //foreach (Sprite sprite in game.SpriteComponent.All) //{ Position position = game.PositionComponent[sprite.EntityID]; Color drawColor = Color.White; if (position.RoomID == roomId) { if (sprite.UseDifferentColor) { drawColor = sprite.SpriteColor; } else { drawColor = Color.White; } Position pos = position; if (game.EnemyComponent.Contains(position.EntityID)) //if enemy -> draw centered on position { pos.Center.X -= sprite.SpriteBounds.Width / 2; pos.Center.Y -= sprite.SpriteBounds.Height / 2; } spriteBatch.Draw(sprite.SpriteSheet, position.Center, sprite.SpriteBounds, drawColor, 0f, // rotation new Vector2(position.Radius, position.Radius), // origin 1f, // scale SpriteEffects.None, 1); } } // Draw all MovementSprites foreach (MovementSprite sprite in game.MovementSpriteComponent.All) { Position position = game.PositionComponent[sprite.EntityID]; if (position.RoomID == roomId) { spriteBatch.Draw(sprite.SpriteSheet, position.Center, sprite.SpriteBounds, Color.White, 0f, // rotation new Vector2(position.Radius, position.Radius), // origin 1f, // scale SpriteEffects.None, .8f); } } //Draw actor text foreach (ActorText actorText in game.ActorTextComponent.All) { Position position = game.PositionComponent[actorText.EntityID]; if (position.RoomID == roomId) { position.Center.Y -= actorText.Offset; spriteBatch.DrawString(_actorTextFont, actorText.Text, position.Center, Color.White); } } //Draw Weapon animations foreach (WeaponSprite sprite in game.WeaponSpriteComponent.All) { Position position = game.PositionComponent[sprite.EntityID]; if (position.RoomID == roomId) { Facing facing = (Facing)game.SpriteAnimationComponent[sprite.EntityID].CurrentAnimationRow; //changed to get direction from spriteanimation instead of movementsprite, currentAnimationRow returns same values as facing for directions position.Center = applyFacingOffset(facing, position.Center); spriteBatch.Draw(sprite.SpriteSheet, position.Center, sprite.SpriteBounds, Color.White, 0f, new Vector2(position.Radius), 1f, SpriteEffects.None, (facing == Facing.North) ? .9f : .7f); } } //Draw HUD - Moving this to the new HUDSystem. /*foreach (HUDSprite sprite in game.HUDSpriteComponent.All) * { * Color playerColor; * PlayerIndex playerDex = sprite.PlayerIndex; * switch (playerDex) * { * case PlayerIndex.One: * playerColor = Color.Red; * break; * case PlayerIndex.Two: * playerColor = Color.Blue; * break; * case PlayerIndex.Three: * playerColor = Color.Green; * break; * case PlayerIndex.Four: * playerColor = Color.Magenta; * break; * default: * playerColor = Color.White; * break; * } * * if (sprite.isSeen) //A,B,X,Y, and Dpad are temp on screen * { * * Position position = game.PositionComponent[sprite.EntityID]; * spriteBatch.Draw(sprite.SpriteSheet, * position.Center, * sprite.SpriteBounds, * playerColor, * 0f, // rotation * new Vector2(position.Radius,position.Radius), // origin * 1f, // scale * SpriteEffects.None, * 0.6f); * } * }*/ game.HUDSystem.Draw(elapsedTime, spriteBatch); /* * foreach (InventorySprite sprite in game.InventorySpriteComponent.All) * { * if (sprite.isSeen) * { * Position position = game.PositionComponent[sprite.EntityID]; * spriteBatch.Draw(sprite.SpriteSheet, * position.Center, * sprite.SpriteBounds, * Color.White, * 0f, // rotation * new Vector2(position.Radius, position.Radius), // origin * 1f, // scale * SpriteEffects.None, * 0.5f); * } * } */ #if DEBUG //If we are in debug, draw the collision bounds. uint roomID = game.CurrentRoomEid; foreach (Collideable collision in game.CollisionComponent.InRoom(roomID)) { if (collision.Bounds is RectangleBounds) { spriteBatch.Draw(_debugTexture, ((RectangleBounds)collision.Bounds).Rectangle, Color.Red); } else { //Might want to change this to a circle. CircleBounds bounds = (CircleBounds)collision.Bounds; spriteBatch.Draw(_debugTexture, new Rectangle((int)(bounds.Center.X - bounds.Radius), (int)(bounds.Center.Y - bounds.Radius), (int)(bounds.Radius * 2), (int)(bounds.Radius * 2)), Color.Red); } } #endif spriteBatch.End(); }
/// <summary> /// Renders the game world /// </summary> /// <param name="elapsedTime"> /// The time between this and the previous frame. /// </param> public void Draw(float elapsedTime) { spriteBatch.Begin(SpriteSortMode.BackToFront, null, SamplerState.PointClamp, null, null, null); uint roomId; try { roomId = DungeonCrawlerGame.LevelManager.getCurrentRoom().EntityID; } catch { roomId = uint.MaxValue; } // Draw all Sprites foreach (Sprite sprite in game.SpriteComponent.All) { Position position = game.PositionComponent[sprite.EntityID]; if (position.RoomID == roomId) { spriteBatch.Draw(sprite.SpriteSheet, position.Center, sprite.SpriteBounds, Color.White, 0f, // rotation new Vector2(position.Radius, position.Radius), // origin 1f, // scale SpriteEffects.None, 1); } } // Draw all MovementSprites foreach (MovementSprite sprite in game.MovementSpriteComponent.All) { Position position = game.PositionComponent[sprite.EntityID]; if (position.RoomID == roomId) { spriteBatch.Draw(sprite.SpriteSheet, position.Center, sprite.SpriteBounds, Color.White, 0f, // rotation new Vector2(position.Radius, position.Radius), // origin 1f, // scale SpriteEffects.None, .8f); } } //Draw actor text foreach (ActorText actorText in game.ActorTextComponent.All) { Position position = game.PositionComponent[actorText.EntityID]; if (position.RoomID == roomId) { position.Center.Y -= actorText.Offset; spriteBatch.DrawString(_actorTextFont, actorText.Text, position.Center, Color.White); } } //Draw Weapon animations foreach (WeaponSprite sprite in game.WeaponSpriteComponent.All) { Position position = game.PositionComponent[sprite.EntityID]; if (position.RoomID == roomId) { Facing facing = (Facing)game.SpriteAnimationComponent[sprite.EntityID].CurrentAnimationRow; //changed to get direction from spriteanimation instead of movementsprite, currentAnimationRow returns same values as facing for directions position.Center = applyFacingOffset(facing, position.Center); spriteBatch.Draw(sprite.SpriteSheet, position.Center, sprite.SpriteBounds, Color.White, 0f, new Vector2(position.Radius), 1f, SpriteEffects.None, (facing == Facing.North) ? .9f : .7f); } } //Draw HUD foreach (HUDSprite sprite in game.HUDSpriteComponent.All) { Color playerColor; PlayerIndex playerDex = sprite.PlayerIndex; switch (playerDex) { case PlayerIndex.One: playerColor = Color.Red; break; case PlayerIndex.Two: playerColor = Color.Blue; break; case PlayerIndex.Three: playerColor = Color.Green; break; case PlayerIndex.Four: playerColor = Color.Magenta; break; default: playerColor = Color.White; break; } if (sprite.isSeen) //A,B,X,Y, and Dpad are temp on screen { Position position = game.PositionComponent[sprite.EntityID]; spriteBatch.Draw(sprite.SpriteSheet, position.Center, sprite.SpriteBounds, playerColor, 0f, // rotation new Vector2(position.Radius, position.Radius), // origin 1f, // scale SpriteEffects.None, 0.6f); } } foreach (InventorySprite sprite in game.InventorySpriteComponent.All) { if (sprite.isSeen) { Position position = game.PositionComponent[sprite.EntityID]; spriteBatch.Draw(sprite.SpriteSheet, position.Center, sprite.SpriteBounds, Color.White, 0f, // rotation new Vector2(position.Radius, position.Radius), // origin 1f, // scale SpriteEffects.None, 0.5f); } } #if DEBUG //If we are in debug, draw the collision bounds. uint roomID = game.CurrentRoomEid; foreach (Collideable collision in game.CollisionComponent.InRoom(roomID)) { if (collision.Bounds is RectangleBounds) { spriteBatch.Draw(_debugTexture, ((RectangleBounds)collision.Bounds).Rectangle, Color.Red); } else { //Might want to change this to a circle. CircleBounds bounds = (CircleBounds)collision.Bounds; spriteBatch.Draw(_debugTexture, new Rectangle((int)(bounds.Center.X - bounds.Radius), (int)(bounds.Center.Y - bounds.Radius), (int)(bounds.Radius * 2), (int)(bounds.Radius * 2)), Color.Red); } } #endif spriteBatch.End(); }
private void HandleDynamicDynamic(uint dID1, uint dID2) { //Need the position for position, the collideable for the bounds type, // and the movement to analyze the amount of pushing that should be done Position pos1 = _game.PositionComponent[dID1]; Position pos2 = _game.PositionComponent[dID2]; Collideable col1 = _game.CollisionComponent[dID1]; Collideable col2 = _game.CollisionComponent[dID2]; Movement mov1 = _game.MovementComponent[dID1]; Movement mov2 = _game.MovementComponent[dID2]; //We'll need different equations for different types of bounds. if (col1.Bounds.GetType() == typeof(CircleBounds) && col2.Bounds.GetType() == typeof(CircleBounds)) { CircleBounds c1 = (CircleBounds)col1.Bounds; CircleBounds c2 = (CircleBounds)col2.Bounds; //Angle from c1 to c2 double angle = Math.Atan2(c2.Center.Y - c1.Center.Y, c2.Center.X - c1.Center.X); double distance = Math.Abs((c2.Center.Y - c1.Center.Y) / Math.Sin(angle)); double ddistance = c1.Radius + c2.Radius - distance; double x = pos1.Center.X - (Math.Cos(angle) * ddistance); double y = pos1.Center.Y - (Math.Sin(angle) * ddistance); pos1.Center = new Vector2((float)x, (float)y); x = pos2.Center.X + (Math.Cos(angle) * ddistance); y = pos2.Center.Y + (Math.Sin(angle) * ddistance); pos2.Center = new Vector2((float)x, (float)y); //Now determine the pushback from the movement /*Vector2 dMove = (mov1.Direction * mov1.Speed + mov2.Direction * mov2.Speed) / 2; * double moveAngle = Math.Atan2(dMove.Y, dMove.X); * * double dAngle = moveAngle - angle; * * double moveDistance = Math.Cos(dAngle) * dMove.Length(); * * dMove.Normalize(); * * pos1.Center += dMove * (float)moveDistance; * pos2.Center += dMove * (float)moveDistance; */ _game.PositionComponent[dID1] = pos1; _game.PositionComponent[dID2] = pos2; c1.Center = pos1.Center; c2.Center = pos2.Center; col1.Bounds = c1; col2.Bounds = c2; _game.CollisionComponent[dID1] = col1; _game.CollisionComponent[dID2] = col2; } if (col1.Bounds.GetType() != col2.Bounds.GetType()) { bool col1IsRect = (col1.Bounds.GetType() == typeof(CircleBounds)); Position rectPos = (col1IsRect ? pos1 : pos2); Collideable rectCol = (col1IsRect ? col1 : col2); Movement rectMov = (col1IsRect ? mov1 : mov2); RectangleBounds rect = (RectangleBounds)rectCol.Bounds; Position circPos = (col1IsRect ? pos2 : pos1); Collideable circCol = (col1IsRect ? col2 : col1); Movement circMov = (col1IsRect ? mov2 : mov1); CircleBounds circ = (CircleBounds)rectCol.Bounds; //Do your thing here throw new NotImplementedException(); } if (col1.Bounds.GetType() == typeof(RectangleBounds) && col2.Bounds.GetType() == typeof(RectangleBounds)) { //Can this happen? throw new NotImplementedException(); } }