diff --git a/Subsurface/Barotrauma.csproj b/Subsurface/Barotrauma.csproj index 6d2a0a9cd..adfef498b 100644 --- a/Subsurface/Barotrauma.csproj +++ b/Subsurface/Barotrauma.csproj @@ -176,6 +176,7 @@ + @@ -422,6 +423,9 @@ PreserveNewest + + PreserveNewest + PreserveNewest @@ -852,12 +856,18 @@ PreserveNewest + + PreserveNewest + PreserveNewest PreserveNewest + + PreserveNewest + PreserveNewest diff --git a/Subsurface/Content/Characters/Human/fhead8.png b/Subsurface/Content/Characters/Human/fhead8.png new file mode 100644 index 000000000..39c08ea85 Binary files /dev/null and b/Subsurface/Content/Characters/Human/fhead8.png differ diff --git a/Subsurface/Content/Characters/Human/human.xml b/Subsurface/Content/Characters/Human/human.xml index 28b9914fe..b0f000efd 100644 --- a/Subsurface/Content/Characters/Human/human.xml +++ b/Subsurface/Content/Characters/Human/human.xml @@ -1,5 +1,5 @@  - + 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"> + [ @@ -101,15 +105,38 @@ namespace Barotrauma var newSprite = new BackgroundSprite(prefab, new Vector3((Vector2)pos, Rand.Range(prefab.DepthRange.X, prefab.DepthRange.Y, false)), Rand.Range(prefab.Scale.X, prefab.Scale.Y, false), rotation); + + //calculate the positions of the corners of the rotated sprite + Vector2 halfSize = newSprite.Prefab.Sprite.size * newSprite.Scale / 2; + var spriteCorners = new Vector2[] + { + -halfSize, new Vector2(-halfSize.X, halfSize.Y), + halfSize, new Vector2(halfSize.X, -halfSize.Y) + }; - Vector2 spriteSize = newSprite.Prefab.Sprite.size * newSprite.Scale; + Vector2 pivotOffset = newSprite.Prefab.Sprite.Origin * newSprite.Scale - halfSize; + pivotOffset.X = -pivotOffset.X; + pivotOffset = new Vector2( + (float)(pivotOffset.X * Math.Cos(-rotation) - pivotOffset.Y * Math.Sin(-rotation)), + (float)(pivotOffset.X * Math.Sin(-rotation) + pivotOffset.Y * Math.Cos(-rotation))); - int minX = (int)Math.Floor((newSprite.Position.X - spriteSize.X / 2 - newSprite.Position.Z) / GridSize); - int maxX = (int)Math.Floor((newSprite.Position.X + spriteSize.X / 2 + newSprite.Position.Z) / GridSize); + for (int j = 0; j < 4; j++) + { + spriteCorners[j] = new Vector2( + (float)(spriteCorners[j].X * Math.Cos(-rotation) - spriteCorners[j].Y * Math.Sin(-rotation)), + (float)(spriteCorners[j].X * Math.Sin(-rotation) + spriteCorners[j].Y * Math.Cos(-rotation))); + + spriteCorners[j] += (Vector2)pos + pivotOffset; + } + + //newSprite.spriteCorners = spriteCorners; + + int minX = (int)Math.Floor((spriteCorners.Min(c => c.X) - newSprite.Position.Z) / GridSize); + int maxX = (int)Math.Floor((spriteCorners.Max(c => c.X) + newSprite.Position.Z) / GridSize); if (minX < 0 || maxX >= sprites.GetLength(0)) continue; - int minY = (int)Math.Floor((newSprite.Position.Y - spriteSize.Y / 2 - newSprite.Position.Z) / GridSize); - int maxY = (int)Math.Floor((newSprite.Position.Y + spriteSize.Y / 2 + newSprite.Position.Z) / GridSize); + int minY = (int)Math.Floor((spriteCorners.Min(c => c.Y) - newSprite.Position.Z) / GridSize); + int maxY = (int)Math.Floor((spriteCorners.Max(c => c.Y) + newSprite.Position.Z) / GridSize); if (minY < 0 || maxY >= sprites.GetLength(1)) continue; for (int x = minX; x <= maxX; x++) @@ -266,7 +293,7 @@ namespace Barotrauma } foreach (BackgroundSprite sprite in visibleSprites) - { + { Vector2 camDiff = new Vector2(sprite.Position.X, sprite.Position.Y) - cam.WorldViewCenter; camDiff.Y = -camDiff.Y; @@ -279,6 +306,14 @@ namespace Barotrauma SpriteEffects.None, z); + /*for (int i = 0; i < 4; i++) + { + GUI.DrawLine(spriteBatch, + new Vector2(sprite.spriteCorners[i].X, -sprite.spriteCorners[i].Y), + new Vector2(sprite.spriteCorners[(i + 1) % 4].X, -sprite.spriteCorners[(i + 1) % 4].Y), + Color.White, 0, 5); + }*/ + if (GameMain.DebugDraw) { GUI.DrawRectangle(spriteBatch, new Vector2(sprite.Position.X, -sprite.Position.Y), new Vector2(10.0f, 10.0f), Color.Red, true); diff --git a/Subsurface/Source/Characters/BackgroundSprite/BackgroundSpritePrefab.cs b/Subsurface/Source/Characters/BackgroundSprite/BackgroundSpritePrefab.cs index 1568b2caf..f3df1563d 100644 --- a/Subsurface/Source/Characters/BackgroundSprite/BackgroundSpritePrefab.cs +++ b/Subsurface/Source/Characters/BackgroundSprite/BackgroundSpritePrefab.cs @@ -43,7 +43,7 @@ namespace Barotrauma Scale.X = ToolBox.GetAttributeFloat(element, "minsize", 1.0f); Scale.Y = ToolBox.GetAttributeFloat(element, "maxsize", 1.0f); - DepthRange = ToolBox.GetAttributeVector2(element, "depthrange", Vector2.Zero); + DepthRange = ToolBox.GetAttributeVector2(element, "depthrange", new Vector2(0.0f, 1.0f)); AlignWithSurface = ToolBox.GetAttributeBool(element, "alignwithsurface", false); diff --git a/Subsurface/Source/GUI/GUITextBlock.cs b/Subsurface/Source/GUI/GUITextBlock.cs index 8b3569a50..be8af4dba 100644 --- a/Subsurface/Source/GUI/GUITextBlock.cs +++ b/Subsurface/Source/GUI/GUITextBlock.cs @@ -187,21 +187,21 @@ namespace Barotrauma public void SetTextPos() { - if (text==null) return; + if (text == null) return; wrappedText = text; Vector2 size = MeasureText(text); - - if (Wrap && rect.Width>0) + + if (Wrap && rect.Width > 0) { - wrappedText = ToolBox.WrapText(text, rect.Width - padding.X - padding.Z, Font); + wrappedText = ToolBox.WrapText(text, rect.Width - padding.X - padding.Z, Font, textScale); Vector2 newSize = MeasureText(wrappedText); size = newSize; } - + if (LimitText && text.Length>1 && size.Y > rect.Height) { string[] lines = text.Split('\n'); diff --git a/Subsurface/Source/GameMain.cs b/Subsurface/Source/GameMain.cs index 7ab1ff275..78fc56525 100644 --- a/Subsurface/Source/GameMain.cs +++ b/Subsurface/Source/GameMain.cs @@ -69,6 +69,7 @@ namespace Barotrauma public static GameSettings Config; + private CoroutineHandle loadingCoroutine; private bool hasLoaded; private GameTime fixedTime; @@ -203,7 +204,7 @@ namespace Barotrauma loadingScreenOpen = true; TitleScreen = new LoadingScreen(GraphicsDevice); - CoroutineManager.StartCoroutine(Load()); + loadingCoroutine = CoroutineManager.StartCoroutine(Load()); } public IEnumerable Load() @@ -335,6 +336,14 @@ namespace Barotrauma { loadingScreenOpen = false; } + + if (!hasLoaded && !CoroutineManager.IsCoroutineRunning(loadingCoroutine)) + { + DebugConsole.ThrowError("Loading was interrupted due to an error"); + loadingScreenOpen = false; + loadingCoroutine = null; + hasLoaded = true; + } } else if (hasLoaded) { @@ -343,8 +352,6 @@ namespace Barotrauma if (PlayerInput.KeyHit(Keys.Escape)) GUI.TogglePauseMenu(); GUIComponent.ClearUpdateList(); - DebugConsole.AddToGUIUpdateList(); - paused = (DebugConsole.IsOpen || GUI.PauseMenuOpen || GUI.SettingsMenuOpen) && (NetworkMember == null || !NetworkMember.GameStarted); @@ -359,6 +366,7 @@ namespace Barotrauma } GUI.AddToGUIUpdateList(); + DebugConsole.AddToGUIUpdateList(); GUIComponent.UpdateMouseOn(); DebugConsole.Update(this, (float)Timing.Step); diff --git a/Subsurface/Source/Map/FireSource.cs b/Subsurface/Source/Map/FireSource.cs index c8defcb9e..44540daf4 100644 --- a/Subsurface/Source/Map/FireSource.cs +++ b/Subsurface/Source/Map/FireSource.cs @@ -145,7 +145,7 @@ namespace Barotrauma public void Update(float deltaTime) { float count = Rand.Range(0.0f, size.X/50.0f); - + if (hull.FireSources.Any(fs => fs != this && fs.size.X > size.X)) { if (basicSoundIndex > 0) @@ -174,41 +174,39 @@ namespace Barotrauma } } - if (size.X > 50.0f) + //the firesource will start to shrink if oxygen percentage is below 10 + float growModifier = Math.Min((hull.OxygenPercentage / 10.0f) - 1.0f, 1.0f); + + for (int i = 0; i < count; i++) { - this.position.Y = MathHelper.Lerp(this.position.Y, hull.Rect.Y - hull.Rect.Height, deltaTime); - } + Vector2 particlePos = new Vector2( + WorldPosition.X + Rand.Range(0.0f, size.X), + Rand.Range(WorldPosition.Y - size.Y, WorldPosition.Y + 20.0f)); - float growModifier = hull.OxygenPercentage < 20.0f ? (hull.OxygenPercentage/10.0f)-1.0f : 1.0f; + Vector2 particleVel = new Vector2( + (particlePos.X - (WorldPosition.X + size.X / 2.0f)), + (float)Math.Sqrt(size.X) * Rand.Range(0.0f, 15.0f) * growModifier); - for (int i = 0; i < count; i++ ) - { - Vector2 spawnPos = new Vector2(WorldPosition.X + Rand.Range(0.0f, size.X), Rand.Range(WorldPosition.Y - size.Y, WorldPosition.Y) + 10.0f); - - Vector2 speed = new Vector2((spawnPos.X - (WorldPosition.X + size.X / 2.0f)), (float)Math.Sqrt(size.X) * Rand.Range(10.0f, 15.0f) * growModifier); - var particle = GameMain.ParticleManager.CreateParticle("flame", - spawnPos, speed, 0.0f, hull); + particlePos, particleVel, 0.0f, hull); if (particle == null) continue; - + + //make some of the particles create another firesource when they enter another hull if (Rand.Int(20) == 1) particle.OnChangeHull = OnChangeHull; - particle.Size *= MathHelper.Clamp(size.X/60.0f * Math.Max(hull.Oxygen/hull.FullVolume, 0.4f), 0.5f, 3.0f); - - if (size.X < 100.0f) continue; + particle.Size *= MathHelper.Clamp(size.X / 60.0f * Math.Max(hull.Oxygen / hull.FullVolume, 0.4f), 0.5f, 1.0f); if (Rand.Int(5) == 1) { var smokeParticle = GameMain.ParticleManager.CreateParticle("smoke", - spawnPos, speed, 0.0f, hull); + particlePos, particleVel * 0.1f, 0.0f, hull); if (smokeParticle != null) { - smokeParticle.Size *= MathHelper.Clamp(size.X / 100.0f * Math.Max(hull.Oxygen / hull.FullVolume, 0.4f), 0.5f, 4.0f); + smokeParticle.Size *= MathHelper.Clamp(size.X / 100.0f * Math.Max(hull.Oxygen / hull.FullVolume, 0.4f), 0.5f, 1.0f); } } - } DamageCharacters(deltaTime); @@ -221,13 +219,22 @@ namespace Barotrauma position.X -= GrowSpeed * growModifier * 0.5f * deltaTime; size.X += GrowSpeed * growModifier * deltaTime; + size.Y = MathHelper.Clamp(size.Y + GrowSpeed * growModifier * deltaTime, 10.0f, 50.0f); + + if (size.X > 50.0f) + { + this.position.Y = MathHelper.Lerp(this.position.Y, hull.Rect.Y - hull.Rect.Height + size.Y, deltaTime); + } LimitSize(); lightSource.Range = Math.Max(size.X, size.Y) * 10.0f / 2.0f; lightSource.Color = new Color(1.0f, 0.45f, 0.3f) * Rand.Range(0.8f, 1.0f); - lightSource.Position = position; + lightSource.Position = position + Vector2.UnitY * 30.0f; + if (GameMain.Client != null) return; + + if (size.X < 1.0f) Remove(); } private void OnChangeHull(Vector2 pos, Hull particleHull) @@ -282,15 +289,19 @@ namespace Barotrauma private void HullWaterExtinquish(float deltaTime) { - float extinquishAmount = Math.Min(hull.Volume / 100.0f, size.X)*10.0f*deltaTime; + //the higher the surface of the water is relative to the firesource, the faster it puts out the fire + float extinquishAmount = (hull.Surface - (position.Y - size.Y)) * deltaTime; - float steamCount = Rand.Range(-5.0f, (float)Math.Sqrt(extinquishAmount)); + if (extinquishAmount < 0.0f) return; + float steamCount = Rand.Range(-5.0f, Math.Min(extinquishAmount * 100.0f, 10)); for (int i = 0; i < steamCount; i++) { - Vector2 spawnPos = new Vector2(position.X + size.X * (i / steamCount) + Rand.Range(-5.0f, 5.0f), Rand.Range(position.Y - size.Y, position.Y) + 10.0f); + Vector2 spawnPos = new Vector2( + WorldPosition.X + Rand.Range(0.0f, size.X), + Rand.Range(position.Y - size.Y, WorldPosition.Y) + 10.0f); - Vector2 speed = new Vector2((spawnPos.X - (position.X + size.X / 2.0f)), (float)Math.Sqrt(size.X) * Rand.Range(20.0f, 25.0f)); + Vector2 speed = new Vector2((spawnPos.X - (WorldPosition.X + size.X / 2.0f)), (float)Math.Sqrt(size.X) * Rand.Range(20.0f, 25.0f)); var particle = GameMain.ParticleManager.CreateParticle("steam", spawnPos, speed, 0.0f, hull); @@ -303,6 +314,7 @@ namespace Barotrauma position.X += extinquishAmount / 2.0f; size.X -= extinquishAmount; + //evaporate some of the water hull.Volume -= extinquishAmount; if (GameMain.Client != null) return; diff --git a/Subsurface/Source/Map/Hull.cs b/Subsurface/Source/Map/Hull.cs index c595c48f8..1df16a2b8 100644 --- a/Subsurface/Source/Map/Hull.cs +++ b/Subsurface/Source/Map/Hull.cs @@ -607,6 +607,11 @@ namespace Barotrauma GUI.SmallFont.DrawString(spriteBatch, "Pressure: " + ((int)pressure - rect.Y).ToString() + " - Oxygen: " + ((int)OxygenPercentage), new Vector2(drawRect.X + 5, -drawRect.Y + 5), Color.White); GUI.SmallFont.DrawString(spriteBatch, volume + " / " + FullVolume, new Vector2(drawRect.X + 5, -drawRect.Y + 20), Color.White); + + foreach (FireSource fs in fireSources) + { + GUI.DrawRectangle(spriteBatch, new Rectangle((int)fs.WorldPosition.X, (int)-fs.WorldPosition.Y, (int)fs.Size.X, (int)fs.Size.Y), Color.Orange, false); + } } if ((IsSelected || isHighlighted) && editing) diff --git a/Subsurface/Source/Map/Structure.cs b/Subsurface/Source/Map/Structure.cs index 0c9c10b53..d4077aa8f 100644 --- a/Subsurface/Source/Map/Structure.cs +++ b/Subsurface/Source/Map/Structure.cs @@ -654,9 +654,9 @@ namespace Barotrauma var section = sections[sectionIndex]; - int particleAmount = (int)(Math.Min(Health - section.damage, damage) * Rand.Range(0.01f, 1.0f)); + float particleAmount = Math.Min(Health - section.damage, damage) * Rand.Range(0.01f, 1.0f); - particleAmount = Math.Min(particleAmount, 200); + particleAmount = Math.Min(particleAmount + Rand.Range(-5,1), 100); for (int i = 0; i < particleAmount; i++) { Vector2 particlePos = new Vector2( diff --git a/Subsurface/Source/Particles/Particle.cs b/Subsurface/Source/Particles/Particle.cs index 9ac4d7b0c..1b8ffbd52 100644 --- a/Subsurface/Source/Particles/Particle.cs +++ b/Subsurface/Source/Particles/Particle.cs @@ -42,6 +42,9 @@ namespace Barotrauma.Particles private Hull currentHull; private List 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) { @@ -232,7 +245,7 @@ namespace Barotrauma.Particles velocity -= (velocity / speed) * Math.Min(speed * speed * prefab.WaterDrag * deltaTime, 1.0f); } - private void OnWallCollisionInside(Hull prevHull, Vector2 position) + private void OnWallCollisionInside(Hull prevHull, Vector2 edgePos) { Rectangle prevHullRect = prevHull.WorldRect; @@ -240,24 +253,24 @@ namespace Barotrauma.Particles velocity -= subVel; - if (position.Y < prevHullRect.Y - prevHullRect.Height) + if (edgePos.Y < prevHullRect.Y - prevHullRect.Height) { position.Y = prevHullRect.Y - prevHullRect.Height + prefab.CollisionRadius; velocity.Y = -velocity.Y; } - else if (position.Y > prevHullRect.Y) + else if (edgePos.Y > prevHullRect.Y) { position.Y = prevHullRect.Y - prefab.CollisionRadius; velocity.X = Math.Abs(velocity.Y) * Math.Sign(velocity.X); velocity.Y = -velocity.Y * 0.1f; } - if (position.X < prevHullRect.X) + if (edgePos.X < prevHullRect.X) { position.X = prevHullRect.X + prefab.CollisionRadius; velocity.X = -velocity.X; } - else if (position.X > prevHullRect.X + prevHullRect.Width) + else if (edgePos.X > prevHullRect.X + prevHullRect.Width) { position.X = prevHullRect.X + prevHullRect.Width - prefab.CollisionRadius; velocity.X = -velocity.X; @@ -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); + } + } +} diff --git a/Subsurface/Source/Utils/ToolBox.cs b/Subsurface/Source/Utils/ToolBox.cs index 1ac5eae40..2e60c0b6a 100644 --- a/Subsurface/Source/Utils/ToolBox.cs +++ b/Subsurface/Source/Utils/ToolBox.cs @@ -465,7 +465,7 @@ namespace Barotrauma return d[n, m]; } - public static string WrapText(string text, float lineLength, ScalableFont font) //TODO: could integrate this into the ScalableFont class directly + public static string WrapText(string text, float lineLength, ScalableFont font, float textScale = 1.0f) //TODO: could integrate this into the ScalableFont class directly { if (font.MeasureString(text).X < lineLength) return text; @@ -475,26 +475,35 @@ namespace Barotrauma StringBuilder wrappedText = new StringBuilder(); float linePos = 0f; - float spaceWidth = font.MeasureString(" ").X; + float spaceWidth = font.MeasureString(" ").X * textScale; for (int i = 0; i < words.Length; ++i) { if (string.IsNullOrWhiteSpace(words[i]) && words[i] != "\n") continue; - Vector2 size = font.MeasureString(words[i]); + Vector2 size = font.MeasureString(words[i]) * textScale; if (size.X > lineLength) { - while (words[i].Length > 0 && - (size = font.MeasureString((words[i][0]).ToString())).X + linePos < lineLength) + if (linePos == 0.0f) { - wrappedText.Append(words[i][0]); - words[i] = words[i].Remove(0, 1); + wrappedText.AppendLine(words[i]); + } + else + { + do + { + if (words[i].Length == 0) break; - linePos += size.X; + wrappedText.Append(words[i][0]); + words[i] = words[i].Remove(0, 1); + + linePos += size.X; + } while (words[i].Length > 0 && (size = font.MeasureString((words[i][0]).ToString()) * textScale).X + linePos < lineLength); + + wrappedText.Append("\n"); + linePos = 0.0f; + i--; } - wrappedText.Append("\n"); - linePos = 0.0f; - i--; continue; }