new doors

This commit is contained in:
Regalis
2015-05-25 19:41:30 +03:00
parent fadb89ae9e
commit a1196d1876
12 changed files with 3494 additions and 3446 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -1,41 +1,41 @@
<Items>
<Item
name="Door"
linkable="true"
pickdistance="150.0">
<Sprite texture ="doorframe.png" depth="0.8" origin="0.5,0.5"/>
<Door>
<Sprite texture ="door.png" depth="0.4" origin="0.5,0.0"/>
</Door>
<ConnectionPanel canbeselected = "true">
<requireditem name="Screwdriver" type="Equipped"/>
<input name="toggle"/>
<input name="set_state"/>
<output name="state_out"/>
</ConnectionPanel>
</Item>
<Item
name="Windowed Door"
linkable="true"
pickdistance="150.0">
<Sprite texture ="doorframe.png" depth="0.8" origin="0.5,0.5"/>
<Door window="0,-18,10,89">
<Sprite texture ="windowedDoor.png" depth="0.4" origin="0.5,0.0"/>
</Door>
<ConnectionPanel canbeselected = "true">
<requireditem name="Screwdriver" type="Equipped"/>
<input name="toggle"/>
<input name="set_state"/>
<output name="state_out"/>
</ConnectionPanel>
</Item>
<Items>
<Item
name="Door"
linkable="true"
pickdistance="150.0">
<Sprite texture ="door.png" sourcerect="0,0,48,208" depth="0.8" origin="0.5,0.5"/>
<Door>
<Sprite texture ="door.png" sourcerect="80,0,19,208" depth="0.4" origin="0.5,0.0"/>
</Door>
<ConnectionPanel canbeselected = "true">
<requireditem name="Screwdriver" type="Equipped"/>
<input name="toggle"/>
<input name="set_state"/>
<output name="state_out"/>
</ConnectionPanel>
</Item>
<Item
name="Windowed Door"
linkable="true"
pickdistance="150.0">
<Sprite texture ="door.png" sourcerect="0,0,48,208" depth="0.8" origin="0.5,0.5"/>
<Door window="0,-18,10,89">
<Sprite texture ="door.png" sourcerect="56,0,19,208" depth="0.4" origin="0.5,0.0"/>
</Door>
<ConnectionPanel canbeselected = "true">
<requireditem name="Screwdriver" type="Equipped"/>
<input name="toggle"/>
<input name="set_state"/>
<output name="state_out"/>
</ConnectionPanel>
</Item>
</Items>

View File

@@ -1,73 +1,73 @@
<?xml version="1.0" encoding="utf-8" ?>
<prefabs>
<watersplash sprite="Content/Particles/spatter.png"
startsizemin="0.15,0.15" startsizemax="0.3,0.3"
sizechangemin="0.9,0.9" sizechangemax="1.2,1.2"
startrotationmin ="0.0" startrotationmax="3.14"
startcolor="1.0, 1.0, 1.0" startalpha="0.8"
colorchange="0.0, 0.0, 0.0, -0.25"
lifetime="3"
deleteonhit="true"
velocitychange="0.0, -9.8"/>
<mist sprite="Content/Particles/spatter.png"
startsizemin="0.2,0.2" startsizemax="0.3,0.3"
sizechangemin="0.5,0.5" sizechangemax="0.5,0.5"
startrotationmin ="0.0" startrotationmax="3.14"
startcolor="1.0, 1.0, 1.0" startalpha="0.5"
colorchange="0.0, 0.0, 0.0, -0.25"
lifetime="3"
velocitychange="0.0, -0.05"/>
<dustcloud sprite="Content/Particles/spatter.png"
startsizemin="0.8,0.8" startsizemax="1.0,1.0"
sizechangemin="0.0,0.0" sizechangemax="0.0,0.0"
startrotationmin ="0.0" startrotationmax="3.14"
startcolor="0.2, 0.2, 0.2" startalpha="0.5"
colorchange="0.0, 0.0, 0.0, -0.3"
lifetime="3"
velocitychange="0.0, -5.0"/>
<bubbles sprite="Content/Particles/bubbles.png"
startsizemin="0.4,0.4" startsizemax="0.5,0.5"
sizechangemin="0.0,0.0" sizechangemax="0.1,0.1"
startrotationmin ="0.0" startrotationmax="3.14"
startcolor="1.0, 1.0, 1.0" startalpha="0.8"
colorchange="0.0, 0.0, 0.0, -0.5"
lifetime="3"
deleteonhit="true"
inwater="true"
velocitychange="0.0, 0.1"/>
<blood sprite="Content/Particles/blood.png"
startsizemin="0.05,0.05" startsizemax="0.6,0.6"
sizechangemin="0.3,0.2" sizechangemax="0.4,0.2"
startrotationmin ="0.0" startrotationmax="0.0"
startcolor="0.5, 0.0, 0.0" startalpha="1.0"
colorchange="0.0, 0.0, 0.0, -1.0"
lifetime="2"
deleteonhit="true"
rotatetodirection="true"
velocitychange="0.0, -9.8"/>
<waterblood sprite="Content/Particles/spatter.png"
startsizemin="0.1,0.1" startsizemax="0.1,0.1"
sizechangemin="0.15,0.15" sizechangemax="0.2,0.2"
startrotationmin ="0.0" startrotationmax="3.14"
startcolor="0.5, 0.0, 0.0" startalpha="1.0"
colorchange="0.0, 0.0, 0.0, -0.25"
lifetime="5.0"
inwater="true"
velocitychange="0.0, 0.0"/>
<explosionfire sprite="Content/Particles/explosion.png"
startsizemin="1.5,1.5" startsizemax="3.0,3.0"
sizechangemin="0.5,0.5" sizechangemax="0.6,0.6"
startrotationmin ="0.0" startrotationmax="3.14"
startcolor="1.0, 1.0, 1.0" startalpha="1.0"
colorchange="-0.4, -0.4, -0.4, -0.3"
lifetime="5.0"
inwater="false"
deleteonhit="true"
velocitychange="0.0, 0.5"/>
</prefabs>
<?xml version="1.0" encoding="utf-8" ?>
<prefabs>
<watersplash sprite="Content/Particles/spatter.png"
startsizemin="0.15,0.15" startsizemax="0.3,0.3"
sizechangemin="0.9,0.9" sizechangemax="1.2,1.2"
startrotationmin ="0.0" startrotationmax="6.28"
startcolor="1.0, 1.0, 1.0" startalpha="0.8"
colorchange="0.0, 0.0, 0.0, -0.25"
lifetime="3"
deleteonhit="true"
velocitychange="0.0, -9.8"/>
<mist sprite="Content/Particles/spatter.png"
startsizemin="0.4,0.4" startsizemax="0.5,0.5"
sizechangemin="0.25,0.25" sizechangemax="0.3,0.3"
startrotationmin ="0.0" startrotationmax="6.28"
startcolor="1.0, 1.0, 1.0" startalpha="0.5"
colorchange="0.0, 0.0, 0.0, -0.25"
lifetime="3"
velocitychange="0.0, -0.05"/>
<dustcloud sprite="Content/Particles/spatter.png"
startsizemin="0.8,0.8" startsizemax="1.0,1.0"
sizechangemin="0.0,0.0" sizechangemax="0.0,0.0"
startrotationmin ="0.0" startrotationmax="6.28"
startcolor="0.2, 0.2, 0.2" startalpha="0.5"
colorchange="0.0, 0.0, 0.0, -0.3"
lifetime="3"
velocitychange="0.0, -5.0"/>
<bubbles sprite="Content/Particles/bubbles.png"
startsizemin="0.4,0.4" startsizemax="0.5,0.5"
sizechangemin="0.0,0.0" sizechangemax="0.1,0.1"
startrotationmin ="0.0" startrotationmax="3.14"
startcolor="1.0, 1.0, 1.0" startalpha="0.8"
colorchange="0.0, 0.0, 0.0, -0.5"
lifetime="3"
deleteonhit="true"
inwater="true"
velocitychange="0.0, 0.1"/>
<blood sprite="Content/Particles/blood.png"
startsizemin="0.05,0.05" startsizemax="0.6,0.6"
sizechangemin="0.3,0.2" sizechangemax="0.4,0.2"
startrotationmin ="0.0" startrotationmax="0.0"
startcolor="0.5, 0.0, 0.0" startalpha="1.0"
colorchange="0.0, 0.0, 0.0, -1.0"
lifetime="2"
deleteonhit="true"
rotatetodirection="true"
velocitychange="0.0, -9.8"/>
<waterblood sprite="Content/Particles/spatter.png"
startsizemin="0.1,0.1" startsizemax="0.1,0.1"
sizechangemin="0.15,0.15" sizechangemax="0.2,0.2"
startrotationmin ="0.0" startrotationmax="6.28"
startcolor="0.5, 0.0, 0.0" startalpha="1.0"
colorchange="0.0, 0.0, 0.0, -0.25"
lifetime="5.0"
inwater="true"
velocitychange="0.0, 0.0"/>
<explosionfire sprite="Content/Particles/explosion.png"
startsizemin="1.5,1.5" startsizemax="3.0,3.0"
sizechangemin="0.5,0.5" sizechangemax="0.6,0.6"
startrotationmin ="0.0" startrotationmax="6.28"
startcolor="1.0, 1.0, 1.0" startalpha="1.0"
colorchange="-0.4, -0.4, -0.4, -0.3"
lifetime="5.0"
inwater="false"
deleteonhit="true"
velocitychange="0.0, 0.5"/>
</prefabs>

View File

@@ -1,267 +1,304 @@
using System;
using System.IO;
using System.Xml.Linq;
using FarseerPhysics;
using FarseerPhysics.Dynamics;
using FarseerPhysics.Factories;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Subsurface.Lights;
namespace Subsurface.Items.Components
{
class Door : ItemComponent
{
Gap linkedGap;
Rectangle window;
ConvexHull convexHull;
ConvexHull convexHull2;
Gap LinkedGap
{
get
{
if (linkedGap != null) return linkedGap;
foreach (MapEntity e in item.linkedTo)
{
linkedGap = e as Gap;
if (linkedGap != null) return linkedGap;
}
linkedGap = new Gap(item.Rect);
linkedGap.Open = openState;
item.linkedTo.Add(linkedGap);
return linkedGap;
}
}
bool isOpen;
float openState;
[HasDefaultValue("0.0,0.0,0.0,0.0", false)]
public string Window
{
get { return ToolBox.Vector4ToString(new Vector4(window.X, window.Y, window.Width, window.Height)); }
set
{
Vector4 vector = ToolBox.ParseToVector4(value);
if (vector.Z!=0.0f || vector.W !=0.0f)
{
window = new Rectangle((int)vector.X, (int)vector.Y, (int)vector.Z, (int)vector.W);
}
}
}
[Editable, HasDefaultValue(false, true)]
public bool IsOpen
{
get { return isOpen; }
set
{
isOpen = value;
openState = (isOpen) ? 1.0f : 0.0f;
}
}
public float OpenState
{
get { return openState; }
set
{
if (openState == value) return;
openState = MathHelper.Clamp(value, 0.0f, 1.0f);
if (window==null)
{
Rectangle rect = item.Rect;
rect.Height = (int)(rect.Height * (1.0f - openState));
}
else
{
//Rectangle rect = item.Rect;
//rect.Height = (int)(rect.Height * (1.0f - openState));
Rectangle rect1 = item.Rect;
rect1.Height = -window.Y;
rect1.Y += (int)(item.Rect.Height * openState);
rect1.Height = Math.Max(rect1.Height - (rect1.Y - item.Rect.Y), 0);
rect1.Y = Math.Min(item.Rect.Y, rect1.Y);
Rectangle rect2 = item.Rect;
rect2.Y = rect2.Y + window.Y - window.Height;
rect2.Y += (int)(item.Rect.Height * openState);
//rect2.Height = Math.Max(rect2.Height - (rect2.Y - item.Rect.Y), 0);
rect2.Y = Math.Min(item.Rect.Y, rect2.Y);
rect2.Height = rect2.Y - (item.Rect.Y - (int)(item.Rect.Height * (1.0f - openState)));
convexHull.SetVertices(GetConvexHullCorners(rect1));
if (convexHull2!=null) convexHull2.SetVertices(GetConvexHullCorners(rect2));
}
}
}
PhysicsBody body;
Sprite doorSprite;
public Door(Item item, XElement element)
: base(item, element)
{
//Vector2 position = new Vector2(newRect.X, newRect.Y);
// isOpen = false;
body = new PhysicsBody(BodyFactory.CreateRectangle(Game1.world,
ConvertUnits.ToSimUnits(Math.Max(item.Rect.Width, 1)),
ConvertUnits.ToSimUnits(Math.Max(item.Rect.Height, 1)),
1.5f));
body.BodyType = BodyType.Static;
body.SetTransform(
ConvertUnits.ToSimUnits(new Vector2(item.Rect.X + item.Rect.Width / 2, item.Rect.Y - item.Rect.Height / 2)),
0.0f);
body.Friction = 0.5f;
//string spritePath = Path.GetDirectoryName(item.Prefab.ConfigFile) + "\\"+ ToolBox.GetAttributeString(element, "sprite", "");
foreach (XElement subElement in element.Elements())
{
if (subElement.Name.ToString().ToLower() != "sprite") continue;
doorSprite = new Sprite(subElement, Path.GetDirectoryName(item.Prefab.ConfigFile));
break;
}
isActive = true;
Vector2[] corners = GetConvexHullCorners(item.Rect);
convexHull = new ConvexHull(corners, Color.Black);
if (window!=null) convexHull2 = new ConvexHull(corners, Color.Black);
OpenState = openState;
//powerConsumption = -100.0f;
//LinkedGap.Open = openState;
}
private Vector2[] GetConvexHullCorners(Rectangle rect)
{
Vector2[] corners = new Vector2[4];
corners[0] = new Vector2(rect.X, rect.Y - rect.Height);
corners[1] = new Vector2(rect.X, rect.Y);
corners[2] = new Vector2(rect.Right, rect.Y);
corners[3] = new Vector2(rect.Right, rect.Y - rect.Height);
return corners;
}
public override void Move(Vector2 amount)
{
base.Move(amount);
body.SetTransform(body.Position + ConvertUnits.ToSimUnits(amount), 0.0f);
convexHull.Move(amount);
}
public override bool Pick(Character picker)
{
isActive = true;
isOpen = !isOpen;
return true;
}
public override void Update(float deltaTime, Camera cam)
{
OpenState += deltaTime * ((isOpen) ? 3.0f : -3.0f);
item.SendSignal((isOpen) ? "1" : "0", "state_out");
}
public override void Draw(SpriteBatch spriteBatch)
{
LinkedGap.Open = openState;
Color color = (item.IsSelected) ? Color.Green : Color.White;
//prefab.sprite.Draw(spriteBatch, new Vector2(rect.X, -rect.Y), new Vector2(rect.Width, rect.Height), color);
if (openState == 1.0f)
{
body.Enabled = false;
convexHull.Enabled = false;
}
else
{
spriteBatch.Draw(doorSprite.Texture, new Vector2(item.Rect.Center.X, -item.Rect.Y),
new Rectangle(0, (int)(doorSprite.size.Y * openState),
(int)doorSprite.size.X, (int)(doorSprite.size.Y * (1.0f - openState))),
color, 0.0f, doorSprite.Origin, 1.0f, SpriteEffects.None, doorSprite.Depth);
convexHull.Enabled = true;
if (openState == 0.0f)
{
body.Enabled = true;
}
else
{
//push characters out of the doorway when the door is closing/opening
Vector2 simPos = ConvertUnits.ToSimUnits(new Vector2(item.Rect.X, item.Rect.Y));
Vector2 simSize = ConvertUnits.ToSimUnits(new Vector2(item.Rect.Width,
item.Rect.Height * (1.0f - openState)));
foreach (Character c in Character.characterList)
{
int dir = Math.Sign(c.animController.limbs[0].SimPosition.X - simPos.X);
foreach (Limb l in c.animController.limbs)
{
if (l.SimPosition.Y < simPos.Y || l.SimPosition.Y > simPos.Y - simSize.Y) continue;
if (Math.Abs(l.SimPosition.X - simPos.X) > simSize.X * 2.0f) continue;
l.body.ApplyForce(new Vector2(dir * 10.0f, 0.0f));
}
}
}
}
}
public override void Remove()
{
base.Remove();
Game1.world.RemoveBody(body.FarseerBody);
doorSprite.Remove();
convexHull.Remove();
if (convexHull2 != null) convexHull2.Remove();
}
public override void ReceiveSignal(string signal, Connection connection, Item sender)
{
isActive = true;
if (connection.name=="toggle")
{
isOpen = !isOpen;
}
else if (connection.name == "set_state")
{
isOpen = (signal!="0");
}
}
}
}
using System;
using System.IO;
using System.Xml.Linq;
using FarseerPhysics;
using FarseerPhysics.Dynamics;
using FarseerPhysics.Factories;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Subsurface.Lights;
namespace Subsurface.Items.Components
{
class Door : ItemComponent
{
Gap linkedGap;
Rectangle window;
ConvexHull convexHull;
ConvexHull convexHull2;
Gap LinkedGap
{
get
{
if (linkedGap != null) return linkedGap;
foreach (MapEntity e in item.linkedTo)
{
linkedGap = e as Gap;
if (linkedGap != null) return linkedGap;
}
linkedGap = new Gap(item.Rect);
linkedGap.Open = openState;
item.linkedTo.Add(linkedGap);
return linkedGap;
}
}
bool isOpen;
float openState;
[HasDefaultValue("0.0,0.0,0.0,0.0", false)]
public string Window
{
get { return ToolBox.Vector4ToString(new Vector4(window.X, window.Y, window.Width, window.Height)); }
set
{
Vector4 vector = ToolBox.ParseToVector4(value);
if (vector.Z!=0.0f || vector.W !=0.0f)
{
window = new Rectangle((int)vector.X, (int)vector.Y, (int)vector.Z, (int)vector.W);
}
}
}
[Editable, HasDefaultValue(false, true)]
public bool IsOpen
{
get { return isOpen; }
set
{
isOpen = value;
openState = (isOpen) ? 1.0f : 0.0f;
}
}
private Rectangle doorRect;
public float OpenState
{
get { return openState; }
set
{
if (openState == value) return;
openState = MathHelper.Clamp(value, 0.0f, 1.0f);
if (window==null)
{
Rectangle rect = item.Rect;
rect.Height = (int)(rect.Height * (1.0f - openState));
}
else
{
//Rectangle rect = item.Rect;
//rect.Height = (int)(rect.Height * (1.0f - openState));
Rectangle rect1 = doorRect;
rect1.Height = -window.Y;
rect1.Y += (int)(doorRect.Height * openState);
rect1.Height = Math.Max(rect1.Height - (rect1.Y - doorRect.Y), 0);
rect1.Y = Math.Min(doorRect.Y, rect1.Y);
if (rect1.Height == 0)
{
convexHull.Enabled = false;
}
else
{
convexHull.SetVertices(GetConvexHullCorners(rect1));
}
if (convexHull2 != null)
{
Rectangle rect2 = doorRect;
rect2.Y = rect2.Y + window.Y - window.Height;
rect2.Y += (int)(doorRect.Height * openState);
rect2.Y = Math.Min(doorRect.Y, rect2.Y);
rect2.Height = rect2.Y - (doorRect.Y - (int)(doorRect.Height * (1.0f - openState)));
convexHull2.SetVertices(GetConvexHullCorners(rect2));
if (rect2.Height == 0)
{
convexHull2.Enabled = false;
}
else
{
convexHull2.SetVertices(GetConvexHullCorners(rect2));
}
}
}
}
}
PhysicsBody body;
Sprite doorSprite;
public Door(Item item, XElement element)
: base(item, element)
{
//Vector2 position = new Vector2(newRect.X, newRect.Y);
// isOpen = false;
foreach (XElement subElement in element.Elements())
{
if (subElement.Name.ToString().ToLower() != "sprite") continue;
doorSprite = new Sprite(subElement, Path.GetDirectoryName(item.Prefab.ConfigFile));
break;
}
doorRect = new Rectangle(
item.Rect.Center.X - (int)(doorSprite.size.X / 2),
item.Rect.Y,
(int)doorSprite.size.X,
(int)doorSprite.size.Y);
body = new PhysicsBody(BodyFactory.CreateRectangle(Game1.world,
ConvertUnits.ToSimUnits(Math.Max(doorRect.Width, 1)),
ConvertUnits.ToSimUnits(Math.Max(doorRect.Height, 1)),
1.5f));
body.BodyType = BodyType.Static;
body.SetTransform(
ConvertUnits.ToSimUnits(new Vector2(doorRect.Center.X, doorRect.Y - doorRect.Height / 2)),
0.0f);
body.Friction = 0.5f;
//string spritePath = Path.GetDirectoryName(item.Prefab.ConfigFile) + "\\"+ ToolBox.GetAttributeString(element, "sprite", "");
isActive = true;
Vector2[] corners = GetConvexHullCorners(doorRect);
convexHull = new ConvexHull(corners, Color.Black);
if (window!=null) convexHull2 = new ConvexHull(corners, Color.Black);
OpenState = openState;
//powerConsumption = -100.0f;
//LinkedGap.Open = openState;
}
private Vector2[] GetConvexHullCorners(Rectangle rect)
{
Vector2[] corners = new Vector2[4];
corners[0] = new Vector2(rect.X, rect.Y - rect.Height);
corners[1] = new Vector2(rect.X, rect.Y);
corners[2] = new Vector2(rect.Right, rect.Y);
corners[3] = new Vector2(rect.Right, rect.Y - rect.Height);
return corners;
}
public override void Move(Vector2 amount)
{
base.Move(amount);
linkedGap.Move(amount);
body.SetTransform(body.Position + ConvertUnits.ToSimUnits(amount), 0.0f);
convexHull.Move(amount);
if (convexHull2 != null) convexHull2.Move(amount);
}
public override bool Pick(Character picker)
{
isActive = true;
isOpen = !isOpen;
return true;
}
public override void Update(float deltaTime, Camera cam)
{
OpenState += deltaTime * ((isOpen) ? 3.0f : -3.0f);
item.SendSignal((isOpen) ? "1" : "0", "state_out");
}
public override void Draw(SpriteBatch spriteBatch)
{
LinkedGap.Open = openState;
Color color = (item.IsSelected) ? Color.Green : Color.White;
//prefab.sprite.Draw(spriteBatch, new Vector2(rect.X, -rect.Y), new Vector2(rect.Width, rect.Height), color);
if (openState == 1.0f)
{
body.Enabled = false;
convexHull.Enabled = false;
}
else
{
spriteBatch.Draw(doorSprite.Texture, new Vector2(item.Rect.Center.X, -item.Rect.Y),
new Rectangle(doorSprite.SourceRect.X, (int)(doorSprite.size.Y * openState),
(int)doorSprite.size.X, (int)(doorSprite.size.Y * (1.0f - openState))),
color, 0.0f, doorSprite.Origin, 1.0f, SpriteEffects.None, doorSprite.Depth);
convexHull.Enabled = true;
if (openState == 0.0f)
{
body.Enabled = true;
}
else
{
//push characters out of the doorway when the door is closing/opening
Vector2 simPos = ConvertUnits.ToSimUnits(new Vector2(item.Rect.X, item.Rect.Y));
Vector2 simSize = ConvertUnits.ToSimUnits(new Vector2(item.Rect.Width,
item.Rect.Height * (1.0f - openState)));
foreach (Character c in Character.characterList)
{
int dir = Math.Sign(c.animController.limbs[0].SimPosition.X - simPos.X);
foreach (Limb l in c.animController.limbs)
{
if (l.SimPosition.Y < simPos.Y || l.SimPosition.Y > simPos.Y - simSize.Y) continue;
if (Math.Abs(l.SimPosition.X - simPos.X) > simSize.X * 2.0f) continue;
l.body.ApplyForce(new Vector2(dir * 10.0f, 0.0f));
}
}
}
}
}
public override void Remove()
{
base.Remove();
Game1.world.RemoveBody(body.FarseerBody);
linkedGap.Remove();
doorSprite.Remove();
convexHull.Remove();
if (convexHull2 != null) convexHull2.Remove();
}
public override void ReceiveSignal(string signal, Connection connection, Item sender)
{
isActive = true;
if (connection.name=="toggle")
{
isOpen = !isOpen;
}
else if (connection.name == "set_state")
{
isOpen = (signal!="0");
}
}
}
}

View File

@@ -1,219 +1,218 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Xml.Linq;
using FarseerPhysics;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
namespace Subsurface
{
class ItemPrefab : MapEntityPrefab
{
static string contentFolder = "Content/Items/";
string configFile;
//should the camera focus on the construction when selected
protected bool focusOnSelected;
//the amount of "camera offset" when selecting the construction
protected float offsetOnSelected;
//default size
protected Vector2 size;
//how close the character has to be to the item to pick it up
float pickDistance;
public List<Sound> sounds;
//an area next to the construction
//the construction can be Activated() by a character inside the area
public List<Rectangle> triggers;
public string ConfigFile
{
get { return configFile; }
}
public float PickDistance
{
get { return pickDistance; }
}
public override bool IsLinkable
{
get { return isLinkable; }
}
public bool FocusOnSelected
{
get { return focusOnSelected; }
}
public float OffsetOnSelected
{
get { return offsetOnSelected; }
}
public override void UpdatePlacing(SpriteBatch spriteBatch, Camera cam)
{
Vector2 position = new Vector2(PlayerInput.GetMouseState.X, PlayerInput.GetMouseState.Y);
position = cam.ScreenToWorld(position);
if (!resizeHorizontal && !resizeVertical)
{
if (PlayerInput.LeftButtonClicked())
{
new Item(new Rectangle((int)position.X, (int)position.Y, (int)sprite.size.X, (int)sprite.size.Y), this);
//constructor.Invoke(lobject);
placePosition = Vector2.Zero;
selected = null;
return;
}
sprite.Draw(spriteBatch, new Vector2(position.X + sprite.size.X / 2.0f, -position.Y + sprite.size.Y / 2.0f));
}
else
{
Vector2 placeSize = size;
if (placePosition == Vector2.Zero)
{
if (PlayerInput.GetMouseState.LeftButton == ButtonState.Pressed)
placePosition = position;
}
else
{
if (resizeHorizontal)
placeSize.X = Math.Max(position.X - placePosition.X, size.X);
if (resizeVertical)
placeSize.Y = Math.Max(placePosition.Y - position.Y, size.Y);
if (PlayerInput.GetMouseState.LeftButton == ButtonState.Released)
{
new Item(new Rectangle((int)placePosition.X, (int)placePosition.Y, (int)placeSize.X, (int)placeSize.Y), this);
selected = null;
return;
}
position = placePosition;
}
sprite.DrawTiled(spriteBatch, new Vector2(position.X, -position.Y), placeSize, Color.White);
}
if (PlayerInput.GetMouseState.RightButton == ButtonState.Pressed) selected = null;
}
public static void LoadAll()
{
string[] files = Directory.GetFiles(contentFolder, "*.xml", SearchOption.AllDirectories);
foreach (string filePath in files)
{
XDocument doc = ToolBox.TryLoadXml(filePath);
if (doc == null) return;
if (doc.Root.Name.ToString().ToLower() == "item")
{
new ItemPrefab(doc.Root, filePath);
}
else
{
foreach (XElement element in doc.Root.Elements())
{
if (element.Name.ToString().ToLower() != "item") continue;
new ItemPrefab(element, filePath);
}
}
}
}
public ItemPrefab (XElement element, string filePath)
{
configFile = filePath;
name = ToolBox.GetAttributeString(element, "name", "");
if (name == "") DebugConsole.ThrowError("Unnamed item in "+filePath+"!");
//if (element.Attribute("sprite") != null)
//{
// sprite = new Sprite(Path.GetDirectoryName(filePath) + "/" + element.Attribute("sprite").Value, new Vector2(0.5f, 0.5f));
// sprite.Depth = 0.5f;
//}
//var initableProperties = GetProperties<Initable>();
//foreach (ObjectProperty initableProperty in initableProperties)
//{
// object value = ToolBox.GetAttributeObject(element, initableProperty.Name.ToLower());
// if (value == null)
// {
// foreach (var ini in initableProperty.Attributes.OfType<Initable>())
// {
// value = ini.defaultValue;
// break;
// }
// }
// initableProperty.TrySetValue(value);
//}
pickDistance = ConvertUnits.ToSimUnits(ToolBox.GetAttributeFloat(element, "pickdistance", 0.0f));
isLinkable = ToolBox.GetAttributeBool(element, "linkable", false);
resizeHorizontal = ToolBox.GetAttributeBool(element, "resizehorizontal", false);
resizeVertical = ToolBox.GetAttributeBool(element, "resizevertical", false);
focusOnSelected = ToolBox.GetAttributeBool(element, "focusonselected", false);
offsetOnSelected = ToolBox.GetAttributeFloat(element, "offsetonselected", 0.0f);
triggers = new List<Rectangle>();
foreach (XElement subElement in element.Elements())
{
switch (subElement.Name.ToString().ToLower())
{
case "sprite":
sprite = new Sprite(subElement, Path.GetDirectoryName(filePath) + "/");
size = sprite.size;
break;
case "trigger":
Rectangle trigger = new Rectangle(0, 0, 10,10);
trigger.X = ToolBox.GetAttributeInt(subElement, "x", 0);
trigger.Y = ToolBox.GetAttributeInt(subElement, "y", 0);
trigger.Width = ToolBox.GetAttributeInt(subElement, "width", 0);
trigger.Height = ToolBox.GetAttributeInt(subElement, "height", 0);
triggers.Add(trigger);
break;
}
}
sounds = new List<Sound>();
var soundElements = element.Descendants("Sound");
foreach (XElement soundElement in soundElements)
{
string soundPath = ToolBox.GetAttributeString(soundElement, "path", "");
if (soundPath == "") continue;
Sound sound = Sound.Load(soundPath);
if (sound != null) sounds.Add(sound);
}
list.Add(this);
}
}
}
using System;
using System.Collections.Generic;
using System.IO;
using System.Xml.Linq;
using FarseerPhysics;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
namespace Subsurface
{
class ItemPrefab : MapEntityPrefab
{
static string contentFolder = "Content/Items/";
string configFile;
//should the camera focus on the construction when selected
protected bool focusOnSelected;
//the amount of "camera offset" when selecting the construction
protected float offsetOnSelected;
//default size
protected Vector2 size;
//how close the character has to be to the item to pick it up
float pickDistance;
public List<Sound> sounds;
//an area next to the construction
//the construction can be Activated() by a character inside the area
public List<Rectangle> triggers;
public string ConfigFile
{
get { return configFile; }
}
public float PickDistance
{
get { return pickDistance; }
}
public override bool IsLinkable
{
get { return isLinkable; }
}
public bool FocusOnSelected
{
get { return focusOnSelected; }
}
public float OffsetOnSelected
{
get { return offsetOnSelected; }
}
public override void UpdatePlacing(SpriteBatch spriteBatch, Camera cam)
{
Vector2 position = Map.MouseToWorldGrid(cam);
if (!resizeHorizontal && !resizeVertical)
{
if (PlayerInput.LeftButtonClicked())
{
new Item(new Rectangle((int)position.X, (int)position.Y, (int)sprite.size.X, (int)sprite.size.Y), this);
//constructor.Invoke(lobject);
placePosition = Vector2.Zero;
selected = null;
return;
}
sprite.Draw(spriteBatch, new Vector2(position.X + sprite.size.X / 2.0f, -position.Y + sprite.size.Y / 2.0f));
}
else
{
Vector2 placeSize = size;
if (placePosition == Vector2.Zero)
{
if (PlayerInput.GetMouseState.LeftButton == ButtonState.Pressed)
placePosition = position;
}
else
{
if (resizeHorizontal)
placeSize.X = Math.Max(position.X - placePosition.X, size.X);
if (resizeVertical)
placeSize.Y = Math.Max(placePosition.Y - position.Y, size.Y);
if (PlayerInput.GetMouseState.LeftButton == ButtonState.Released)
{
new Item(new Rectangle((int)placePosition.X, (int)placePosition.Y, (int)placeSize.X, (int)placeSize.Y), this);
selected = null;
return;
}
position = placePosition;
}
sprite.DrawTiled(spriteBatch, new Vector2(position.X, -position.Y), placeSize, Color.White);
}
if (PlayerInput.GetMouseState.RightButton == ButtonState.Pressed) selected = null;
}
public static void LoadAll()
{
string[] files = Directory.GetFiles(contentFolder, "*.xml", SearchOption.AllDirectories);
foreach (string filePath in files)
{
XDocument doc = ToolBox.TryLoadXml(filePath);
if (doc == null) return;
if (doc.Root.Name.ToString().ToLower() == "item")
{
new ItemPrefab(doc.Root, filePath);
}
else
{
foreach (XElement element in doc.Root.Elements())
{
if (element.Name.ToString().ToLower() != "item") continue;
new ItemPrefab(element, filePath);
}
}
}
}
public ItemPrefab (XElement element, string filePath)
{
configFile = filePath;
name = ToolBox.GetAttributeString(element, "name", "");
if (name == "") DebugConsole.ThrowError("Unnamed item in "+filePath+"!");
//if (element.Attribute("sprite") != null)
//{
// sprite = new Sprite(Path.GetDirectoryName(filePath) + "/" + element.Attribute("sprite").Value, new Vector2(0.5f, 0.5f));
// sprite.Depth = 0.5f;
//}
//var initableProperties = GetProperties<Initable>();
//foreach (ObjectProperty initableProperty in initableProperties)
//{
// object value = ToolBox.GetAttributeObject(element, initableProperty.Name.ToLower());
// if (value == null)
// {
// foreach (var ini in initableProperty.Attributes.OfType<Initable>())
// {
// value = ini.defaultValue;
// break;
// }
// }
// initableProperty.TrySetValue(value);
//}
pickDistance = ConvertUnits.ToSimUnits(ToolBox.GetAttributeFloat(element, "pickdistance", 0.0f));
isLinkable = ToolBox.GetAttributeBool(element, "linkable", false);
resizeHorizontal = ToolBox.GetAttributeBool(element, "resizehorizontal", false);
resizeVertical = ToolBox.GetAttributeBool(element, "resizevertical", false);
focusOnSelected = ToolBox.GetAttributeBool(element, "focusonselected", false);
offsetOnSelected = ToolBox.GetAttributeFloat(element, "offsetonselected", 0.0f);
triggers = new List<Rectangle>();
foreach (XElement subElement in element.Elements())
{
switch (subElement.Name.ToString().ToLower())
{
case "sprite":
sprite = new Sprite(subElement, Path.GetDirectoryName(filePath) + "/");
size = sprite.size;
break;
case "trigger":
Rectangle trigger = new Rectangle(0, 0, 10,10);
trigger.X = ToolBox.GetAttributeInt(subElement, "x", 0);
trigger.Y = ToolBox.GetAttributeInt(subElement, "y", 0);
trigger.Width = ToolBox.GetAttributeInt(subElement, "width", 0);
trigger.Height = ToolBox.GetAttributeInt(subElement, "height", 0);
triggers.Add(trigger);
break;
}
}
sounds = new List<Sound>();
var soundElements = element.Descendants("Sound");
foreach (XElement soundElement in soundElements)
{
string soundPath = ToolBox.GetAttributeString(soundElement, "path", "");
if (soundPath == "") continue;
Sound sound = Sound.Load(soundPath);
if (sound != null) sounds.Add(sound);
}
list.Add(this);
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,436 +1,436 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Xml.Linq;
using FarseerPhysics;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
namespace Subsurface
{
class Hull : MapEntity
{
public static List<Hull> hullList = new List<Hull>();
public static bool EditWater;
public static WaterRenderer renderer;
public static bool DebugDraw;
public const float OxygenDistributionSpeed = 500.0f;
public const float OxygenDetoriationSpeed = 0.3f;
public const float OxygenConsumptionSpeed = 1000.0f;
public const int WaveWidth = 16;
const float WaveStiffness = 0.003f;
const float WaveSpread = 0.05f;
const float WaveDampening = 0.01f;
//how much excess water the room can contain (= more than the volume of the room)
public const float MaxCompress = 10000f;
public readonly Dictionary<string, PropertyDescriptor> properties;
float lethalPressure;
float surface;
float volume;
float pressure;
float oxygen;
bool update;
float[] waveY; //displacement from the surface of the water
float[] waveVel; //velocity of the point
float[] leftDelta;
float[] rightDelta;
public override bool IsLinkable
{
get { return true; }
}
public float LethalPressure
{
get { return lethalPressure; }
set { lethalPressure = MathHelper.Clamp(value, 0.0f, 100.0f); }
}
public Vector2 Size
{
get { return new Vector2(rect.Width, rect.Height); }
}
public float Surface
{
get { return surface; }
}
public float Volume
{
get { return volume; }
set
{
volume = MathHelper.Clamp(value, 0.0f, FullVolume + MaxCompress);
if (volume < FullVolume) Pressure = rect.Y - rect.Height + volume / rect.Width;
if (volume > 0.0f) update = true;
}
}
public float Oxygen
{
get { return oxygen; }
set { oxygen = MathHelper.Clamp(value, 0.0f, FullVolume); }
}
public float OxygenPercentage
{
get { return oxygen / FullVolume * 100.0f; }
set { Oxygen = (value / 100.0f) * FullVolume; }
}
public float FullVolume
{
get { return (rect.Width * rect.Height); }
}
public float Pressure
{
get { return pressure; }
set { pressure = value; }
}
public float[] WaveY
{
get { return waveY; }
}
public float[] WaveVel
{
get { return waveVel; }
}
public Hull(Rectangle rectangle)
{
rect = rectangle;
OxygenPercentage = (float)(Game1.random.NextDouble() * 100.0);
properties = TypeDescriptor.GetProperties(this.GetType())
.Cast<PropertyDescriptor>()
.ToDictionary(pr => pr.Name);
int arraySize = (rectangle.Width / WaveWidth + 1);
waveY = new float[arraySize];
waveVel = new float[arraySize];
leftDelta = new float[arraySize];
rightDelta = new float[arraySize];
surface = rect.Y - rect.Height;
aiTarget = new AITarget(this);
aiTarget.SightRange = (rect.Width + rect.Height)*10.0f;
hullList.Add(this);
Item.UpdateHulls();
Gap.UpdateHulls();
Volume = 0.0f;
//add to list of entities as well
mapEntityList.Add(this);
}
public override bool Contains(Vector2 position)
{
return (Map.RectContains(rect, position) &&
!Map.RectContains(new Rectangle(rect.X + 8, rect.Y - 8, rect.Width -16, rect.Height -16), position));
}
public int GetWaveIndex(Vector2 position)
{
int index = (int)(position.X - rect.X) / WaveWidth;
index = MathHelper.Clamp(index, 0, waveY.Length-1);
return index;
}
public override void Move(Vector2 amount)
{
rect.X += (int)amount.X;
rect.Y += (int)amount.Y;
Item.UpdateHulls();
Gap.UpdateHulls();
}
public override void Remove()
{
base.Remove();
Item.UpdateHulls();
Gap.UpdateHulls();
//renderer.Dispose();
hullList.Remove(this);
}
public override void Update(Camera cam, float deltaTime)
{
Oxygen -= OxygenDetoriationSpeed * deltaTime;
if (EditWater)
{
Vector2 position = cam.ScreenToWorld(PlayerInput.MousePosition);
if (Map.RectContains(rect, position))
{
if (PlayerInput.LeftButtonDown())
{
waveY[(int)(position.X - rect.X) / Hull.WaveWidth] = 100.0f;
Volume = Volume + 1500.0f;
}
else if (PlayerInput.GetMouseState.RightButton == Microsoft.Xna.Framework.Input.ButtonState.Pressed)
{
Volume = Volume - 1500.0f;
}
}
}
if (!update) return;
float surfaceY = rect.Y - rect.Height + Volume / rect.Width;
for (int i = 0; i < waveY.Length; i++)
{
float maxDelta = Math.Max(Math.Abs(rightDelta[i]), Math.Abs(leftDelta[i]));
if (maxDelta > ToolBox.RandomFloat(0.2f,10.0f))
{
Game1.particleManager.CreateParticle(ConvertUnits.ToSimUnits(new Vector2(rect.X + WaveWidth * i,surface + waveY[i])),
0.0f, new Vector2(0.0f, waveVel[i]/10.0f-1.0f), "mist");
}
waveY[i] = waveY[i] + waveVel[i];
if (surfaceY + waveY[i] > rect.Y)
{
waveY[i] -= (surfaceY + waveY[i]) - rect.Y;
waveVel[i] = waveVel[i] * -0.5f;
}
else if (surfaceY + waveY[i] < rect.Y - rect.Height)
{
waveY[i] -= (surfaceY + waveY[i]) - (rect.Y - rect.Height);
waveVel[i] = waveVel[i] * -0.5f;
}
//acceleration
float a = -WaveStiffness * waveY[i] - waveVel[i] * WaveDampening;
waveVel[i] = waveVel[i] + a;
}
for (int j = 0; j < 2; j++)
{
for (int i = 1; i < waveY.Length - 1; i++)
{
leftDelta[i] = WaveSpread * (waveY[i] - waveY[i - 1]);
waveVel[i - 1] = waveVel[i - 1] + leftDelta[i];
rightDelta[i] = WaveSpread * (waveY[i] - waveY[i + 1]);
waveVel[i + 1] = waveVel[i + 1] + rightDelta[i];
}
for (int i = 1; i < waveY.Length - 1; i++)
{
waveY[i - 1] = waveY[i - 1] + leftDelta[i];
waveY[i + 1] = waveY[i + 1] + rightDelta[i];
}
}
if (volume<FullVolume)
{
LethalPressure -= 0.5f;
if (Volume == 0.0f)
{
for (int i = 1; i < waveY.Length - 1; i++)
{
if (waveY[i] > 0.1f) return;
}
update = false;
}
}
else
{
LethalPressure += 1.0f;
}
}
public override void Draw(SpriteBatch spriteBatch, bool editing)
{
if (!editing && !DebugDraw) return;
GUI.DrawRectangle(spriteBatch,
new Vector2(rect.X, -rect.Y),
new Vector2(rect.Width, rect.Height),
isHighlighted ? Color.Green : Color.Blue);
GUI.DrawRectangle(spriteBatch,
new Rectangle(rect.X, -rect.Y, rect.Width, rect.Height),
Color.Red*((100.0f-OxygenPercentage)/400.0f), true);
spriteBatch.DrawString(GUI.font, "Pressure: " + ((int)pressure - rect.Y).ToString() +
" - Lethality: " + lethalPressure +
" - Oxygen: "+((int)OxygenPercentage).ToString(), new Vector2(rect.X+10, -rect.Y+10), Color.Black);
spriteBatch.DrawString(GUI.font, volume.ToString() +" / "+ FullVolume.ToString(), new Vector2(rect.X+10, -rect.Y+30), Color.Black);
if (isSelected && editing)
{
GUI.DrawRectangle(spriteBatch,
new Vector2(rect.X - 5, -rect.Y - 5),
new Vector2(rect.Width + 10, rect.Height + 10),
Color.Red);
}
}
public void Render(GraphicsDevice graphicsDevice, Camera cam)
{
if (renderer.positionInBuffer > renderer.vertices.Length - 6) return;
//calculate where the surface should be based on the water volume
float top = rect.Y;
float bottom = rect.Y - rect.Height;
float surfaceY = bottom + Volume / rect.Width;
//interpolate the position of the rendered surface towards the "target surface"
surface = surface + (surfaceY - surface) / 10.0f;
Matrix transform =
cam.Transform
* Matrix.CreateOrthographic(Game1.GraphicsWidth, Game1.GraphicsHeight, -1, 1) * 0.5f;
if (bottom > cam.WorldView.Y || top < cam.WorldView.Y - cam.WorldView.Height) return;
if (!update)
{
// create the four corners of our triangle.
Vector3 p1 = new Vector3(rect.X, top, 0.0f);
Vector3 p2 = new Vector3(rect.X + rect.Width, top, 0.0f);
Vector3 p3 = new Vector3(p2.X, bottom, 0.0f);
Vector3 p4 = new Vector3(p1.X, bottom, 0.0f);
renderer.vertices[renderer.positionInBuffer] = new WaterVertex(p1, new Vector2(p1.X, -p1.Y), transform);
renderer.vertices[renderer.positionInBuffer + 1] = new WaterVertex(p2, new Vector2(p2.X, -p2.Y), transform);
renderer.vertices[renderer.positionInBuffer + 2] = new WaterVertex(p3, new Vector2(p3.X, -p3.Y), transform);
renderer.vertices[renderer.positionInBuffer + 3] = new WaterVertex(p1, new Vector2(p1.X, -p1.Y), transform);
renderer.vertices[renderer.positionInBuffer + 4] = new WaterVertex(p3, new Vector2(p3.X, -p3.Y), transform);
renderer.vertices[renderer.positionInBuffer + 5] = new WaterVertex(p4, new Vector2(p4.X, -p4.Y), transform);
renderer.positionInBuffer += 6;
return;
}
int x = rect.X;
int start = (int)Math.Floor((float)(cam.WorldView.X - x) / WaveWidth);
start = Math.Max(start, 0);
int end = (waveY.Length - 1)
- (int)Math.Floor((float)((x + rect.Width) - (cam.WorldView.X + cam.WorldView.Width)) / WaveWidth);
end = Math.Min(end, waveY.Length - 1);
x += start * WaveWidth;
for (int i = start; i < end; i++)
{
if (renderer.positionInBuffer > renderer.vertices.Length - 6) return;
Vector3 p1 = new Vector3(x, top, 0.0f);
Vector3 p4 = new Vector3(p1.X, surface + waveY[i], 0.0f);
//skip adjacent "water rects" if the surface of the water is roughly at the same position
int width = WaveWidth;
while (i<end-1 && Math.Abs(waveY[i + 1] - waveY[i]) < 1.0f)
{
width += WaveWidth;
i++;
}
Vector3 p2 = new Vector3(x + width, top, 0.0f);
Vector3 p3 = new Vector3(p2.X, surface + waveY[i+1], 0.0f);
renderer.vertices[renderer.positionInBuffer] = new WaterVertex(p1, new Vector2(p1.X, -p1.Y), transform);
renderer.vertices[renderer.positionInBuffer + 1] = new WaterVertex(p2, new Vector2(p2.X, -p2.Y), transform);
renderer.vertices[renderer.positionInBuffer + 2] = new WaterVertex(p3, new Vector2(p3.X, -p3.Y), transform);
renderer.vertices[renderer.positionInBuffer + 3] = new WaterVertex(p1, new Vector2(p1.X, -p1.Y), transform);
renderer.vertices[renderer.positionInBuffer + 4] = new WaterVertex(p3, new Vector2(p3.X, -p3.Y), transform);
renderer.vertices[renderer.positionInBuffer + 5] = new WaterVertex(p4, new Vector2(p4.X, -p4.Y), transform);
renderer.positionInBuffer += 6;
x += width;
}
}
//returns the water block which contains the point (or null if it isn't inside any)
public static Hull FindHull(Vector2 position, Hull guess = null)
{
if (guess != null && hullList.Contains(guess))
{
if (Map.RectContains(guess.rect, position)) return guess;
}
foreach (Hull w in hullList)
{
if (Map.RectContains(w.rect, position)) return w;
}
return null;
}
public override XElement Save(XDocument doc)
{
XElement element = new XElement("Hull");
element.Add(new XAttribute("ID", ID),
new XAttribute("x", rect.X),
new XAttribute("y", rect.Y),
new XAttribute("width", rect.Width),
new XAttribute("height", rect.Height),
new XAttribute("water", volume));
doc.Root.Add(element);
return element;
}
public static void Load(XElement element)
{
Rectangle rect = new Rectangle(
int.Parse(element.Attribute("x").Value),
int.Parse(element.Attribute("y").Value),
int.Parse(element.Attribute("width").Value),
int.Parse(element.Attribute("height").Value));
Hull h = new Hull(rect);
h.volume = ToolBox.GetAttributeFloat(element, "pressure", 0.0f);
h.ID = int.Parse(element.Attribute("ID").Value);
}
}
}
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Xml.Linq;
using FarseerPhysics;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
namespace Subsurface
{
class Hull : MapEntity
{
public static List<Hull> hullList = new List<Hull>();
public static bool EditWater;
public static WaterRenderer renderer;
public static bool DebugDraw;
public const float OxygenDistributionSpeed = 500.0f;
public const float OxygenDetoriationSpeed = 0.3f;
public const float OxygenConsumptionSpeed = 1000.0f;
public const int WaveWidth = 16;
const float WaveStiffness = 0.003f;
const float WaveSpread = 0.05f;
const float WaveDampening = 0.01f;
//how much excess water the room can contain (= more than the volume of the room)
public const float MaxCompress = 10000f;
public readonly Dictionary<string, PropertyDescriptor> properties;
float lethalPressure;
float surface;
float volume;
float pressure;
float oxygen;
bool update;
float[] waveY; //displacement from the surface of the water
float[] waveVel; //velocity of the point
float[] leftDelta;
float[] rightDelta;
public override bool IsLinkable
{
get { return true; }
}
public float LethalPressure
{
get { return lethalPressure; }
set { lethalPressure = MathHelper.Clamp(value, 0.0f, 100.0f); }
}
public Vector2 Size
{
get { return new Vector2(rect.Width, rect.Height); }
}
public float Surface
{
get { return surface; }
}
public float Volume
{
get { return volume; }
set
{
volume = MathHelper.Clamp(value, 0.0f, FullVolume + MaxCompress);
if (volume < FullVolume) Pressure = rect.Y - rect.Height + volume / rect.Width;
if (volume > 0.0f) update = true;
}
}
public float Oxygen
{
get { return oxygen; }
set { oxygen = MathHelper.Clamp(value, 0.0f, FullVolume); }
}
public float OxygenPercentage
{
get { return oxygen / FullVolume * 100.0f; }
set { Oxygen = (value / 100.0f) * FullVolume; }
}
public float FullVolume
{
get { return (rect.Width * rect.Height); }
}
public float Pressure
{
get { return pressure; }
set { pressure = value; }
}
public float[] WaveY
{
get { return waveY; }
}
public float[] WaveVel
{
get { return waveVel; }
}
public Hull(Rectangle rectangle)
{
rect = rectangle;
OxygenPercentage = (float)(Game1.random.NextDouble() * 100.0);
properties = TypeDescriptor.GetProperties(this.GetType())
.Cast<PropertyDescriptor>()
.ToDictionary(pr => pr.Name);
int arraySize = (rectangle.Width / WaveWidth + 1);
waveY = new float[arraySize];
waveVel = new float[arraySize];
leftDelta = new float[arraySize];
rightDelta = new float[arraySize];
surface = rect.Y - rect.Height;
aiTarget = new AITarget(this);
aiTarget.SightRange = (rect.Width + rect.Height)*10.0f;
hullList.Add(this);
Item.UpdateHulls();
Gap.UpdateHulls();
Volume = 0.0f;
//add to list of entities as well
mapEntityList.Add(this);
}
public override bool Contains(Vector2 position)
{
return (Map.RectContains(rect, position) &&
!Map.RectContains(new Rectangle(rect.X + 8, rect.Y - 8, rect.Width - 16, rect.Height - 16), position));
}
public int GetWaveIndex(Vector2 position)
{
int index = (int)(position.X - rect.X) / WaveWidth;
index = MathHelper.Clamp(index, 0, waveY.Length-1);
return index;
}
public override void Move(Vector2 amount)
{
rect.X += (int)amount.X;
rect.Y += (int)amount.Y;
Item.UpdateHulls();
Gap.UpdateHulls();
}
public override void Remove()
{
base.Remove();
Item.UpdateHulls();
Gap.UpdateHulls();
//renderer.Dispose();
hullList.Remove(this);
}
public override void Update(Camera cam, float deltaTime)
{
Oxygen -= OxygenDetoriationSpeed * deltaTime;
if (EditWater)
{
Vector2 position = cam.ScreenToWorld(PlayerInput.MousePosition);
if (Map.RectContains(rect, position))
{
if (PlayerInput.LeftButtonDown())
{
waveY[(int)(position.X - rect.X) / Hull.WaveWidth] = 100.0f;
Volume = Volume + 1500.0f;
}
else if (PlayerInput.GetMouseState.RightButton == Microsoft.Xna.Framework.Input.ButtonState.Pressed)
{
Volume = Volume - 1500.0f;
}
}
}
if (!update) return;
float surfaceY = rect.Y - rect.Height + Volume / rect.Width;
for (int i = 0; i < waveY.Length; i++)
{
float maxDelta = Math.Max(Math.Abs(rightDelta[i]), Math.Abs(leftDelta[i]));
if (maxDelta > ToolBox.RandomFloat(0.2f,10.0f))
{
Game1.particleManager.CreateParticle(ConvertUnits.ToSimUnits(new Vector2(rect.X + WaveWidth * i,surface + waveY[i])),
ToolBox.RandomFloat(0.0f,6.2f), new Vector2(0.0f, -0.5f), "mist");
}
waveY[i] = waveY[i] + waveVel[i];
if (surfaceY + waveY[i] > rect.Y)
{
waveY[i] -= (surfaceY + waveY[i]) - rect.Y;
waveVel[i] = waveVel[i] * -0.5f;
}
else if (surfaceY + waveY[i] < rect.Y - rect.Height)
{
waveY[i] -= (surfaceY + waveY[i]) - (rect.Y - rect.Height);
waveVel[i] = waveVel[i] * -0.5f;
}
//acceleration
float a = -WaveStiffness * waveY[i] - waveVel[i] * WaveDampening;
waveVel[i] = waveVel[i] + a;
}
for (int j = 0; j < 2; j++)
{
for (int i = 1; i < waveY.Length - 1; i++)
{
leftDelta[i] = WaveSpread * (waveY[i] - waveY[i - 1]);
waveVel[i - 1] = waveVel[i - 1] + leftDelta[i];
rightDelta[i] = WaveSpread * (waveY[i] - waveY[i + 1]);
waveVel[i + 1] = waveVel[i + 1] + rightDelta[i];
}
for (int i = 1; i < waveY.Length - 1; i++)
{
waveY[i - 1] = waveY[i - 1] + leftDelta[i];
waveY[i + 1] = waveY[i + 1] + rightDelta[i];
}
}
if (volume<FullVolume)
{
LethalPressure -= 0.5f;
if (Volume == 0.0f)
{
for (int i = 1; i < waveY.Length - 1; i++)
{
if (waveY[i] > 0.1f) return;
}
update = false;
}
}
else
{
LethalPressure += 1.0f;
}
}
public override void Draw(SpriteBatch spriteBatch, bool editing)
{
if (!editing && !DebugDraw) return;
GUI.DrawRectangle(spriteBatch,
new Vector2(rect.X, -rect.Y),
new Vector2(rect.Width, rect.Height),
isHighlighted ? Color.Green : Color.Blue);
GUI.DrawRectangle(spriteBatch,
new Rectangle(rect.X, -rect.Y, rect.Width, rect.Height),
Color.Red*((100.0f-OxygenPercentage)/400.0f), true);
spriteBatch.DrawString(GUI.font, "Pressure: " + ((int)pressure - rect.Y).ToString() +
" - Lethality: " + lethalPressure +
" - Oxygen: "+((int)OxygenPercentage).ToString(), new Vector2(rect.X+10, -rect.Y+10), Color.Black);
spriteBatch.DrawString(GUI.font, volume.ToString() +" / "+ FullVolume.ToString(), new Vector2(rect.X+10, -rect.Y+30), Color.Black);
if (isSelected && editing)
{
GUI.DrawRectangle(spriteBatch,
new Vector2(rect.X - 5, -rect.Y - 5),
new Vector2(rect.Width + 10, rect.Height + 10),
Color.Red);
}
}
public void Render(GraphicsDevice graphicsDevice, Camera cam)
{
if (renderer.positionInBuffer > renderer.vertices.Length - 6) return;
//calculate where the surface should be based on the water volume
float top = rect.Y;
float bottom = rect.Y - rect.Height;
float surfaceY = bottom + Volume / rect.Width;
//interpolate the position of the rendered surface towards the "target surface"
surface = surface + (surfaceY - surface) / 10.0f;
Matrix transform =
cam.Transform
* Matrix.CreateOrthographic(Game1.GraphicsWidth, Game1.GraphicsHeight, -1, 1) * 0.5f;
if (bottom > cam.WorldView.Y || top < cam.WorldView.Y - cam.WorldView.Height) return;
if (!update)
{
// create the four corners of our triangle.
Vector3 p1 = new Vector3(rect.X, top, 0.0f);
Vector3 p2 = new Vector3(rect.X + rect.Width, top, 0.0f);
Vector3 p3 = new Vector3(p2.X, bottom, 0.0f);
Vector3 p4 = new Vector3(p1.X, bottom, 0.0f);
renderer.vertices[renderer.positionInBuffer] = new WaterVertex(p1, new Vector2(p1.X, -p1.Y), transform);
renderer.vertices[renderer.positionInBuffer + 1] = new WaterVertex(p2, new Vector2(p2.X, -p2.Y), transform);
renderer.vertices[renderer.positionInBuffer + 2] = new WaterVertex(p3, new Vector2(p3.X, -p3.Y), transform);
renderer.vertices[renderer.positionInBuffer + 3] = new WaterVertex(p1, new Vector2(p1.X, -p1.Y), transform);
renderer.vertices[renderer.positionInBuffer + 4] = new WaterVertex(p3, new Vector2(p3.X, -p3.Y), transform);
renderer.vertices[renderer.positionInBuffer + 5] = new WaterVertex(p4, new Vector2(p4.X, -p4.Y), transform);
renderer.positionInBuffer += 6;
return;
}
int x = rect.X;
int start = (int)Math.Floor((float)(cam.WorldView.X - x) / WaveWidth);
start = Math.Max(start, 0);
int end = (waveY.Length - 1)
- (int)Math.Floor((float)((x + rect.Width) - (cam.WorldView.X + cam.WorldView.Width)) / WaveWidth);
end = Math.Min(end, waveY.Length - 1);
x += start * WaveWidth;
for (int i = start; i < end; i++)
{
if (renderer.positionInBuffer > renderer.vertices.Length - 6) return;
Vector3 p1 = new Vector3(x, top, 0.0f);
Vector3 p4 = new Vector3(p1.X, surface + waveY[i], 0.0f);
//skip adjacent "water rects" if the surface of the water is roughly at the same position
int width = WaveWidth;
while (i<end-1 && Math.Abs(waveY[i + 1] - waveY[i]) < 1.0f)
{
width += WaveWidth;
i++;
}
Vector3 p2 = new Vector3(x + width, top, 0.0f);
Vector3 p3 = new Vector3(p2.X, surface + waveY[i+1], 0.0f);
renderer.vertices[renderer.positionInBuffer] = new WaterVertex(p1, new Vector2(p1.X, -p1.Y), transform);
renderer.vertices[renderer.positionInBuffer + 1] = new WaterVertex(p2, new Vector2(p2.X, -p2.Y), transform);
renderer.vertices[renderer.positionInBuffer + 2] = new WaterVertex(p3, new Vector2(p3.X, -p3.Y), transform);
renderer.vertices[renderer.positionInBuffer + 3] = new WaterVertex(p1, new Vector2(p1.X, -p1.Y), transform);
renderer.vertices[renderer.positionInBuffer + 4] = new WaterVertex(p3, new Vector2(p3.X, -p3.Y), transform);
renderer.vertices[renderer.positionInBuffer + 5] = new WaterVertex(p4, new Vector2(p4.X, -p4.Y), transform);
renderer.positionInBuffer += 6;
x += width;
}
}
//returns the water block which contains the point (or null if it isn't inside any)
public static Hull FindHull(Vector2 position, Hull guess = null)
{
if (guess != null && hullList.Contains(guess))
{
if (Map.RectContains(guess.rect, position)) return guess;
}
foreach (Hull w in hullList)
{
if (Map.RectContains(w.rect, position)) return w;
}
return null;
}
public override XElement Save(XDocument doc)
{
XElement element = new XElement("Hull");
element.Add(new XAttribute("ID", ID),
new XAttribute("x", rect.X),
new XAttribute("y", rect.Y),
new XAttribute("width", rect.Width),
new XAttribute("height", rect.Height),
new XAttribute("water", volume));
doc.Root.Add(element);
return element;
}
public static void Load(XElement element)
{
Rectangle rect = new Rectangle(
int.Parse(element.Attribute("x").Value),
int.Parse(element.Attribute("y").Value),
int.Parse(element.Attribute("width").Value),
int.Parse(element.Attribute("height").Value));
Hull h = new Hull(rect);
h.volume = ToolBox.GetAttributeFloat(element, "pressure", 0.0f);
h.ID = int.Parse(element.Attribute("ID").Value);
}
}
}

View File

@@ -1,191 +1,183 @@
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Subsurface.Lights
{
class ConvexHull
{
public static List<ConvexHull> list = new List<ConvexHull>();
static BasicEffect drawingEffect;
private VertexPositionColor[] vertices;
private short[] indices;
int primitiveCount;
bool[] backFacing;
VertexPositionColor[] shadowVertices;
public bool Enabled
{
get;
set;
}
//private Vector2 position = Vector2.Zero;
//public Vector2 Position
//{
// get { return position; }
// set { position = value; }
//}
public ConvexHull(Vector2[] points, Color color)
{
int vertexCount = points.Length;
vertices = new VertexPositionColor[vertexCount + 1];
Vector2 center = Vector2.Zero;
for (int i = 0; i < vertexCount; i++)
{
vertices[i] = new VertexPositionColor(new Vector3(points[i], 0), color);
center += points[i];
}
center /= points.Length;
vertices[vertexCount] = new VertexPositionColor(new Vector3(center, 0), color);
primitiveCount = points.Length;
indices = new short[primitiveCount * 3];
for (int i = 0; i < primitiveCount; i++)
{
indices[3 * i] = (short)i;
indices[3 * i + 1] = (short)((i + 1) % vertexCount);
indices[3 * i + 2] = (short)vertexCount;
}
backFacing = new bool[vertexCount];
Enabled = true;
list.Add(this);
}
public void Move(Vector2 amount)
{
for (int i = 0; i < vertices.Count(); i++)
{
vertices[i].Position = new Vector3(vertices[i].Position.X + amount.X, vertices[i].Position.Y + amount.Y, vertices[i].Position.Z);
}
}
public void SetVertices(Vector2[] points)
{
int vertexCount = points.Length;
vertices = new VertexPositionColor[vertexCount + 1];
for (int i = 0; i < vertexCount; i++)
{
vertices[i] = new VertexPositionColor(new Vector3(points[i], 0), Color.Black);
}
}
//public void Draw(GameTime gameTime)
//{
// device.RasterizerState = RasterizerState.CullNone;
// device.BlendState = BlendState.Opaque;
// drawingEffect.World = Matrix.CreateTranslation(position.X, position.Y, 0);
// foreach (EffectPass pass in drawingEffect.CurrentTechnique.Passes)
// {
// pass.Apply();
// device.DrawUserIndexedPrimitives<VertexPositionColor>(PrimitiveType.TriangleList, vertices, 0, vertices.Length, indices, 0, primitiveCount);
// }
//}
public void DrawShadows(GraphicsDevice graphicsDevice, Camera cam, Vector2 lightSourcePos)
{
if (!Enabled) return;
if (drawingEffect == null)
{
drawingEffect = new BasicEffect(graphicsDevice);
drawingEffect.VertexColorEnabled = true;
}
//compute facing of each edge, using N*L
for (int i = 0; i < primitiveCount; i++)
{
Vector2 firstVertex = new Vector2(vertices[i].Position.X, vertices[i].Position.Y);
int secondIndex = (i + 1) % primitiveCount;
Vector2 secondVertex = new Vector2(vertices[secondIndex].Position.X, vertices[secondIndex].Position.Y);
Vector2 middle = (firstVertex + secondVertex) / 2;
Vector2 L = lightSourcePos - middle;
Vector2 N = new Vector2();
N.X = -(secondVertex.Y - firstVertex.Y);
N.Y = secondVertex.X - firstVertex.X;
backFacing[i] = (Vector2.Dot(N, L) < 0);
}
//find beginning and ending vertices which
//belong to the shadow
int startingIndex = 0;
int endingIndex = 0;
for (int i = 0; i < primitiveCount; i++)
{
int currentEdge = i;
int nextEdge = (i + 1) % primitiveCount;
if (backFacing[currentEdge] && !backFacing[nextEdge])
endingIndex = nextEdge;
if (!backFacing[currentEdge] && backFacing[nextEdge])
startingIndex = nextEdge;
}
int shadowVertexCount;
//nr of vertices that are in the shadow
if (endingIndex > startingIndex)
shadowVertexCount = endingIndex - startingIndex + 1;
else
shadowVertexCount = primitiveCount + 1 - startingIndex + endingIndex;
shadowVertices = new VertexPositionColor[shadowVertexCount * 2];
//create a triangle strip that has the shape of the shadow
int currentIndex = startingIndex;
int svCount = 0;
while (svCount != shadowVertexCount * 2)
{
Vector3 vertexPos = vertices[currentIndex].Position;
//one vertex on the hull
shadowVertices[svCount] = new VertexPositionColor();
shadowVertices[svCount].Color = Color.Black;
shadowVertices[svCount].Position = vertexPos;
//one extruded by the light direction
shadowVertices[svCount + 1] = new VertexPositionColor();
shadowVertices[svCount + 1].Color = Color.Black;
Vector3 L2P = vertexPos - new Vector3(lightSourcePos, 0);
L2P.Normalize();
shadowVertices[svCount + 1].Position = new Vector3(lightSourcePos, 0) + L2P * 9000;
svCount += 2;
currentIndex = (currentIndex + 1) % primitiveCount;
}
drawingEffect.World = cam.ShaderTransform
* Matrix.CreateOrthographic(Game1.GraphicsWidth, Game1.GraphicsHeight, -1, 1) * 0.5f;
drawingEffect.CurrentTechnique.Passes[0].Apply();
graphicsDevice.DrawUserPrimitives<VertexPositionColor>(PrimitiveType.TriangleStrip, shadowVertices, 0, shadowVertexCount * 2 - 2);
}
public void Remove()
{
list.Remove(this);
}
}
}
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Subsurface.Lights
{
class ConvexHull
{
public static List<ConvexHull> list = new List<ConvexHull>();
static BasicEffect drawingEffect;
private VertexPositionColor[] vertices;
private short[] indices;
int primitiveCount;
bool[] backFacing;
VertexPositionColor[] shadowVertices;
public bool Enabled
{
get;
set;
}
public ConvexHull(Vector2[] points, Color color)
{
int vertexCount = points.Length;
vertices = new VertexPositionColor[vertexCount + 1];
Vector2 center = Vector2.Zero;
for (int i = 0; i < vertexCount; i++)
{
vertices[i] = new VertexPositionColor(new Vector3(points[i], 0), color);
center += points[i];
}
center /= points.Length;
vertices[vertexCount] = new VertexPositionColor(new Vector3(center, 0), color);
primitiveCount = points.Length;
indices = new short[primitiveCount * 3];
for (int i = 0; i < primitiveCount; i++)
{
indices[3 * i] = (short)i;
indices[3 * i + 1] = (short)((i + 1) % vertexCount);
indices[3 * i + 2] = (short)vertexCount;
}
backFacing = new bool[vertexCount];
Enabled = true;
list.Add(this);
}
public void Move(Vector2 amount)
{
for (int i = 0; i < vertices.Count(); i++)
{
vertices[i].Position = new Vector3(vertices[i].Position.X + amount.X, vertices[i].Position.Y + amount.Y, vertices[i].Position.Z);
}
}
public void SetVertices(Vector2[] points)
{
int vertexCount = points.Length;
vertices = new VertexPositionColor[vertexCount + 1];
for (int i = 0; i < vertexCount; i++)
{
vertices[i] = new VertexPositionColor(new Vector3(points[i], 0), Color.Black);
}
}
//public void Draw(GameTime gameTime)
//{
// device.RasterizerState = RasterizerState.CullNone;
// device.BlendState = BlendState.Opaque;
// drawingEffect.World = Matrix.CreateTranslation(position.X, position.Y, 0);
// foreach (EffectPass pass in drawingEffect.CurrentTechnique.Passes)
// {
// pass.Apply();
// device.DrawUserIndexedPrimitives<VertexPositionColor>(PrimitiveType.TriangleList, vertices, 0, vertices.Length, indices, 0, primitiveCount);
// }
//}
public void DrawShadows(GraphicsDevice graphicsDevice, Camera cam, Vector2 lightSourcePos)
{
if (!Enabled) return;
if (drawingEffect == null)
{
drawingEffect = new BasicEffect(graphicsDevice);
drawingEffect.VertexColorEnabled = true;
}
//compute facing of each edge, using N*L
for (int i = 0; i < primitiveCount; i++)
{
Vector2 firstVertex = new Vector2(vertices[i].Position.X, vertices[i].Position.Y);
int secondIndex = (i + 1) % primitiveCount;
Vector2 secondVertex = new Vector2(vertices[secondIndex].Position.X, vertices[secondIndex].Position.Y);
Vector2 middle = (firstVertex + secondVertex) / 2;
Vector2 L = lightSourcePos - middle;
Vector2 N = new Vector2();
N.X = -(secondVertex.Y - firstVertex.Y);
N.Y = secondVertex.X - firstVertex.X;
backFacing[i] = (Vector2.Dot(N, L) < 0);
}
//find beginning and ending vertices which
//belong to the shadow
int startingIndex = 0;
int endingIndex = 0;
for (int i = 0; i < primitiveCount; i++)
{
int currentEdge = i;
int nextEdge = (i + 1) % primitiveCount;
if (backFacing[currentEdge] && !backFacing[nextEdge])
endingIndex = nextEdge;
if (!backFacing[currentEdge] && backFacing[nextEdge])
startingIndex = nextEdge;
}
int shadowVertexCount;
//nr of vertices that are in the shadow
if (endingIndex > startingIndex)
shadowVertexCount = endingIndex - startingIndex + 1;
else
shadowVertexCount = primitiveCount + 1 - startingIndex + endingIndex;
shadowVertices = new VertexPositionColor[shadowVertexCount * 2];
//create a triangle strip that has the shape of the shadow
int currentIndex = startingIndex;
int svCount = 0;
while (svCount != shadowVertexCount * 2)
{
Vector3 vertexPos = vertices[currentIndex].Position;
//one vertex on the hull
shadowVertices[svCount] = new VertexPositionColor();
shadowVertices[svCount].Color = Color.Black;
shadowVertices[svCount].Position = vertexPos;
//one extruded by the light direction
shadowVertices[svCount + 1] = new VertexPositionColor();
shadowVertices[svCount + 1].Color = Color.Black;
Vector3 L2P = vertexPos - new Vector3(lightSourcePos, 0);
L2P.Normalize();
shadowVertices[svCount + 1].Position = new Vector3(lightSourcePos, 0) + L2P * 9000;
svCount += 2;
currentIndex = (currentIndex + 1) % primitiveCount;
}
drawingEffect.World = cam.ShaderTransform
* Matrix.CreateOrthographic(Game1.GraphicsWidth, Game1.GraphicsHeight, -1, 1) * 0.5f;
drawingEffect.CurrentTechnique.Passes[0].Apply();
graphicsDevice.DrawUserPrimitives<VertexPositionColor>(PrimitiveType.TriangleStrip, shadowVertices, 0, shadowVertexCount * 2 - 2);
}
public void Remove()
{
list.Remove(this);
}
}
}

View File

@@ -1,381 +1,398 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Xml.Linq;
using FarseerPhysics;
using FarseerPhysics.Dynamics;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using FarseerPhysics.Collision;
namespace Subsurface
{
public enum Direction : byte
{
None = 0, Left = 1, Right = 2
}
static class Map
{
public static Vector2 gridSize = new Vector2(16.0f, 16.0f);
private static Vector2 lastPickedPosition;
private static float lastPickedFraction;
private static Rectangle borders;
private static string filePath;
public static Vector2 LastPickedPosition
{
get { return lastPickedPosition; }
}
public static float LastPickedFraction
{
get { return lastPickedFraction; }
}
public static Rectangle Borders
{
get { return borders; }
}
public static string FilePath
{
get { return filePath; }
}
public static void Draw(SpriteBatch spriteBatch, bool editing = false)
{
for (int i = 0; i < MapEntity.mapEntityList.Count(); i++ )
{
MapEntity.mapEntityList[i].Draw(spriteBatch, editing);
}
}
public static void DrawFront(SpriteBatch spriteBatch, bool editing = false)
{
for (int i = 0; i < MapEntity.mapEntityList.Count(); i++)
{
if (MapEntity.mapEntityList[i].sprite == null || MapEntity.mapEntityList[i].sprite.Depth < 0.5f)
MapEntity.mapEntityList[i].Draw(spriteBatch, editing);
}
}
public static void DrawBack(SpriteBatch spriteBatch, bool editing = false)
{
for (int i = 0; i < MapEntity.mapEntityList.Count(); i++)
{
if (MapEntity.mapEntityList[i].sprite == null || MapEntity.mapEntityList[i].sprite.Depth >= 0.5f)
MapEntity.mapEntityList[i].Draw(spriteBatch, editing);
}
}
public static Vector2 MouseToWorldGrid(Camera cam)
{
Vector2 position = new Vector2(PlayerInput.GetMouseState.X, PlayerInput.GetMouseState.Y);
position = cam.ScreenToWorld(position);
return VectorToWorldGrid(position);
}
public static Vector2 VectorToWorldGrid(Vector2 position)
{
position.X = (float)Math.Floor(Convert.ToDouble(position.X / gridSize.X)) * gridSize.X;
position.Y = (float)Math.Ceiling(Convert.ToDouble(position.Y / gridSize.Y)) * gridSize.Y;
return position;
}
public static Rectangle AbsRect(Vector2 pos, Vector2 size)
{
if (size.X < 0.0f)
{
pos.X += size.X;
size.X = -size.X;
}
if (size.Y < 0.0f)
{
pos.Y -= size.Y;
size.Y = -size.Y;
}
return new Rectangle((int)pos.X, (int)pos.Y, (int)size.X, (int)size.Y);
}
public static bool RectContains(Rectangle rect, Vector2 pos)
{
return (pos.X > rect.X && pos.X < rect.X + rect.Width
&& pos.Y < rect.Y && pos.Y > rect.Y - rect.Height);
}
public static bool RectsOverlap(Rectangle rect1, Rectangle rect2)
{
return !(rect1.X > rect2.X + rect2.Width || rect1.X + rect1.Width < rect2.X ||
rect1.Y < rect2.Y - rect2.Height || rect1.Y - rect1.Height > rect2.Y);
}
public static Body PickBody(Vector2 rayStart, Vector2 rayEnd, List<Body> ignoredBodies = null)
{
float closestFraction = 1.0f;
Body closestBody = null;
Game1.world.RayCast((fixture, point, normal, fraction) =>
{
if (fixture == null || fixture.CollisionCategories == Category.None) return -1;
if (ignoredBodies != null && ignoredBodies.Contains(fixture.Body)) return -1;
Structure structure = fixture.Body.UserData as Structure;
if (structure != null && (structure.IsPlatform || !structure.HasBody)) return -1;
if (fraction < closestFraction)
{
closestFraction = fraction;
if (fixture.Body!=null) closestBody = fixture.Body;
}
return fraction;
}
, rayStart, rayEnd);
lastPickedPosition = rayStart + (rayEnd - rayStart) * closestFraction;
lastPickedFraction = closestFraction;
return closestBody;
}
public static Structure CheckVisibility(Vector2 rayStart, Vector2 rayEnd)
{
Structure closestStructure = null;
float closestFraction = 1.0f;
if (Vector2.Distance(rayStart,rayEnd)<0.01f)
{
closestFraction = 0.01f;
return null;
}
Game1.world.RayCast((fixture, point, normal, fraction) =>
{
if (fixture == null || fixture.CollisionCategories != Physics.CollisionWall) return -1;
Structure structure = fixture.Body.UserData as Structure;
if (structure != null)
{
if (structure.IsPlatform || structure.StairDirection != Direction.None) return -1;
int sectionIndex = structure.FindSectionIndex(ConvertUnits.ToDisplayUnits(point));
if (sectionIndex > -1 && structure.SectionHasHole(sectionIndex)) return -1;
}
if (fraction < closestFraction)
{
if (structure != null) closestStructure = structure;
closestFraction = fraction;
}
return closestFraction;
}
, rayStart, rayEnd);
lastPickedPosition = rayStart + (rayEnd - rayStart) * closestFraction;
lastPickedFraction = closestFraction;
return closestStructure;
}
public static Body PickBody(Vector2 point)
{
Body foundBody = null;
AABB aabb = new AABB(point, point);
Game1.world.QueryAABB(p =>
{
foundBody = p.Body;
return true;
}, ref aabb);
return foundBody;
}
public static bool InsideWall(Vector2 point)
{
Body foundBody = Map.PickBody(point);
if (foundBody==null) return false;
Structure wall = foundBody.UserData as Structure;
if (wall == null || wall.IsPlatform) return false;
return true;
}
public static void Save(string filePath, string fileName)
{
if (fileName==null)
{
DebugConsole.ThrowError("No save file selected");
return;
}
XDocument doc = new XDocument(
new XElement((XName)fileName));
foreach (MapEntity e in MapEntity.mapEntityList)
{
e.Save(doc);
}
try
{
string docString = doc.ToString();
ToolBox.CompressStringToFile(filePath+fileName+".gz", doc.ToString());
}
catch
{
DebugConsole.ThrowError("Saving map ''" + filePath + fileName + "'' failed!");
}
//doc.Save(filePath + fileName);
}
public static string[] GetMapFilePaths()
{
string[] mapFilePaths;
try
{
mapFilePaths = Directory.GetFiles("Content/SavedMaps");
}
catch (Exception e)
{
DebugConsole.ThrowError("Couldn't open directory ''Content/SavedMaps''!", e);
return null;
}
return mapFilePaths;
}
public static void Load(string filePath, string fileName)
{
Load(filePath + fileName);
}
public static void Load(string file)
{
Clear();
filePath = file;
XDocument doc = null;
string extension = Path.GetExtension(file);
if (extension==".gz")
{
Stream stream = ToolBox.DecompressFiletoStream(file);
if (stream == null)
{
DebugConsole.ThrowError("Loading map ''" + file + "'' failed!");
return;
}
try
{
stream.Position = 0;
doc = XDocument.Load(stream); //ToolBox.TryLoadXml(file);
stream.Close();
stream.Dispose();
}
catch
{
DebugConsole.ThrowError("Loading map ''" + file + "'' failed!");
return;
}
}
else if (extension ==".xml")
{
doc = XDocument.Load(file);
}
else
{
DebugConsole.ThrowError("Couldn't load map ''"+file+"! (Unrecognized file extension)");
return;
}
foreach (XElement element in doc.Root.Elements())
{
string typeName = element.Name.ToString();
Type t;
try
{
// Get the type of a specified class.
t = Type.GetType("Subsurface." + typeName + ", Subsurface", true, true);
if (t == null)
{
DebugConsole.ThrowError("Error in " + file + "! Could not find a entity of the type ''" + typeName + "''.");
continue;
}
}
catch (Exception e)
{
DebugConsole.ThrowError("Error in " + file + "! Could not find a entity of the type ''" + typeName + "''.", e);
continue;
}
try
{
MethodInfo loadMethod = t.GetMethod("Load");
loadMethod.Invoke(t, new object[] { element });
}
catch (Exception e)
{
DebugConsole.ThrowError("Could not find the method ''Load'' in " + t + ".", e);
}
}
borders = new Rectangle(0, 0, 1, 1);
foreach (Hull hull in Hull.hullList)
{
if (hull.Rect.X < borders.X || borders.X == 0) borders.X = hull.Rect.X;
if (hull.Rect.Y > borders.Y || borders.Y == 0) borders.Y = hull.Rect.Y;
if (hull.Rect.X + hull.Rect.Width > borders.X + borders.Width) borders.Width = hull.Rect.X + hull.Rect.Width - borders.X;
if (hull.Rect.Y - hull.Rect.Height < borders.Y - borders.Height) borders.Height = borders.Y - (hull.Rect.Y - hull.Rect.Height);
}
MapEntity.LinkAll();
foreach (Item item in Item.itemList)
{
foreach (ItemComponent ic in item.components)
{
ic.OnMapLoaded();
}
}
}
public static void Clear()
{
Map.filePath = "";
if (Game1.gameScreen.Cam != null) Game1.gameScreen.Cam.TargetPos = Vector2.Zero;
Entity.RemoveAll();
if (Game1.gameSession!=null)
Game1.gameSession.crewManager.EndShift();
PhysicsBody.list.Clear();
Ragdoll.list.Clear();
Game1.world.Clear();
}
}
}
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Xml.Linq;
using FarseerPhysics;
using FarseerPhysics.Dynamics;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using FarseerPhysics.Collision;
namespace Subsurface
{
public enum Direction : byte
{
None = 0, Left = 1, Right = 2
}
static class Map
{
static string MapFolder = "Content/SavedMaps";
public static Vector2 gridSize = new Vector2(16.0f, 16.0f);
private static Vector2 lastPickedPosition;
private static float lastPickedFraction;
private static Rectangle borders;
private static string filePath;
public static Vector2 LastPickedPosition
{
get { return lastPickedPosition; }
}
public static float LastPickedFraction
{
get { return lastPickedFraction; }
}
public static Rectangle Borders
{
get { return borders; }
}
public static string FilePath
{
get { return filePath; }
}
public static void Draw(SpriteBatch spriteBatch, bool editing = false)
{
for (int i = 0; i < MapEntity.mapEntityList.Count(); i++ )
{
MapEntity.mapEntityList[i].Draw(spriteBatch, editing);
}
}
public static void DrawFront(SpriteBatch spriteBatch, bool editing = false)
{
for (int i = 0; i < MapEntity.mapEntityList.Count(); i++)
{
if (MapEntity.mapEntityList[i].sprite == null || MapEntity.mapEntityList[i].sprite.Depth < 0.5f)
MapEntity.mapEntityList[i].Draw(spriteBatch, editing);
}
}
public static void DrawBack(SpriteBatch spriteBatch, bool editing = false)
{
for (int i = 0; i < MapEntity.mapEntityList.Count(); i++)
{
if (MapEntity.mapEntityList[i].sprite == null || MapEntity.mapEntityList[i].sprite.Depth >= 0.5f)
MapEntity.mapEntityList[i].Draw(spriteBatch, editing);
}
}
public static Vector2 MouseToWorldGrid(Camera cam)
{
Vector2 position = new Vector2(PlayerInput.GetMouseState.X, PlayerInput.GetMouseState.Y);
position = cam.ScreenToWorld(position);
return VectorToWorldGrid(position);
}
public static Vector2 VectorToWorldGrid(Vector2 position)
{
position.X = (float)Math.Floor(Convert.ToDouble(position.X / gridSize.X)) * gridSize.X;
position.Y = (float)Math.Ceiling(Convert.ToDouble(position.Y / gridSize.Y)) * gridSize.Y;
return position;
}
public static Rectangle AbsRect(Vector2 pos, Vector2 size)
{
if (size.X < 0.0f)
{
pos.X += size.X;
size.X = -size.X;
}
if (size.Y < 0.0f)
{
pos.Y -= size.Y;
size.Y = -size.Y;
}
return new Rectangle((int)pos.X, (int)pos.Y, (int)size.X, (int)size.Y);
}
public static bool RectContains(Rectangle rect, Vector2 pos)
{
return (pos.X > rect.X && pos.X < rect.X + rect.Width
&& pos.Y < rect.Y && pos.Y > rect.Y - rect.Height);
}
public static bool RectsOverlap(Rectangle rect1, Rectangle rect2)
{
return !(rect1.X > rect2.X + rect2.Width || rect1.X + rect1.Width < rect2.X ||
rect1.Y < rect2.Y - rect2.Height || rect1.Y - rect1.Height > rect2.Y);
}
public static Body PickBody(Vector2 rayStart, Vector2 rayEnd, List<Body> ignoredBodies = null)
{
float closestFraction = 1.0f;
Body closestBody = null;
Game1.world.RayCast((fixture, point, normal, fraction) =>
{
if (fixture == null || fixture.CollisionCategories == Category.None) return -1;
if (ignoredBodies != null && ignoredBodies.Contains(fixture.Body)) return -1;
Structure structure = fixture.Body.UserData as Structure;
if (structure != null && (structure.IsPlatform || !structure.HasBody)) return -1;
if (fraction < closestFraction)
{
closestFraction = fraction;
if (fixture.Body!=null) closestBody = fixture.Body;
}
return fraction;
}
, rayStart, rayEnd);
lastPickedPosition = rayStart + (rayEnd - rayStart) * closestFraction;
lastPickedFraction = closestFraction;
return closestBody;
}
public static Structure CheckVisibility(Vector2 rayStart, Vector2 rayEnd)
{
Structure closestStructure = null;
float closestFraction = 1.0f;
if (Vector2.Distance(rayStart,rayEnd)<0.01f)
{
closestFraction = 0.01f;
return null;
}
Game1.world.RayCast((fixture, point, normal, fraction) =>
{
if (fixture == null || fixture.CollisionCategories != Physics.CollisionWall) return -1;
Structure structure = fixture.Body.UserData as Structure;
if (structure != null)
{
if (structure.IsPlatform || structure.StairDirection != Direction.None) return -1;
int sectionIndex = structure.FindSectionIndex(ConvertUnits.ToDisplayUnits(point));
if (sectionIndex > -1 && structure.SectionHasHole(sectionIndex)) return -1;
}
if (fraction < closestFraction)
{
if (structure != null) closestStructure = structure;
closestFraction = fraction;
}
return closestFraction;
}
, rayStart, rayEnd);
lastPickedPosition = rayStart + (rayEnd - rayStart) * closestFraction;
lastPickedFraction = closestFraction;
return closestStructure;
}
public static Body PickBody(Vector2 point)
{
Body foundBody = null;
AABB aabb = new AABB(point, point);
Game1.world.QueryAABB(p =>
{
foundBody = p.Body;
return true;
}, ref aabb);
return foundBody;
}
public static bool InsideWall(Vector2 point)
{
Body foundBody = Map.PickBody(point);
if (foundBody==null) return false;
Structure wall = foundBody.UserData as Structure;
if (wall == null || wall.IsPlatform) return false;
return true;
}
public static void Save(string filePath, string fileName)
{
if (fileName==null)
{
DebugConsole.ThrowError("No save file selected");
return;
}
XDocument doc = new XDocument(
new XElement((XName)fileName));
foreach (MapEntity e in MapEntity.mapEntityList)
{
e.Save(doc);
}
try
{
string docString = doc.ToString();
ToolBox.CompressStringToFile(filePath+fileName+".gz", doc.ToString());
}
catch
{
DebugConsole.ThrowError("Saving map ''" + filePath + fileName + "'' failed!");
}
//doc.Save(filePath + fileName);
}
public static string[] GetMapFilePaths()
{
string[] mapFilePaths;
if (!Directory.Exists(MapFolder))
{
try
{
Directory.CreateDirectory(MapFolder);
}
catch
{
DebugConsole.ThrowError("Directory ''Content/SavedMaps'' not found and creating the directory failed.");
return null;
}
}
try
{
mapFilePaths = Directory.GetFiles(MapFolder);
}
catch (Exception e)
{
DebugConsole.ThrowError("Couldn't open directory ''Content/SavedMaps''!", e);
return null;
}
return mapFilePaths;
}
public static void Load(string filePath, string fileName)
{
Load(filePath + fileName);
}
public static void Load(string file)
{
Clear();
filePath = file;
XDocument doc = null;
string extension = Path.GetExtension(file);
if (extension==".gz")
{
Stream stream = ToolBox.DecompressFiletoStream(file);
if (stream == null)
{
DebugConsole.ThrowError("Loading map ''" + file + "'' failed!");
return;
}
try
{
stream.Position = 0;
doc = XDocument.Load(stream); //ToolBox.TryLoadXml(file);
stream.Close();
stream.Dispose();
}
catch
{
DebugConsole.ThrowError("Loading map ''" + file + "'' failed!");
return;
}
}
else if (extension ==".xml")
{
doc = XDocument.Load(file);
}
else
{
DebugConsole.ThrowError("Couldn't load map ''"+file+"! (Unrecognized file extension)");
return;
}
foreach (XElement element in doc.Root.Elements())
{
string typeName = element.Name.ToString();
Type t;
try
{
// Get the type of a specified class.
t = Type.GetType("Subsurface." + typeName + ", Subsurface", true, true);
if (t == null)
{
DebugConsole.ThrowError("Error in " + file + "! Could not find a entity of the type ''" + typeName + "''.");
continue;
}
}
catch (Exception e)
{
DebugConsole.ThrowError("Error in " + file + "! Could not find a entity of the type ''" + typeName + "''.", e);
continue;
}
try
{
MethodInfo loadMethod = t.GetMethod("Load");
loadMethod.Invoke(t, new object[] { element });
}
catch (Exception e)
{
DebugConsole.ThrowError("Could not find the method ''Load'' in " + t + ".", e);
}
}
borders = new Rectangle(0, 0, 1, 1);
foreach (Hull hull in Hull.hullList)
{
if (hull.Rect.X < borders.X || borders.X == 0) borders.X = hull.Rect.X;
if (hull.Rect.Y > borders.Y || borders.Y == 0) borders.Y = hull.Rect.Y;
if (hull.Rect.X + hull.Rect.Width > borders.X + borders.Width) borders.Width = hull.Rect.X + hull.Rect.Width - borders.X;
if (hull.Rect.Y - hull.Rect.Height < borders.Y - borders.Height) borders.Height = borders.Y - (hull.Rect.Y - hull.Rect.Height);
}
MapEntity.LinkAll();
foreach (Item item in Item.itemList)
{
foreach (ItemComponent ic in item.components)
{
ic.OnMapLoaded();
}
}
}
public static void Clear()
{
Map.filePath = "";
if (Game1.gameScreen.Cam != null) Game1.gameScreen.Cam.TargetPos = Vector2.Zero;
Entity.RemoveAll();
if (Game1.gameSession!=null)
Game1.gameSession.crewManager.EndShift();
PhysicsBody.list.Clear();
Ragdoll.list.Clear();
Game1.world.Clear();
}
}
}

View File

@@ -1,291 +1,291 @@
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using System;
namespace Subsurface
{
class EditMapScreen : Screen
{
Camera cam;
GUIComponent GUIpanel;
GUIComponent[] GUItabs;
int selectedTab;
//a character used for picking up and manipulating items
Character dummyCharacter;
bool characterMode;
public Camera Cam
{
get { return cam; }
}
public EditMapScreen()
{
cam = new Camera();
cam.Translate(new Vector2(-10.0f, 50.0f));
selectedTab = -1;
GUIpanel = new GUIFrame(new Rectangle(0,0, 120, Game1.GraphicsHeight), Color.DarkGray*0.8f);
GUIpanel.Padding = new Vector4(10.0f, 10.0f, 10.0f, 10.0f);
//GUIListBox constructionList = new GUIListBox(new Rectangle(0, 0, 0, 300), Color.White * 0.7f, GUIpanel);
//constructionList.OnSelected = MapEntityPrefab.SelectPrefab;
//constructionList.CheckSelected = MapEntityPrefab.GetSelected;
GUIButton button = new GUIButton(new Rectangle(0, 50, 100, 20), "Items", GUI.style, Alignment.Left, GUIpanel);
button.UserData = 0;
button.OnClicked = SelectTab;
button = new GUIButton(new Rectangle(0, 80, 100, 20), "Structures", GUI.style, Alignment.Left, GUIpanel);
button.UserData = 1;
button.OnClicked = SelectTab;
button = new GUIButton(new Rectangle(0, 140, 100, 20), "Character mode", GUI.style, Alignment.Left, GUIpanel);
button.OnClicked = ToggleCharacterMode;
GUItabs = new GUIComponent[2];
int width = 400, height = 400;
GUItabs[0] = new GUIFrame(new Rectangle(Game1.GraphicsWidth/2-width/2, Game1.GraphicsHeight/2-height/2, width, height), Color.DarkGray*0.8f);
GUItabs[0].Padding = new Vector4(10.0f, 10.0f, 10.0f, 10.0f);
GUIListBox itemList = new GUIListBox(new Rectangle(0, 0, 0, 0), Color.White * 0.7f, GUItabs[0]);
itemList.OnSelected = SelectPrefab;
itemList.CheckSelected = MapEntityPrefab.GetSelected;
GUItabs[1] = new GUIFrame(new Rectangle(Game1.GraphicsWidth / 2 - width / 2, Game1.GraphicsHeight / 2 - height / 2, width, height), Color.DarkGray * 0.8f);
GUItabs[1].Padding = new Vector4(10.0f, 10.0f, 10.0f, 10.0f);
GUIListBox structureList = new GUIListBox(new Rectangle(0, 0, 0, 300), Color.White * 0.7f, GUItabs[1]);
structureList.OnSelected = SelectPrefab;
structureList.CheckSelected = MapEntityPrefab.GetSelected;
foreach (MapEntityPrefab ep in MapEntityPrefab.list)
{
GUIListBox parent = ((ep as ItemPrefab) == null) ? structureList : itemList;
Color color = ((parent.CountChildren % 2) == 0) ? Color.White : Color.LightGray;
GUIFrame frame = new GUIFrame(new Rectangle(0, 0, 0, 50), Color.Transparent, parent);
frame.UserData = ep;
frame.Padding = new Vector4(5.0f, 5.0f, 5.0f, 5.0f);
frame.Color = color;
frame.HoverColor = Color.Gold * 0.2f;
frame.SelectedColor = Color.Gold * 0.5f;
GUITextBlock textBlock = new GUITextBlock(
new Rectangle(40, 0, 0, 25),
ep.Name,
Color.Transparent, Color.Black,
Alignment.Left,
Alignment.Left,
frame);
textBlock.Padding = new Vector4(5.0f, 0.0f, 5.0f, 0.0f);
if (ep.sprite != null)
{
GUIImage img = new GUIImage(new Rectangle(0, 0, 40, 40), ep.sprite, Alignment.Left, frame);
img.Scale = Math.Min(Math.Min(40.0f / img.SourceRect.Width, 40.0f / img.SourceRect.Height), 1.0f);
}
}
}
public override void Select()
{
base.Select();
GUIComponent.MouseOn = null;
characterMode = false;
//CreateDummyCharacter();
}
public override void Deselect()
{
base.Deselect();
GUIComponent.MouseOn = null;
if (dummyCharacter != null)
{
dummyCharacter.Remove();
dummyCharacter = null;
Game1.world.ProcessChanges();
}
}
private void CreateDummyCharacter()
{
if (dummyCharacter != null) dummyCharacter.Remove();
dummyCharacter = new Character("Content/Characters/Human/human.xml", Vector2.Zero);
Character.Controlled = dummyCharacter;
Game1.world.ProcessChanges();
}
private bool SelectTab(GUIButton button, object obj)
{
selectedTab = (int)obj;
return true;
}
private bool ToggleCharacterMode(GUIButton button, object obj)
{
characterMode = !characterMode;
button.Color = (characterMode) ? Color.Gold : Color.White;
if (characterMode)
{
CreateDummyCharacter();
}
else if (dummyCharacter != null)
{
dummyCharacter.Remove();
dummyCharacter = null;
}
foreach (MapEntity me in MapEntity.mapEntityList)
{
me.IsHighlighted = false;
me.IsSelected = false;
}
return true;
}
private bool SelectPrefab(object obj)
{
MapEntityPrefab.SelectPrefab(obj);
selectedTab = -1;
GUIComponent.MouseOn = null;
return true;
}
/// <summary>
/// Allows the game to run logic such as updating the world,
/// checking for collisions, gathering input, and playing audio.
/// </summary>
/// <param name="gameTime">Provides a snapshot of timing values.</param>
public override void Update(double deltaTime)
{
//Vector2 mousePosition = new Vector2(PlayerInput.GetMouseState.X, PlayerInput.GetMouseState.Y);
//mousePosition = cam.ScreenToWorld(mousePosition);
//if (!Character.characterList.Contains(dummyCharacter))
//{
// CreateDummyCharacter();
//}
cam.MoveCamera((float)deltaTime);
cam.Zoom = MathHelper.Clamp(cam.Zoom + PlayerInput.ScrollWheelSpeed/1000.0f,0.1f, 2.0f);
if (characterMode)
{
foreach (MapEntity me in MapEntity.mapEntityList)
{
me.IsHighlighted = false;
}
if (dummyCharacter.SelectedConstruction==null)
{
Vector2 mouseSimPos = FarseerPhysics.ConvertUnits.ToSimUnits(cam.ScreenToWorld(PlayerInput.MousePosition));
foreach (Limb limb in dummyCharacter.animController.limbs)
{
limb.body.SetTransform(mouseSimPos, 0.0f);
}
}
dummyCharacter.ControlLocalPlayer(cam, false);
dummyCharacter.Control(cam);
}
else
{
MapEntity.UpdateSelecting(cam);
}
GUIpanel.Update((float)deltaTime);
if (selectedTab > -1)
{
GUItabs[selectedTab].Update((float)deltaTime);
if (PlayerInput.RightButtonClicked()) selectedTab = -1;
}
}
/// <summary>
/// This is called when the game should draw itself.
/// </summary>
/// <param name="gameTime">Provides a snapshot of timing values.</param>
public override void Draw(double deltaTime, GraphicsDevice graphics, SpriteBatch spriteBatch)
{
//cam.UpdateTransform();
spriteBatch.Begin(SpriteSortMode.BackToFront,
BlendState.AlphaBlend,
null, null, null, null,
cam.Transform);
graphics.Clear(new Color(0.051f, 0.149f, 0.271f, 1.0f));
Map.Draw(spriteBatch, true);
if (!characterMode)
{
if (MapEntityPrefab.Selected != null) MapEntityPrefab.Selected.UpdatePlacing(spriteBatch, cam);
MapEntity.DrawSelecting(spriteBatch, cam);
}
spriteBatch.End();
//-------------------- HUD -----------------------------
spriteBatch.Begin();
GUIpanel.Draw(spriteBatch);
if (selectedTab > -1) GUItabs[selectedTab].Draw(spriteBatch);
GUI.Draw((float)deltaTime, spriteBatch);
//EntityPrefab.DrawList(spriteBatch, new Vector2(20,50));
if (characterMode)
{
if (dummyCharacter != null && dummyCharacter.SelectedConstruction != null)
{
if (Character.Controlled.SelectedConstruction == dummyCharacter.ClosestItem)
{
dummyCharacter.SelectedConstruction.DrawHUD(spriteBatch, dummyCharacter);
}
else
{
dummyCharacter.SelectedConstruction = null;
}
}
if (PlayerInput.GetMouseState.LeftButton != ButtonState.Pressed)
{
//if (Inventory.draggingItem!=null)
//{
// Inventory.draggingItem.see
//}
Inventory.draggingItem = null;
}
}
else
{
MapEntity.Edit(spriteBatch, cam);
}
spriteBatch.End();
}
}
}
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using System;
namespace Subsurface
{
class EditMapScreen : Screen
{
Camera cam;
GUIComponent GUIpanel;
GUIComponent[] GUItabs;
int selectedTab;
//a character used for picking up and manipulating items
Character dummyCharacter;
bool characterMode;
public Camera Cam
{
get { return cam; }
}
public EditMapScreen()
{
cam = new Camera();
cam.Translate(new Vector2(-10.0f, 50.0f));
selectedTab = -1;
GUIpanel = new GUIFrame(new Rectangle(0,0, 120, Game1.GraphicsHeight), Color.DarkGray*0.8f);
GUIpanel.Padding = new Vector4(10.0f, 10.0f, 10.0f, 10.0f);
//GUIListBox constructionList = new GUIListBox(new Rectangle(0, 0, 0, 300), Color.White * 0.7f, GUIpanel);
//constructionList.OnSelected = MapEntityPrefab.SelectPrefab;
//constructionList.CheckSelected = MapEntityPrefab.GetSelected;
GUIButton button = new GUIButton(new Rectangle(0, 50, 100, 20), "Items", GUI.style, Alignment.Left, GUIpanel);
button.UserData = 0;
button.OnClicked = SelectTab;
button = new GUIButton(new Rectangle(0, 80, 100, 20), "Structures", GUI.style, Alignment.Left, GUIpanel);
button.UserData = 1;
button.OnClicked = SelectTab;
button = new GUIButton(new Rectangle(0, 140, 100, 20), "Character mode", GUI.style, Alignment.Left, GUIpanel);
button.OnClicked = ToggleCharacterMode;
GUItabs = new GUIComponent[2];
int width = 400, height = 400;
GUItabs[0] = new GUIFrame(new Rectangle(Game1.GraphicsWidth/2-width/2, Game1.GraphicsHeight/2-height/2, width, height), Color.DarkGray*0.8f);
GUItabs[0].Padding = new Vector4(10.0f, 10.0f, 10.0f, 10.0f);
GUIListBox itemList = new GUIListBox(new Rectangle(0, 0, 0, 0), Color.White * 0.7f, GUItabs[0]);
itemList.OnSelected = SelectPrefab;
itemList.CheckSelected = MapEntityPrefab.GetSelected;
GUItabs[1] = new GUIFrame(new Rectangle(Game1.GraphicsWidth / 2 - width / 2, Game1.GraphicsHeight / 2 - height / 2, width, height), Color.DarkGray * 0.8f);
GUItabs[1].Padding = new Vector4(10.0f, 10.0f, 10.0f, 10.0f);
GUIListBox structureList = new GUIListBox(new Rectangle(0, 0, 0, 300), Color.White * 0.7f, GUItabs[1]);
structureList.OnSelected = SelectPrefab;
structureList.CheckSelected = MapEntityPrefab.GetSelected;
foreach (MapEntityPrefab ep in MapEntityPrefab.list)
{
GUIListBox parent = ((ep as ItemPrefab) == null) ? structureList : itemList;
Color color = ((parent.CountChildren % 2) == 0) ? Color.White : Color.LightGray;
GUIFrame frame = new GUIFrame(new Rectangle(0, 0, 0, 50), Color.Transparent, parent);
frame.UserData = ep;
frame.Padding = new Vector4(5.0f, 5.0f, 5.0f, 5.0f);
frame.Color = color;
frame.HoverColor = Color.Gold * 0.2f;
frame.SelectedColor = Color.Gold * 0.5f;
GUITextBlock textBlock = new GUITextBlock(
new Rectangle(40, 0, 0, 25),
ep.Name,
Color.Transparent, Color.Black,
Alignment.Left,
Alignment.Left,
frame);
textBlock.Padding = new Vector4(5.0f, 0.0f, 5.0f, 0.0f);
if (ep.sprite != null)
{
GUIImage img = new GUIImage(new Rectangle(0, 0, 40, 40), ep.sprite, Alignment.Left, frame);
img.Scale = Math.Min(Math.Min(40.0f / img.SourceRect.Width, 40.0f / img.SourceRect.Height), 1.0f);
}
}
}
public override void Select()
{
base.Select();
GUIComponent.MouseOn = null;
characterMode = false;
//CreateDummyCharacter();
}
public override void Deselect()
{
base.Deselect();
GUIComponent.MouseOn = null;
if (dummyCharacter != null)
{
dummyCharacter.Remove();
dummyCharacter = null;
Game1.world.ProcessChanges();
}
}
private void CreateDummyCharacter()
{
if (dummyCharacter != null) dummyCharacter.Remove();
dummyCharacter = new Character("Content/Characters/Human/human.xml", Vector2.Zero);
Character.Controlled = dummyCharacter;
Game1.world.ProcessChanges();
}
private bool SelectTab(GUIButton button, object obj)
{
selectedTab = (int)obj;
return true;
}
private bool ToggleCharacterMode(GUIButton button, object obj)
{
characterMode = !characterMode;
button.Color = (characterMode) ? Color.Gold : Color.White;
if (characterMode)
{
CreateDummyCharacter();
}
else if (dummyCharacter != null)
{
dummyCharacter.Remove();
dummyCharacter = null;
}
foreach (MapEntity me in MapEntity.mapEntityList)
{
me.IsHighlighted = false;
me.IsSelected = false;
}
return true;
}
private bool SelectPrefab(object obj)
{
MapEntityPrefab.SelectPrefab(obj);
selectedTab = -1;
GUIComponent.MouseOn = null;
return true;
}
/// <summary>
/// Allows the game to run logic such as updating the world,
/// checking for collisions, gathering input, and playing audio.
/// </summary>
/// <param name="gameTime">Provides a snapshot of timing values.</param>
public override void Update(double deltaTime)
{
//Vector2 mousePosition = new Vector2(PlayerInput.GetMouseState.X, PlayerInput.GetMouseState.Y);
//mousePosition = cam.ScreenToWorld(mousePosition);
//if (!Character.characterList.Contains(dummyCharacter))
//{
// CreateDummyCharacter();
//}
cam.MoveCamera((float)deltaTime);
cam.Zoom = MathHelper.Clamp(cam.Zoom + PlayerInput.ScrollWheelSpeed/1000.0f,0.1f, 2.0f);
if (characterMode)
{
foreach (MapEntity me in MapEntity.mapEntityList)
{
me.IsHighlighted = false;
}
if (dummyCharacter.SelectedConstruction==null)
{
Vector2 mouseSimPos = FarseerPhysics.ConvertUnits.ToSimUnits(cam.ScreenToWorld(PlayerInput.MousePosition));
foreach (Limb limb in dummyCharacter.animController.limbs)
{
limb.body.SetTransform(mouseSimPos, 0.0f);
}
}
dummyCharacter.ControlLocalPlayer(cam, false);
dummyCharacter.Control(cam);
}
else
{
MapEntity.UpdateSelecting(cam);
}
GUIpanel.Update((float)deltaTime);
if (selectedTab > -1)
{
GUItabs[selectedTab].Update((float)deltaTime);
if (PlayerInput.RightButtonClicked()) selectedTab = -1;
}
}
/// <summary>
/// This is called when the game should draw itself.
/// </summary>
/// <param name="gameTime">Provides a snapshot of timing values.</param>
public override void Draw(double deltaTime, GraphicsDevice graphics, SpriteBatch spriteBatch)
{
//cam.UpdateTransform();
spriteBatch.Begin(SpriteSortMode.BackToFront,
BlendState.AlphaBlend,
null, null, null, null,
cam.Transform);
graphics.Clear(new Color(0.051f, 0.149f, 0.271f, 1.0f));
Map.Draw(spriteBatch, true);
if (!characterMode)
{
if (MapEntityPrefab.Selected != null) MapEntityPrefab.Selected.UpdatePlacing(spriteBatch, cam);
MapEntity.DrawSelecting(spriteBatch, cam);
}
spriteBatch.End();
//-------------------- HUD -----------------------------
spriteBatch.Begin();
GUIpanel.Draw(spriteBatch);
if (selectedTab > -1) GUItabs[selectedTab].Draw(spriteBatch);
GUI.Draw((float)deltaTime, spriteBatch);
//EntityPrefab.DrawList(spriteBatch, new Vector2(20,50));
if (characterMode)
{
if (dummyCharacter != null && dummyCharacter.SelectedConstruction != null)
{
if (dummyCharacter.SelectedConstruction == dummyCharacter.ClosestItem)
{
dummyCharacter.SelectedConstruction.DrawHUD(spriteBatch, dummyCharacter);
}
else
{
dummyCharacter.SelectedConstruction = null;
}
}
if (PlayerInput.GetMouseState.LeftButton != ButtonState.Pressed)
{
//if (Inventory.draggingItem!=null)
//{
// Inventory.draggingItem.see
//}
Inventory.draggingItem = null;
}
}
else
{
MapEntity.Edit(spriteBatch, cam);
}
spriteBatch.End();
}
}
}

View File

@@ -1,14 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<PublishUrlHistory>publish\</PublishUrlHistory>
<InstallUrlHistory />
<SupportUrlHistory />
<UpdateUrlHistory />
<BootstrapperUrlHistory />
<ErrorReportUrlHistory />
<FallbackCulture>en-US</FallbackCulture>
<VerifyUploadedFiles>false</VerifyUploadedFiles>
<ProjectView>ShowAllFiles</ProjectView>
</PropertyGroup>
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<PublishUrlHistory>publish\</PublishUrlHistory>
<InstallUrlHistory />
<SupportUrlHistory />
<UpdateUrlHistory />
<BootstrapperUrlHistory />
<ErrorReportUrlHistory />
<FallbackCulture>en-US</FallbackCulture>
<VerifyUploadedFiles>false</VerifyUploadedFiles>
<ProjectView>ProjectFiles</ProjectView>
</PropertyGroup>
</Project>

Binary file not shown.