Skip to content

Commit

Permalink
Calculate Box and Point positions in MonoGame coordinates. (#81)
Browse files Browse the repository at this point in the history
  • Loading branch information
loodakrawa authored Jun 5, 2017
1 parent 2805be1 commit 844efbc
Show file tree
Hide file tree
Showing 8 changed files with 154 additions and 41 deletions.
75 changes: 58 additions & 17 deletions SpriterDotNet.MonoGame.Example/MonoGameDebugAnimator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,23 @@
// This software may be modified and distributed under the terms
// of the zlib license. See the LICENSE file for details.

using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Audio;
using SpriterDotNet.MonoGame.Sprites;
using Microsoft.Xna.Framework.Graphics;
using System;
using System.Collections.Generic;

namespace SpriterDotNet.MonoGame.Example
{
public class MonoGameDebugAnimator : MonoGameAnimator
{
private IDictionary<string, ISprite> boxTextures = new Dictionary<string, ISprite>();
private ISprite pointTexture;
public bool DrawSpriteOutlines { get; set; }
public Color DebugColor { get; set; } = Color.Red;

private readonly List<KeyValuePair<Vector2, Vector2>> lines = new List<KeyValuePair<Vector2, Vector2>>();
private readonly Texture2D whiteDot;

private static readonly float PointBoxSize = 2.5f;

public MonoGameDebugAnimator
(
Expand All @@ -24,27 +29,63 @@ public MonoGameDebugAnimator
Stack<SpriteDrawInfo> drawInfoPool = null
) : base(entity, providerFactory, drawInfoPool)
{
pointTexture = new TextureSprite(TextureUtil.CreateCircle(graphicsDevice, 5, Color.Cyan));
whiteDot = TextureUtil.CreateRectangle(graphicsDevice, 1, 1, Color.White);
}

if (entity.ObjectInfos != null)
{
foreach (SpriterObjectInfo objInfo in entity.ObjectInfos)
{
if (objInfo.ObjectType != SpriterObjectType.Box) continue;
boxTextures[objInfo.Name] = new TextureSprite(TextureUtil.CreateRectangle(graphicsDevice, (int)objInfo.Width, (int)objInfo.Height, Color.Cyan));
}
}
protected override void ApplySpriteTransform(ISprite drawable, SpriterObject info)
{
base.ApplySpriteTransform(drawable, info);
if (DrawSpriteOutlines) AddForDrawing(GetBoundingBox(info, drawable.Width, drawable.Height));
}

protected override void ApplyPointTransform(string name, SpriterObject info)
{
if (pointTexture == null) return;
ApplySpriteTransform(pointTexture, info);
Vector2 position = GetPosition(info);
Box box = new Box
{
Point1 = position + new Vector2(-PointBoxSize, -PointBoxSize),
Point2 = position + new Vector2(PointBoxSize, -PointBoxSize),
Point3 = position + new Vector2(PointBoxSize, PointBoxSize),
Point4 = position + new Vector2(-PointBoxSize, PointBoxSize)
};
AddForDrawing(box);
}

protected override void ApplyBoxTransform(SpriterObjectInfo objInfo, SpriterObject info)
{
ApplySpriteTransform(boxTextures[objInfo.Name], info);
Box bounds = GetBoundingBox(info, objInfo.Width, objInfo.Height);
AddForDrawing(bounds);
}

public override void Draw(SpriteBatch spriteBatch)
{
base.Draw(spriteBatch);

foreach (var pair in lines) DrawLine(spriteBatch, pair.Key, pair.Value);
lines.Clear();
}

public void AddForDrawing(Box cb)
{
AddForDrawing(cb.Point1, cb.Point2);
AddForDrawing(cb.Point2, cb.Point3);
AddForDrawing(cb.Point3, cb.Point4);
AddForDrawing(cb.Point4, cb.Point1);
}

public void AddForDrawing(Vector2 v1, Vector2 v2)
{
lines.Add(new KeyValuePair<Vector2, Vector2>(v1, v2));
}

private void DrawLine(SpriteBatch batch, Vector2 start, Vector2 end)
{
Vector2 edge = end - start;
float angle = (float)Math.Atan2(edge.Y, edge.X);

Rectangle rec = new Rectangle((int)start.X, (int)start.Y, (int)edge.Length(), 1);

batch.Draw(whiteDot, rec, null, DebugColor, angle, new Vector2(0, 0), SpriteEffects.None, 0);
}
}
}
20 changes: 14 additions & 6 deletions SpriterDotNet.MonoGame.Example/SpriterGameState.cs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,8 @@ public class SpriterGameState : GameState
"Q/E = Rotate",
"N/M = Scale",
"F/G = Flip",
"J = Toggle Colour"
"J = Toggle Colour",
"~ = Toggle Sprite Outlines"
};

private static readonly Config config = new Config
Expand All @@ -67,11 +68,11 @@ public class SpriterGameState : GameState
private string metadata = string.Empty;
private Stats stats = new Stats();

private Vector2 centre;
private float elapsedTime;

protected override void Load()
{
centre = new Vector2(Width / 2.0f, Height / 2.0f);
Vector2 centre = new Vector2(Width / 2.0f, Height / 2.0f);
oldState = Keyboard.GetState();

spriteBatch = new SpriteBatch(GraphicsDevice);
Expand Down Expand Up @@ -142,14 +143,21 @@ public override void Update(float deltaTime)
if (IsPressed(Keys.M)) currentAnimator.Scale += new Vector2(Math.Sign(scale.X) * 0.2f, Math.Sign(scale.Y) * 0.2f);
if (IsPressed(Keys.F)) currentAnimator.Scale *= new Vector2(-1, 1);
if (IsPressed(Keys.G)) currentAnimator.Scale *= new Vector2(1, -1);
if (IsPressed(Keys.OemTilde)) (currentAnimator as MonoGameDebugAnimator).DrawSpriteOutlines = !(currentAnimator as MonoGameDebugAnimator).DrawSpriteOutlines;


oldState = Keyboard.GetState();

currentAnimator.Update(deltaTime);

string entity = currentAnimator.Entity.Name;
status = string.Format("{0} : {1}", entity, currentAnimator.Name);
metadata = "Variables:\n" + GetVarValues() + "\nTags:\n" + GetTagValues();
elapsedTime += deltaTime;
if(elapsedTime >= 100)
{
elapsedTime -= 100;
string entity = currentAnimator.Entity.Name;
status = string.Format("{0} : {1}", entity, currentAnimator.Name);
metadata = string.Format("Variables:\n{0}\nTags:\n", GetVarValues(), GetTagValues());
}
}

private void DrawText(string text, Vector2 position, float size, Color color)
Expand Down
12 changes: 12 additions & 0 deletions SpriterDotNet.MonoGame/Box.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
using Microsoft.Xna.Framework;

namespace SpriterDotNet.MonoGame
{
public struct Box
{
public Vector2 Point1;
public Vector2 Point2;
public Vector2 Point3;
public Vector2 Point4;
}
}
2 changes: 2 additions & 0 deletions SpriterDotNet.MonoGame/ISprite.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ namespace SpriterDotNet.MonoGame
{
public interface ISprite
{
float Width { get; }
float Height { get; }
void Draw(SpriteBatch spriteBatch, Vector2 pivot, Vector2 position, Vector2 scale, float rotation, Color color, float depth);
}
}
79 changes: 61 additions & 18 deletions SpriterDotNet.MonoGame/MonoGameAnimator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -79,8 +79,8 @@ public virtual float Rotation

public MonoGameAnimator
(
SpriterEntity entity,
IProviderFactory<ISprite, SoundEffect> providerFactory = null,
SpriterEntity entity,
IProviderFactory<ISprite, SoundEffect> providerFactory = null,
Stack<SpriteDrawInfo> drawInfoPool = null
) : base(entity, providerFactory)
{
Expand Down Expand Up @@ -111,10 +111,63 @@ public override void Update(float deltaTime)
}

protected override void ApplySpriteTransform(ISprite drawable, SpriterObject info)
{
float posX, posY, rotation;
GetPositionAndRotation(info, out posX, out posY, out rotation);

SpriteDrawInfo di = DrawInfoPool.Count > 0 ? DrawInfoPool.Pop() : new SpriteDrawInfo();

di.Drawable = drawable;
di.Pivot = new Vector2(info.PivotX, (1 - info.PivotY));
di.Position = new Vector2(posX, posY);
di.Scale = new Vector2(info.ScaleX, info.ScaleY) * Scale;
di.Rotation = rotation;
di.Color = Color * info.Alpha;
di.Depth = Depth + DeltaDepth * DrawInfos.Count;

DrawInfos.Add(di);
}

protected override void PlaySound(SoundEffect sound, SpriterSound info)
{
sound.Play(info.Volume, 0.0f, info.Panning);
}

public Box GetBoundingBox(SpriterObject info, float width, float height)
{
float posX, posY, rotation;
GetPositionAndRotation(info, out posX, out posY, out rotation);

float w = width * info.ScaleX * Scale.X;
float h = height * info.ScaleY * Scale.Y;

float rs = (float)Math.Sin(rotation);
float rc = (float)Math.Cos(rotation);

Vector2 originDelta = Rotate(new Vector2(-info.PivotX * w, -(1 - info.PivotY) * h), rs, rc);

Box cb = new Box();
Vector2 horizontal = Rotate(new Vector2(w, 0), rs, rc);
cb.Point1 = new Vector2(posX, posY) + originDelta;
cb.Point2 = cb.Point1 + horizontal;
cb.Point4 = cb.Point1 + Rotate(new Vector2(0, h), rs, rc);
cb.Point3 = cb.Point4 + horizontal;

return cb;
}

public Vector2 GetPosition(SpriterObject info)
{
float posX, posY, rotation;
GetPositionAndRotation(info, out posX, out posY, out rotation);
return new Vector2(posX, posY);
}

private void GetPositionAndRotation(SpriterObject info, out float posX, out float posY, out float rotation)
{
float px = info.X;
float py = -info.Y;
float rotation = MathHelper.ToRadians(-info.Angle);
rotation = MathHelper.ToRadians(-info.Angle);

if (Scale.X < 0)
{
Expand All @@ -131,25 +184,15 @@ protected override void ApplySpriteTransform(ISprite drawable, SpriterObject inf
px *= scaleAbs.X;
py *= scaleAbs.Y;

float posX = px * rotationCos - py * rotationSin;
float posY = px * rotationSin + py * rotationCos;

SpriteDrawInfo di = DrawInfoPool.Count > 0 ? DrawInfoPool.Pop() : new SpriteDrawInfo();

di.Drawable = drawable;
di.Pivot = new Vector2(info.PivotX, (1 - info.PivotY));
di.Position = new Vector2(posX, posY) + Position;
di.Scale = new Vector2(info.ScaleX, info.ScaleY) * Scale;
di.Rotation = rotation + Rotation;
di.Color = Color * info.Alpha;
di.Depth = Depth + DeltaDepth * DrawInfos.Count;
rotation += Rotation;

DrawInfos.Add(di);
posX = px * rotationCos - py * rotationSin + Position.X;
posY = px * rotationSin + py * rotationCos + Position.Y;
}

protected override void PlaySound(SoundEffect sound, SpriterSound info)
private static Vector2 Rotate(Vector2 v, float s, float c)
{
sound.Play(info.Volume, 0.0f, info.Panning);
return new Vector2(v.X * c - v.Y * s, v.X * s + v.Y * c);
}
}
}
1 change: 1 addition & 0 deletions SpriterDotNet.MonoGame/SpriterDotNet.MonoGame.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Compile Include="Box.cs" />
<Compile Include="ISprite.cs" />
<Compile Include="MonoGameAnimator.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
Expand Down
3 changes: 3 additions & 0 deletions SpriterDotNet.MonoGame/Sprites/TexturePackerSprite.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ namespace SpriterDotNet.MonoGame.Sprites
/// </summary>
public class TexturePackerSprite : ISprite
{
public float Width => width;
public float Height => height;

private static readonly float SpriteAtlasRotation = MathHelper.ToRadians(-90);

public Texture2D texture;
Expand Down
3 changes: 3 additions & 0 deletions SpriterDotNet.MonoGame/Sprites/TextureSprite.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ namespace SpriterDotNet.MonoGame.Sprites
/// </summary>
public class TextureSprite : ISprite
{
public float Width => texture.Width;
public float Height => texture.Height;

private readonly Texture2D texture;

public TextureSprite(Texture2D texture)
Expand Down

0 comments on commit 844efbc

Please sign in to comment.