diff --git a/Subsurface/Barotrauma.csproj b/Subsurface/Barotrauma.csproj index 117d4b36c..7da1f6e51 100644 --- a/Subsurface/Barotrauma.csproj +++ b/Subsurface/Barotrauma.csproj @@ -60,6 +60,7 @@ Icon.ico + @@ -850,12 +851,18 @@ PreserveNewest + + PreserveNewest + PreserveNewest PreserveNewest + + PreserveNewest + PreserveNewest diff --git a/Subsurface/Content/Particles/FlameRoundParticleSheet.png b/Subsurface/Content/Particles/FlameRoundParticleSheet.png new file mode 100644 index 000000000..8b6c84a46 Binary files /dev/null and b/Subsurface/Content/Particles/FlameRoundParticleSheet.png differ diff --git a/Subsurface/Content/Particles/ParticlePrefabs.xml b/Subsurface/Content/Particles/ParticlePrefabs.xml index 7182505bc..36fbedd31 100644 --- a/Subsurface/Content/Particles/ParticlePrefabs.xml +++ b/Subsurface/Content/Particles/ParticlePrefabs.xml @@ -111,19 +111,20 @@ - - + velocitychange="0.0, 2.5" + animduration="1.2" + loopanim="false"> + - + collisionradius="80.0" + velocitychange="0.0, 2.5" + animduration="4" + restitution="0.98" + loopanim="false"> + hullGaps; + + private float animState; + private int animFrame; public ParticlePrefab.DrawTargetType DrawTarget { @@ -77,6 +80,9 @@ namespace Barotrauma.Particles spriteIndex = Rand.Int(prefab.Sprites.Count); + animState = 0; + animFrame = 0; + currentHull = Hull.FindHull(position, hullGuess); this.position = position; @@ -166,6 +172,13 @@ namespace Barotrauma.Particles color.R / 255.0f + prefab.ColorChange.X * deltaTime, color.G / 255.0f + prefab.ColorChange.Y * deltaTime, color.B / 255.0f + prefab.ColorChange.Z * deltaTime); + + if (prefab.Sprites[spriteIndex] is SpriteSheet) + { + animState += deltaTime; + int frameCount = ((SpriteSheet)prefab.Sprites[spriteIndex]).FrameCount; + animFrame = (int)Math.Min(Math.Floor(animState / prefab.AnimDuration * frameCount), frameCount - 1); + } if (prefab.DeleteOnCollision || prefab.CollidesWithWalls) { @@ -317,11 +330,25 @@ namespace Barotrauma.Particles drawSize *= ((totalLifeTime - lifeTime) / prefab.GrowTime); } - prefab.Sprites[spriteIndex].Draw(spriteBatch, - new Vector2(drawPosition.X, -drawPosition.Y), - color * alpha, - prefab.Sprites[spriteIndex].Origin, drawRotation, - drawSize, SpriteEffects.None, prefab.Sprites[spriteIndex].Depth); + if (prefab.Sprites[spriteIndex] is SpriteSheet) + { + ((SpriteSheet)prefab.Sprites[spriteIndex]).Draw( + spriteBatch, animFrame, + new Vector2(drawPosition.X, -drawPosition.Y), + color * alpha, + prefab.Sprites[spriteIndex].Origin, drawRotation, + drawSize, SpriteEffects.None, prefab.Sprites[spriteIndex].Depth); + } + else + { + prefab.Sprites[spriteIndex].Draw(spriteBatch, + new Vector2(drawPosition.X, -drawPosition.Y), + color * alpha, + prefab.Sprites[spriteIndex].Origin, drawRotation, + drawSize, SpriteEffects.None, prefab.Sprites[spriteIndex].Depth); + } + + } } } diff --git a/Subsurface/Source/Particles/ParticlePrefab.cs b/Subsurface/Source/Particles/ParticlePrefab.cs index c0af6a518..47c9d29c5 100644 --- a/Subsurface/Source/Particles/ParticlePrefab.cs +++ b/Subsurface/Source/Particles/ParticlePrefab.cs @@ -13,6 +13,9 @@ namespace Barotrauma.Particles public readonly List Sprites; + public readonly float AnimDuration; + public readonly bool LoopAnim; + public readonly float AngularVelocityMin, AngularVelocityMax; public readonly float StartRotationMin, StartRotationMax; @@ -53,11 +56,21 @@ namespace Barotrauma.Particles foreach (XElement subElement in element.Elements()) { - if (subElement.Name.ToString().ToLowerInvariant() != "sprite") continue; - - Sprites.Add(new Sprite(subElement)); + switch (subElement.Name.ToString().ToLowerInvariant()) + { + case "sprite": + Sprites.Add(new Sprite(subElement)); + break; + case "spritesheet": + case "animatedsprite": + Sprites.Add(new SpriteSheet(subElement)); + break; + } } + AnimDuration = ToolBox.GetAttributeFloat(element, "animduration", 1.0f); + LoopAnim = ToolBox.GetAttributeBool(element, "loopanim", true); + if (element.Attribute("angularvelocity") == null) { AngularVelocityMin = ToolBox.GetAttributeFloat(element, "angularvelocitymin", 0.0f); @@ -134,7 +147,9 @@ namespace Barotrauma.Particles DeleteOnCollision = ToolBox.GetAttributeBool(element, "deleteoncollision", false); CollidesWithWalls = ToolBox.GetAttributeBool(element, "collideswithwalls", false); - CollisionRadius = ToolBox.GetAttributeFloat(element, "collisionradius", Sprites[0].SourceRect.Width/2.0f); + CollisionRadius = ToolBox.GetAttributeFloat(element, + "collisionradius", + Sprites.Count > 0 ? 1 : Sprites[0].SourceRect.Width / 2.0f); ColorChange = ToolBox.GetAttributeVector4(element, "colorchange", Vector4.Zero); diff --git a/Subsurface/Source/Sprite.cs b/Subsurface/Source/Sprite.cs index 0788538fd..236a7b102 100644 --- a/Subsurface/Source/Sprite.cs +++ b/Subsurface/Source/Sprite.cs @@ -14,15 +14,15 @@ namespace Barotrauma //if two sprites use the same file, they share the same texture string file; - Texture2D texture; + protected Texture2D texture; //the area in the texture that is supposed to be drawn Rectangle sourceRect; //the offset used when drawing the sprite - Vector2 offset; + protected Vector2 offset; - private Vector2 origin; + protected Vector2 origin; //the size of the drawn sprite, if larger than the source, //the sprite is tiled to fill the target size @@ -32,7 +32,7 @@ namespace Barotrauma public SpriteEffects effects; - float depth; + protected float depth; public Rectangle SourceRect { @@ -202,7 +202,7 @@ namespace Barotrauma this.Draw(spriteBatch, pos, color, origin, rotate, new Vector2(scale, scale), spriteEffect, depth); } - public void Draw(SpriteBatch spriteBatch, Vector2 pos, Color color, Vector2 origin, float rotate, Vector2 scale, SpriteEffects spriteEffect = SpriteEffects.None, float? depth = null) + public virtual void Draw(SpriteBatch spriteBatch, Vector2 pos, Color color, Vector2 origin, float rotate, Vector2 scale, SpriteEffects spriteEffect = SpriteEffects.None, float? depth = null) { //for (int x = -1; x <= 1; x += 2) //{ diff --git a/Subsurface/Source/SpriteSheet.cs b/Subsurface/Source/SpriteSheet.cs new file mode 100644 index 000000000..eadc93492 --- /dev/null +++ b/Subsurface/Source/SpriteSheet.cs @@ -0,0 +1,55 @@ +using Microsoft.Xna.Framework; +using System; +using System.Xml.Linq; +using Microsoft.Xna.Framework.Graphics; + +namespace Barotrauma +{ + class SpriteSheet : Sprite + { + private Rectangle[] sourceRects; + + public int FrameCount + { + get { return sourceRects.Length; } + } + + public SpriteSheet(XElement element, string path = "", string file = "") + : base(element, path, file) + { + int columnCount = Math.Max(ToolBox.GetAttributeInt(element, "columns", 1), 1); + int rowCount = Math.Max(ToolBox.GetAttributeInt(element, "rows", 1), 1); + + sourceRects = new Rectangle[rowCount * columnCount]; + + int cellWidth = SourceRect.Width / columnCount; + int cellHeight = SourceRect.Height / rowCount; + + for (int x = 0; x < columnCount; x++) + { + for (int y = 0; y < rowCount; y++) + { + sourceRects[x + y * columnCount] = new Rectangle(x * cellWidth, y * cellHeight, cellWidth, cellHeight); + } + } + + origin = ToolBox.GetAttributeVector2(element, "origin", new Vector2(0.5f, 0.5f)); + origin.X = origin.X * cellWidth; + origin.Y = origin.Y * cellHeight; + } + + public override void Draw(SpriteBatch spriteBatch, Vector2 pos, Color color, Vector2 origin, float rotate, Vector2 scale, SpriteEffects spriteEffect = SpriteEffects.None, float? depth = default(float?)) + { + if (texture == null) return; + + spriteBatch.Draw(texture, pos + offset, sourceRects[0], color, rotation + rotate, origin, scale, spriteEffect, depth == null ? this.depth : (float)depth); + } + + public void Draw(SpriteBatch spriteBatch, int spriteIndex, Vector2 pos, Color color, Vector2 origin, float rotate, Vector2 scale, SpriteEffects spriteEffect = SpriteEffects.None, float? depth = default(float?)) + { + if (texture == null) return; + + spriteBatch.Draw(texture, pos + offset, sourceRects[spriteIndex], color, rotation + rotate, origin, scale, spriteEffect, depth == null ? this.depth : (float)depth); + } + } +}