Animated fire & smoke particles

This commit is contained in:
Regalis
2017-03-30 21:32:08 +03:00
parent e661724cbb
commit c58d7dfd73
8 changed files with 132 additions and 24 deletions
+7
View File
@@ -60,6 +60,7 @@
<ApplicationIcon>Icon.ico</ApplicationIcon> <ApplicationIcon>Icon.ico</ApplicationIcon>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<Compile Include="Source\AnimatedSprite.cs" />
<Compile Include="Source\Camera.cs" /> <Compile Include="Source\Camera.cs" />
<Compile Include="Source\Characters\AICharacter.cs" /> <Compile Include="Source\Characters\AICharacter.cs" />
<Compile Include="Source\Characters\AI\AIController.cs" /> <Compile Include="Source\Characters\AI\AIController.cs" />
@@ -850,12 +851,18 @@
<Content Include="Content\Particles\fire.png"> <Content Include="Content\Particles\fire.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content> </Content>
<Content Include="Content\Particles\FlameRoundParticleSheet.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Content\Particles\flames.png"> <Content Include="Content\Particles\flames.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content> </Content>
<Content Include="Content\Particles\shrapnel.png"> <Content Include="Content\Particles\shrapnel.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content> </Content>
<Content Include="Content\Particles\SmokeParticleSheet.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Content\UI\damageOverlay.png"> <Content Include="Content\UI\damageOverlay.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content> </Content>
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

@@ -111,19 +111,20 @@
</shockwave> </shockwave>
<flame <flame
startsizemin="0.3,0.3" startsizemax="0.5,0.5" startsizemin="0.5,0.3" startsizemax="1.0,0.5"
sizechangemin="0.1,0.1" sizechangemax="0.2,0.2" sizechangemin="0.1,0.1" sizechangemax="0.2,0.2"
startrotationmin ="-20.0" startrotationmax="20" startrotationmin ="-20.0" startrotationmax="20"
startcolor="1.0, 1.0, 1.0" startalpha="1.0" startcolor="1.0, 1.0, 1.0" startalpha="1.0"
colorchange="-0.9, -1.5, -6.3, -1.2" colorchange="-0.9, -1.5, -6.3, -1.2"
lifetime="2.5" lifetime="2.5"
growtime ="0.05" growtime ="0.2"
drawtarget="air" drawtarget="air"
collideswithwalls="true" collideswithwalls="true"
blendstate="additive" blendstate="additive"
velocitychange="0.0, 2.5"> velocitychange="0.0, 2.5"
<sprite texture="Content/Particles/fire.png" sourcerect="0,0,96,96"/> animduration="1.2"
<sprite texture="Content/Particles/fire.png" sourcerect="96,0,96,96"/> loopanim="false">
<animatedsprite texture="Content/Particles/FlameRoundParticleSheet.png" sourcerect="0,0,2048,2048" columns="10" rows="5" origin="0.5,0.8"/>
</flame> </flame>
<steam <steam
@@ -144,14 +145,17 @@
startsizemin="0.4,0.4" startsizemax="0.5,0.5" startsizemin="0.4,0.4" startsizemax="0.5,0.5"
sizechangemin="0.25,0.25" sizechangemax="0.3,0.3" sizechangemin="0.25,0.25" sizechangemax="0.3,0.3"
startrotationmin ="0.0" startrotationmax="360" startrotationmin ="0.0" startrotationmax="360"
startcolor="0.0, 0.0, 0.0" startalpha="0.5" startcolor="0.0, 0.0, 0.0" startalpha="1.0"
colorchange="0.0, 0.0, 0.0, -0.25" colorchange="0.0, 0.0, 0.0, -0.25"
growtime ="0.2" growtime ="0.2"
lifetime="3" lifetime="5"
collideswithwalls="true" collideswithwalls="true"
collisionradius="30.0" collisionradius="80.0"
velocitychange="0.0, 2.5"> velocitychange="0.0, 2.5"
<sprite texture="Content/Particles/spatter.png" sourcerect="128,128,128,128"/> animduration="4"
restitution="0.98"
loopanim="false">
<animatedsprite texture="Content/Particles/SmokeParticleSheet.png" sourcerect="0,0,1024,1024" columns="5" rows="5"/>
</smoke> </smoke>
<explosionfire <explosionfire
Binary file not shown.

After

Width:  |  Height:  |  Size: 621 KiB

+32 -5
View File
@@ -42,6 +42,9 @@ namespace Barotrauma.Particles
private Hull currentHull; private Hull currentHull;
private List<Gap> hullGaps; private List<Gap> hullGaps;
private float animState;
private int animFrame;
public ParticlePrefab.DrawTargetType DrawTarget public ParticlePrefab.DrawTargetType DrawTarget
{ {
@@ -77,6 +80,9 @@ namespace Barotrauma.Particles
spriteIndex = Rand.Int(prefab.Sprites.Count); spriteIndex = Rand.Int(prefab.Sprites.Count);
animState = 0;
animFrame = 0;
currentHull = Hull.FindHull(position, hullGuess); currentHull = Hull.FindHull(position, hullGuess);
this.position = position; this.position = position;
@@ -166,6 +172,13 @@ namespace Barotrauma.Particles
color.R / 255.0f + prefab.ColorChange.X * deltaTime, color.R / 255.0f + prefab.ColorChange.X * deltaTime,
color.G / 255.0f + prefab.ColorChange.Y * deltaTime, color.G / 255.0f + prefab.ColorChange.Y * deltaTime,
color.B / 255.0f + prefab.ColorChange.Z * 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) if (prefab.DeleteOnCollision || prefab.CollidesWithWalls)
{ {
@@ -317,11 +330,25 @@ namespace Barotrauma.Particles
drawSize *= ((totalLifeTime - lifeTime) / prefab.GrowTime); drawSize *= ((totalLifeTime - lifeTime) / prefab.GrowTime);
} }
prefab.Sprites[spriteIndex].Draw(spriteBatch, if (prefab.Sprites[spriteIndex] is SpriteSheet)
new Vector2(drawPosition.X, -drawPosition.Y), {
color * alpha, ((SpriteSheet)prefab.Sprites[spriteIndex]).Draw(
prefab.Sprites[spriteIndex].Origin, drawRotation, spriteBatch, animFrame,
drawSize, SpriteEffects.None, prefab.Sprites[spriteIndex].Depth); 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);
}
} }
} }
} }
+19 -4
View File
@@ -13,6 +13,9 @@ namespace Barotrauma.Particles
public readonly List<Sprite> Sprites; public readonly List<Sprite> Sprites;
public readonly float AnimDuration;
public readonly bool LoopAnim;
public readonly float AngularVelocityMin, AngularVelocityMax; public readonly float AngularVelocityMin, AngularVelocityMax;
public readonly float StartRotationMin, StartRotationMax; public readonly float StartRotationMin, StartRotationMax;
@@ -53,11 +56,21 @@ namespace Barotrauma.Particles
foreach (XElement subElement in element.Elements()) foreach (XElement subElement in element.Elements())
{ {
if (subElement.Name.ToString().ToLowerInvariant() != "sprite") continue; switch (subElement.Name.ToString().ToLowerInvariant())
{
Sprites.Add(new Sprite(subElement)); 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) if (element.Attribute("angularvelocity") == null)
{ {
AngularVelocityMin = ToolBox.GetAttributeFloat(element, "angularvelocitymin", 0.0f); AngularVelocityMin = ToolBox.GetAttributeFloat(element, "angularvelocitymin", 0.0f);
@@ -134,7 +147,9 @@ namespace Barotrauma.Particles
DeleteOnCollision = ToolBox.GetAttributeBool(element, "deleteoncollision", false); DeleteOnCollision = ToolBox.GetAttributeBool(element, "deleteoncollision", false);
CollidesWithWalls = ToolBox.GetAttributeBool(element, "collideswithwalls", 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); ColorChange = ToolBox.GetAttributeVector4(element, "colorchange", Vector4.Zero);
+5 -5
View File
@@ -14,15 +14,15 @@ namespace Barotrauma
//if two sprites use the same file, they share the same texture //if two sprites use the same file, they share the same texture
string file; string file;
Texture2D texture; protected Texture2D texture;
//the area in the texture that is supposed to be drawn //the area in the texture that is supposed to be drawn
Rectangle sourceRect; Rectangle sourceRect;
//the offset used when drawing the sprite //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 size of the drawn sprite, if larger than the source,
//the sprite is tiled to fill the target size //the sprite is tiled to fill the target size
@@ -32,7 +32,7 @@ namespace Barotrauma
public SpriteEffects effects; public SpriteEffects effects;
float depth; protected float depth;
public Rectangle SourceRect public Rectangle SourceRect
{ {
@@ -202,7 +202,7 @@ namespace Barotrauma
this.Draw(spriteBatch, pos, color, origin, rotate, new Vector2(scale, scale), spriteEffect, depth); 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) //for (int x = -1; x <= 1; x += 2)
//{ //{
+55
View File
@@ -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);
}
}
}