|
|
using System.Collections.Generic;
|
|
|
using System.Linq;
|
|
|
using Microsoft.Xna.Framework;
|
|
|
using Microsoft.Xna.Framework.Audio;
|
|
|
using Microsoft.Xna.Framework.Input;
|
|
|
using Microsoft.Xna.Framework.Graphics;
|
|
|
using Microsoft.Xna.Framework.Media;
|
|
|
|
|
|
|
|
|
using System;
|
|
|
using System.IO;
|
|
|
using SpriteFontPlus;
|
|
|
using isometricparkfna;
|
|
|
using System.Diagnostics;
|
|
|
|
|
|
using static isometricparkfna.CellMap;
|
|
|
using isometricparkfna.Utils;
|
|
|
using isometricparkfna.UI;
|
|
|
using isometricparkfna.Engines;
|
|
|
using isometricparkfna.Components;
|
|
|
using isometricparkfna.Renderers;
|
|
|
using isometricparkfna.Messages;
|
|
|
using isometricparkfna.Spawners;
|
|
|
|
|
|
using ImGuiNET.SampleProgram.XNA;
|
|
|
using ImGuiNET;
|
|
|
using TraceryNet;
|
|
|
using Encompass;
|
|
|
|
|
|
class FNAGame : Game
|
|
|
{
|
|
|
private KeyboardState keyboardPrev = new KeyboardState();
|
|
|
private MouseState mousePrev = new MouseState();
|
|
|
|
|
|
private SpriteBatch batch;
|
|
|
private SoundEffect sound;
|
|
|
private SpriteFont monoFont;
|
|
|
|
|
|
private Camera camera = new Camera(new float[] { 0.25f, 0.5f, 1.0f, 2.0f, 4.0f });
|
|
|
|
|
|
Random random_generator = new Random();
|
|
|
|
|
|
int frameRate = 0;
|
|
|
int frameCounter = 0;
|
|
|
TimeSpan elapsedTime = TimeSpan.Zero;
|
|
|
TimeSpan drawTime = TimeSpan.Zero;
|
|
|
TimeSpan updateTime = TimeSpan.Zero;
|
|
|
|
|
|
Queue<float> past_fps = new Queue<float>(100);
|
|
|
int tilesDrawn = 0;
|
|
|
|
|
|
private const int width = 1280;
|
|
|
private const int height = 640;
|
|
|
|
|
|
//new tile stuff
|
|
|
int squaresAcross = 50;
|
|
|
int squaresDown = 50;
|
|
|
// int baseOffsetX = -14;
|
|
|
// int baseOffsetY = -14;
|
|
|
|
|
|
Simulation simulation;
|
|
|
|
|
|
public Vector2 mouseGrid;
|
|
|
Vector2 original_point;
|
|
|
|
|
|
//for now
|
|
|
public bool in_zone;
|
|
|
|
|
|
private ImGuiRenderer _imGuiRenderer;
|
|
|
private DebugWindow debugWindow;
|
|
|
|
|
|
public ImageMap imageMap;
|
|
|
|
|
|
public bool show_another_window;
|
|
|
private bool showInitial;
|
|
|
int messageIndex;
|
|
|
|
|
|
//buggy
|
|
|
private static bool enableCulling = false;
|
|
|
|
|
|
private Node<DialogOption> currentNode;
|
|
|
private Queue<Node<DialogOption>> remainingDialog;
|
|
|
private List<NewsItem> newsItems;
|
|
|
|
|
|
|
|
|
public bool showGrid;
|
|
|
public bool showTrees;
|
|
|
private Grammar grammar;
|
|
|
private string output;
|
|
|
private GraphicsDeviceManager gdm;
|
|
|
public bool showBudget;
|
|
|
private BudgetWindow budgetWindow;
|
|
|
public bool showForest;
|
|
|
public bool showNews;
|
|
|
|
|
|
//Encompass
|
|
|
private WorldBuilder WorldBuilder = new WorldBuilder();
|
|
|
private World World;
|
|
|
|
|
|
private ImGuiWindowBridgeEngine imGuiWindowBridgeEngine;
|
|
|
|
|
|
private static void Main(string[] args)
|
|
|
{
|
|
|
#if NETCOREAPP
|
|
|
DllMap.Initialise(false);
|
|
|
#endif
|
|
|
using FNAGame g = new FNAGame();
|
|
|
g.Run();
|
|
|
|
|
|
#if !DEBUG
|
|
|
Logging.logFile.Close();
|
|
|
File.Delete(Logging.logFileName);
|
|
|
#endif
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private FNAGame()
|
|
|
{
|
|
|
|
|
|
#if DEBUG
|
|
|
foreach (System.Reflection.Assembly assembly in AppDomain.CurrentDomain.GetAssemblies())
|
|
|
{
|
|
|
Logging.Debug(assembly.ToString() + "\n");
|
|
|
}
|
|
|
;
|
|
|
|
|
|
#endif
|
|
|
this.gdm = new GraphicsDeviceManager(this) {
|
|
|
// Typically you would load a config here...
|
|
|
PreferredBackBufferWidth = width,
|
|
|
PreferredBackBufferHeight = height,
|
|
|
IsFullScreen = false,
|
|
|
SynchronizeWithVerticalRetrace = true
|
|
|
};
|
|
|
//gdm.SynchronizeWithVerticalRetrace = false;
|
|
|
IsFixedTimeStep = false;
|
|
|
|
|
|
this.simulation = new Simulation(this.squaresAcross, this.squaresDown, new float[] {16.66667f*240, 16.66667f*120, 16.66667f*60, 16.66667f*30f, 16.66667f*1 });
|
|
|
|
|
|
foreach (List<Cell> row in this.simulation.map.cells)
|
|
|
{
|
|
|
foreach (Cell cell in row)
|
|
|
{
|
|
|
if (this.random_generator.NextDouble() > 0.75)
|
|
|
{
|
|
|
int random_year = (int)MathHelper.Clamp((float)MathUtils.NextNormal(random_generator, 2010.0f, 40.0f), 1800, Simulation.START_YEAR);
|
|
|
int random_month = random_generator.Next(1, 12);
|
|
|
DateTime random_date = new DateTime(random_year, random_month, 1);
|
|
|
|
|
|
cell.addTree(random_date);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
showInitial = true;
|
|
|
messageIndex = 0;
|
|
|
showBudget = false;
|
|
|
showForest = false;
|
|
|
showNews = false;
|
|
|
showGrid = true;
|
|
|
showTrees = true;
|
|
|
|
|
|
this.Window.Title = "Isometric Park";
|
|
|
|
|
|
Content.RootDirectory = "Content";
|
|
|
|
|
|
currentNode = DialogTrees.introTree;
|
|
|
|
|
|
}
|
|
|
|
|
|
protected override void Initialize()
|
|
|
{
|
|
|
/* This is a nice place to start up the engine, after
|
|
|
* loading configuration stuff in the constructor
|
|
|
*/
|
|
|
this.IsMouseVisible = true;
|
|
|
|
|
|
_imGuiRenderer = new ImGuiRenderer(this);
|
|
|
_imGuiRenderer.RebuildFontAtlas(); // Required so fonts are available for rendering
|
|
|
|
|
|
base.Initialize();
|
|
|
}
|
|
|
|
|
|
protected override void LoadContent()
|
|
|
{
|
|
|
// Create the batch...
|
|
|
batch = new SpriteBatch(GraphicsDevice);
|
|
|
|
|
|
sound = Content.Load<SoundEffect>("FNASound");
|
|
|
Tile.TileSetTexture = Content.Load<Texture2D>(@"part4_tileset");
|
|
|
var texture = Content.Load<Texture2D>(@"solid_tileset");
|
|
|
|
|
|
ImageMap.ImageMapTexture = Content.Load<Texture2D>(@"photos_converted3");
|
|
|
this.imageMap = new ImageMap(500, 400);
|
|
|
|
|
|
Line.initialize(GraphicsDevice);
|
|
|
Quad.Initialize(GraphicsDevice, texture);
|
|
|
Logging.Success("Initialized Quad texture.");
|
|
|
ContractWindow.LoadContent(this._imGuiRenderer, this.imageMap);
|
|
|
|
|
|
//Has to happen before Encompass stuff, because the Encompass machinery around ImGui requires debugWindow's monoFont to be loaded:
|
|
|
this.debugWindow = new DebugWindow(this._imGuiRenderer, GraphicsDevice, this.imageMap);
|
|
|
|
|
|
//Has to happen before Encompass stuff, so Spawners can use the grammar:
|
|
|
var json2 = new FileInfo(@"Content/grammar.json");
|
|
|
|
|
|
this.grammar = new TraceryNet.Grammar(json2);
|
|
|
|
|
|
|
|
|
WorldBuilder.AddEngine(new InputEngine(Menu.MENU_BAR_HEIGHT, FNAGame.width, FNAGame.height, this.camera, GraphicsDevice));
|
|
|
WorldBuilder.AddEngine(new UIEngine());
|
|
|
|
|
|
WorldBuilder.AddEngine(new GameBridgeEngine(this));
|
|
|
WorldBuilder.AddEngine(this.simulation.BridgeEngine);
|
|
|
WorldBuilder.AddEngine(new CameraBridgeEngine(this.camera));
|
|
|
this.imGuiWindowBridgeEngine = new ImGuiWindowBridgeEngine();
|
|
|
WorldBuilder.AddEngine(this.imGuiWindowBridgeEngine);
|
|
|
WorldBuilder.AddEngine(new ContractStatusEngine(this.simulation));
|
|
|
|
|
|
WorldBuilder.AddEngine(new ContractSpawner(simulation.map.MapWidth, simulation.map.MapHeight, this.simulation, this.grammar));
|
|
|
WorldBuilder.AddEngine(new OrganizationSpawner(this.simulation, this.grammar));
|
|
|
|
|
|
WorldBuilder.AddGeneralRenderer(new AreaRenderer(this.batch, this.monoFont), 1);
|
|
|
WorldBuilder.AddGeneralRenderer(new ImGuiWindowRenderer(debugWindow.monoFont, debugWindow.italicFont, this.imGuiWindowBridgeEngine), 2);
|
|
|
var contractWindow = WorldBuilder.CreateEntity();
|
|
|
WorldBuilder.SetComponent(contractWindow, new VisibilityComponent { visible = false });
|
|
|
WorldBuilder.SetComponent(contractWindow, new WindowTypeComponent { type = isometricparkfna.Messages.Window.Contracts });
|
|
|
|
|
|
|
|
|
var forestWindow = WorldBuilder.CreateEntity();
|
|
|
WorldBuilder.SetComponent(forestWindow, new VisibilityComponent { visible = false });
|
|
|
WorldBuilder.SetComponent(forestWindow, new WindowTypeComponent { type = isometricparkfna.Messages.Window.Forest });
|
|
|
|
|
|
var newsWindow = WorldBuilder.CreateEntity();
|
|
|
WorldBuilder.SetComponent(newsWindow, new VisibilityComponent { visible = false });
|
|
|
WorldBuilder.SetComponent(newsWindow, new WindowTypeComponent { type = isometricparkfna.Messages.Window.News });
|
|
|
|
|
|
// var budgetWindow = WorldBuilder.CreateEntity();
|
|
|
// WorldBuilder.SetComponent(budgetWindow, new VisibilityComponent{visible = true});
|
|
|
// WorldBuilder.SetComponent(budgetWindow, new BudgetComponent());
|
|
|
|
|
|
var area = WorldBuilder.CreateEntity();
|
|
|
// WorldBuilder.SetComponent(area, new AreaComponent{squares = new[] {new Vector2(4,4), new Vector2(5,4)}});
|
|
|
var size = 5;
|
|
|
var squares = new Vector2[size * size];
|
|
|
var start_x = 10;
|
|
|
|
|
|
for (int i = 0; i < size; i++)
|
|
|
{
|
|
|
for (int j = 0; j < size; j++)
|
|
|
{
|
|
|
squares[i * size + j] = new Vector2(i + start_x, j);
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
for (int i = 0; i < 3; i++)
|
|
|
{
|
|
|
|
|
|
WorldBuilder.SendMessage(new SpawnOrganizationtMessage { offersContracts = true,
|
|
|
name = "#family_company.capitalizeAll#",
|
|
|
description = "#family_company_description#",
|
|
|
type = OrganizationType.Family });
|
|
|
WorldBuilder.SendMessage(new SpawnOrganizationtMessage { offersContracts = true,
|
|
|
name = "#large_company.capitalizeAll#",
|
|
|
description = "#large_company_description#",
|
|
|
type = OrganizationType.LargeCorporation });
|
|
|
}
|
|
|
WorldBuilder.SendMessage(new SpawnOrganizationtMessage { offersContracts = true,
|
|
|
name = "#logging_company.capitalizeAll#",
|
|
|
description = "#company_description#" });
|
|
|
WorldBuilder.SendMessage(new SpawnOrganizationtMessage { offersContracts = true,
|
|
|
name = "#coop_company.capitalizeAll#",
|
|
|
description = "#coop_company_description#",
|
|
|
type = OrganizationType.Cooperative });
|
|
|
WorldBuilder.SendMessage(new SpawnOrganizationtMessage { offersContracts = true,
|
|
|
name = "#coop_company.capitalizeAll#",
|
|
|
description = "#coop_company_description#",
|
|
|
type = OrganizationType.Cooperative });
|
|
|
WorldBuilder.SendMessage(new SpawnContractMessage
|
|
|
{
|
|
|
squares = squares,
|
|
|
name = "Northshore Logging"
|
|
|
});
|
|
|
WorldBuilder.SendMessage(new SpawnContractMessage
|
|
|
{
|
|
|
name = "Aeres Maximalis Ltd."
|
|
|
});
|
|
|
World = WorldBuilder.Build();
|
|
|
|
|
|
var bakedMono = TtfFontBaker.Bake(File.OpenRead(@"Content/iosevka-term-extendedmedium.ttf"),
|
|
|
15,
|
|
|
1024,
|
|
|
1024,
|
|
|
new[]
|
|
|
{
|
|
|
CharacterRange.BasicLatin,
|
|
|
CharacterRange.Latin1Supplement,
|
|
|
CharacterRange.LatinExtendedA,
|
|
|
CharacterRange.Cyrillic,
|
|
|
CharacterRange.LatinExtendedB,
|
|
|
new CharacterRange((char) 0x00B7)
|
|
|
}
|
|
|
);
|
|
|
|
|
|
|
|
|
this.output = grammar.Flatten("#greeting#");
|
|
|
var result = grammar.Flatten("#[assistantName:#assistantNames#][whatever:whatever]vars#");
|
|
|
|
|
|
Func<string, string> toUpper = delegate (string i)
|
|
|
{
|
|
|
return i.ToUpper();
|
|
|
};
|
|
|
|
|
|
grammar.AddModifier("toUpper", toUpper);
|
|
|
|
|
|
var newItems = new[] {new NewsItem{hed="Test", contents="#city.toUpper# - This is where the lede would go. #whatever#", source="Wire"}
|
|
|
};
|
|
|
|
|
|
this.newsItems = newItems.ToList();
|
|
|
|
|
|
using (var sr = new StreamReader(@"Content/news_items.yaml"))
|
|
|
{
|
|
|
this.newsItems.AddRange(NewsItem.FromYaml(sr.ReadToEnd()));
|
|
|
}
|
|
|
using (var sr_pregenerated = new StreamReader(@"Content/news_items_pregenerated.yaml"))
|
|
|
{
|
|
|
this.newsItems.AddRange(NewsItem.FromYaml(sr_pregenerated.ReadToEnd()));
|
|
|
}
|
|
|
this.simulation.LoadContent(this.newsItems, this.grammar);
|
|
|
|
|
|
this.remainingDialog = new Queue<Node<DialogOption>>();
|
|
|
|
|
|
#if DEBUG
|
|
|
this.remainingDialog.Enqueue(DialogTrees.flatten(DialogTrees.testTree, this.grammar));
|
|
|
#endif
|
|
|
|
|
|
//font = fontBakeResult.CreateSpriteFont(GraphicsDevice);
|
|
|
monoFont = bakedMono.CreateSpriteFont(GraphicsDevice);
|
|
|
|
|
|
this.budgetWindow = new BudgetWindow(new Budget { }, this.monoFont, 0, 0);
|
|
|
|
|
|
Logging.Success("Content loaded.");
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
protected override void UnloadContent()
|
|
|
{
|
|
|
batch.Dispose();
|
|
|
sound.Dispose();
|
|
|
Tile.TileSetTexture.Dispose();
|
|
|
Logging.Success("Disposed of Tile texture.");
|
|
|
if (Quad.PixelTexture != null)
|
|
|
{
|
|
|
Quad.PixelTexture.Dispose();
|
|
|
Logging.Success("Disposed of Pixel texture.");
|
|
|
}
|
|
|
if (Quad.SolidTexture != null)
|
|
|
{
|
|
|
Quad.SolidTexture.Dispose();
|
|
|
}
|
|
|
}
|
|
|
|
|
|
Vector2 calculateMousegrid(Vector2 normalizedMousePos)
|
|
|
{
|
|
|
//int gridx = (int)(normalizedMousePos.X / Tile.TileSpriteWidth);
|
|
|
//int gridy = (int)(normalizedMousePos.Y / Tile.TileSpriteHeight);
|
|
|
Vector2 adjust = new Vector2(Tile.TileSpriteWidth / 2, Tile.TileSpriteHeight);
|
|
|
Vector2 adjustedMousePos = normalizedMousePos - adjust;
|
|
|
|
|
|
float boardx = ((adjustedMousePos.X / Tile.TileSpriteWidth) + (adjustedMousePos.Y / Tile.TileSpriteHeight));
|
|
|
float boardy = ((adjustedMousePos.Y / Tile.TileSpriteHeight) - (adjustedMousePos.X / Tile.TileSpriteWidth));
|
|
|
|
|
|
|
|
|
return new Vector2((int)boardx, (int)boardy);
|
|
|
/*
|
|
|
int gridx = (int)((normalizedMousePos.X + (this.baseOffsetX + 4)) / Tile.TileWidth) ;
|
|
|
int gridy = (int)((normalizedMousePos.Y + (this.baseOffsetX + 4) + (2*baseOffsetY)) / (Tile.TileStepY));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int within_gridx = (int)((normalizedMousePos.X) % Tile.TileWidth) - (Tile.TileWidth/2);
|
|
|
int within_gridy = (int)((normalizedMousePos.Y) % Tile.TileHeight) - (Tile.TileHeight / 2);
|
|
|
|
|
|
int middle_distance = Math.Abs(within_gridx) + Math.Abs(within_gridx);
|
|
|
Vector2 adjustment_vector;
|
|
|
|
|
|
return new Vector2(gridx, gridy);
|
|
|
if (middle_distance < (Tile.TileWidth / 2))
|
|
|
{
|
|
|
return new Vector2(gridx, gridy);
|
|
|
}
|
|
|
|
|
|
else if ((Math.Sign(within_gridx) == -1) && (Math.Sign(within_gridy) == 1))
|
|
|
{
|
|
|
adjustment_vector = new Vector2(-1, -1);
|
|
|
return new Vector2(gridx, gridy) + adjustment_vector;
|
|
|
}
|
|
|
else if ((Math.Sign(within_gridx) == -1) && (Math.Sign(within_gridy) == -1))
|
|
|
{
|
|
|
adjustment_vector = new Vector2(-1, 1);
|
|
|
return new Vector2(gridx, gridy) + adjustment_vector;
|
|
|
}
|
|
|
else if ((Math.Sign(within_gridx) == 1) && (Math.Sign(within_gridy) == 1))
|
|
|
{
|
|
|
adjustment_vector = new Vector2(0, -1);
|
|
|
return new Vector2(gridx, gridy) + adjustment_vector;
|
|
|
}
|
|
|
else if ((Math.Sign(within_gridx) == 1) && (Math.Sign(within_gridy) == -1))
|
|
|
{
|
|
|
adjustment_vector = new Vector2(0, 1);
|
|
|
return new Vector2(gridx, gridy) + adjustment_vector;
|
|
|
}
|
|
|
else {
|
|
|
return new Vector2(gridx, gridy);
|
|
|
}
|
|
|
*/
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
protected override void Update(GameTime gameTime)
|
|
|
{
|
|
|
|
|
|
Stopwatch stopWatch = new Stopwatch();
|
|
|
stopWatch.Start();
|
|
|
|
|
|
float volume = 1.0f;
|
|
|
float pitch = 0.0f;
|
|
|
float pan = 0.0f;
|
|
|
|
|
|
KeyboardState keyboardCur = Keyboard.GetState();
|
|
|
MouseState mouseCur = Mouse.GetState();
|
|
|
|
|
|
#region input
|
|
|
//
|
|
|
#region misc_keys
|
|
|
if (keyboardCur.IsKeyDown(Keys.OemBackslash) && keyboardPrev.IsKeyUp(Keys.OemBackslash) && keyboardCur.IsKeyDown(Keys.LeftShift))
|
|
|
{
|
|
|
sound.Play(volume, pitch, pan);
|
|
|
}
|
|
|
#endregion misc_keys
|
|
|
//
|
|
|
|
|
|
#endregion input
|
|
|
|
|
|
|
|
|
|
|
|
World.Update(gameTime.ElapsedGameTime.TotalSeconds);
|
|
|
this.simulation.update(gameTime.ElapsedGameTime);
|
|
|
|
|
|
if (this.showBudget)
|
|
|
{
|
|
|
this.showBudget = this.budgetWindow.update(mouseCur, this.simulation.latestBudget, this.simulation.previousBudget);
|
|
|
}
|
|
|
|
|
|
|
|
|
if (!this.showInitial && this.remainingDialog.Count > 0)
|
|
|
{
|
|
|
this.currentNode = this.remainingDialog.Dequeue();
|
|
|
this.showInitial = true;
|
|
|
}
|
|
|
|
|
|
this.original_point = Vector2.Transform(new Vector2(mouseCur.X, mouseCur.Y), Matrix.Invert(camera.get_transformation(GraphicsDevice)));
|
|
|
|
|
|
//int gridx = (int)((this.original_point.X-baseOffsetX) / Tile.TileStepX);
|
|
|
/* int gridx = (int)(this.original_point.Y / Tile.TileHeight + this.original_point.X / Tile.TileWidth); */
|
|
|
//int gridy = (int)((this.original_point.Y-baseOffsetY) / (Tile.TileStepY*2));
|
|
|
/* int gridy = (int)(this.original_point.Y / Tile.TileHeight - this.original_point.X / Tile.TileWidth); */
|
|
|
|
|
|
//this.mouseGrid = new Vector2(gridx, gridy);
|
|
|
this.mouseGrid = this.calculateMousegrid(this.original_point);
|
|
|
|
|
|
elapsedTime += gameTime.ElapsedGameTime;
|
|
|
|
|
|
if (elapsedTime > TimeSpan.FromSeconds(1))
|
|
|
{
|
|
|
elapsedTime -= TimeSpan.FromSeconds(1);
|
|
|
frameRate = frameCounter;
|
|
|
frameCounter = 0;
|
|
|
}
|
|
|
|
|
|
this.keyboardPrev = keyboardCur;
|
|
|
this.mousePrev = mouseCur;
|
|
|
|
|
|
stopWatch.Stop();
|
|
|
this.updateTime = stopWatch.Elapsed;
|
|
|
|
|
|
base.Update(gameTime);
|
|
|
|
|
|
}
|
|
|
|
|
|
protected float calculateDepth() {
|
|
|
return ((this.squaresAcross + 1) + ((this.squaresDown + 1) * Tile.TileWidth)) * 10;
|
|
|
}
|
|
|
|
|
|
protected Boolean cull(int gridX, int gridY)
|
|
|
{
|
|
|
int screenX = (gridX - gridY) * Tile.TileSpriteWidth / 2;
|
|
|
int screenY = (gridX + gridY) * Tile.TileSpriteHeight / 2;
|
|
|
|
|
|
Vector2 original = Vector2.Transform(new Vector2(screenX, screenY), camera.get_transformation(GraphicsDevice));
|
|
|
|
|
|
return (!FNAGame.enableCulling ||
|
|
|
(MathUtils.BetweenExclusive(original.X, -Tile.TileSpriteWidth, FNAGame.width)
|
|
|
&& MathUtils.BetweenExclusive(original.Y, -Tile.TileSpriteHeight, FNAGame.height)));
|
|
|
}
|
|
|
|
|
|
//Convenience method I'm not super sure about anymore.
|
|
|
protected void drawTileAt(int x, int y, int tileIndex, int height)
|
|
|
{
|
|
|
float maxdepth = ((this.squaresAcross + 1) + ((this.squaresDown + 1) * Tile.TileWidth)) * 10;
|
|
|
|
|
|
float depthOffset = 0.7f - ((0 + (0 * Tile.TileWidth)) / maxdepth);
|
|
|
|
|
|
Tile.drawTileAt(this.batch, x, y, tileIndex, height, depthOffset);
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
protected override void Draw(GameTime gameTime)
|
|
|
{
|
|
|
frameCounter++;
|
|
|
|
|
|
string fps = string.Format("fps: {0}", frameRate);
|
|
|
|
|
|
Stopwatch stopWatch = new Stopwatch();
|
|
|
stopWatch.Start();
|
|
|
GraphicsDevice.Clear(Color.CornflowerBlue);
|
|
|
batch.Begin(SpriteSortMode.BackToFront,
|
|
|
BlendState.AlphaBlend,
|
|
|
null,
|
|
|
null,
|
|
|
null,
|
|
|
null,
|
|
|
camera.get_transformation(GraphicsDevice));
|
|
|
|
|
|
|
|
|
#region draw_tiles
|
|
|
//reset
|
|
|
this.tilesDrawn = 0;
|
|
|
|
|
|
for (int y = 0; y < this.squaresDown; y++)
|
|
|
{
|
|
|
for (int x = 0; x < this.squaresAcross; x++)
|
|
|
{
|
|
|
int screenx = (x - y) * Tile.TileSpriteWidth / 2;
|
|
|
int screeny = (x + y) * Tile.TileSpriteHeight / 2;
|
|
|
|
|
|
if (this.cull(x, y))
|
|
|
{
|
|
|
batch.Draw(
|
|
|
Tile.TileSetTexture,
|
|
|
new Rectangle(
|
|
|
screenx,
|
|
|
screeny,
|
|
|
Tile.TileWidth, Tile.TileHeight),
|
|
|
Tile.GetSourceRectangle(1),
|
|
|
Color.White,
|
|
|
0.0f,
|
|
|
Vector2.Zero,
|
|
|
SpriteEffects.None,
|
|
|
0.9f);
|
|
|
|
|
|
this.tilesDrawn++;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
#endregion draw_tiles
|
|
|
|
|
|
#region draw_gridlines
|
|
|
|
|
|
if (this.showGrid)
|
|
|
{
|
|
|
//need to go one extra so gridlines include the far side of the final tile:
|
|
|
for (int y = 0; y < (this.squaresDown + 1); y++)
|
|
|
{
|
|
|
|
|
|
Vector2 adjust = new Vector2(Tile.TileSpriteWidth / 2, Tile.TileSpriteHeight); //TODO figure out why this second value shouldn't be halved
|
|
|
|
|
|
Line.drawLine(batch,
|
|
|
new Vector2(((0 - y) * Tile.TileSpriteWidth / 2),
|
|
|
(0 + y) * Tile.TileSpriteHeight / 2) + adjust,
|
|
|
//new Vector2(this.squaresAcross * Tile.TileSpriteWidth, (y+1) * Tile.TileSpriteHeight),
|
|
|
new Vector2((this.squaresAcross - (y)) * Tile.TileSpriteWidth / 2,
|
|
|
(this.squaresAcross + (y)) * Tile.TileSpriteHeight / 2) + adjust,
|
|
|
|
|
|
Color.White, 0.81f);//Just below the highlighted square and areas
|
|
|
|
|
|
}
|
|
|
|
|
|
for (int x = 0; x < (this.squaresAcross + 1); x++)
|
|
|
{
|
|
|
|
|
|
Vector2 adjust = new Vector2(Tile.TileSpriteWidth / 2, Tile.TileSpriteHeight); //TODO figure out why this second value shouldn't be halved
|
|
|
|
|
|
Line.drawLine(batch,
|
|
|
new Vector2(((x - 0) * Tile.TileSpriteWidth / 2), (x + 0) * Tile.TileSpriteHeight / 2) + adjust,
|
|
|
//new Vector2(this.squaresAcross * Tile.TileSpriteWidth, (y+1) * Tile.TileSpriteHeight),
|
|
|
new Vector2((x - this.squaresDown) * Tile.TileSpriteWidth / 2, (x + this.squaresDown) * Tile.TileSpriteHeight / 2) + adjust,
|
|
|
Color.White, 0.81f);
|
|
|
|
|
|
}
|
|
|
}
|
|
|
#endregion draw_gridlines
|
|
|
|
|
|
|
|
|
//Gridlines
|
|
|
//Lines going down and to the right:
|
|
|
/*
|
|
|
for (int x = (int)(-this.squaresAcross/2); x < this.squaresAcross; x++)
|
|
|
{
|
|
|
int rowOffset = 0;
|
|
|
|
|
|
float startX = (x * Tile.TileStepX) + baseOffsetX - (Tile.TileStepX / 2);
|
|
|
|
|
|
Vector2 start = new Vector2(startX, -baseOffsetY+4);
|
|
|
Vector2 stop = new Vector2(startX + this.squaresAcross* Tile.TileStepX/2,
|
|
|
this.squaresDown*Tile.TileStepY- baseOffsetY+4);
|
|
|
|
|
|
|
|
|
|
|
|
Line.drawLine(batch,
|
|
|
Line.departurePoint(stop, start, this.squaresAcross * Tile.TileWidth, this.squaresDown * Tile.TileHeight),
|
|
|
Line.departurePoint(start, stop, this.squaresAcross * Tile.TileWidth, this.squaresDown * Tile.TileHeight),
|
|
|
Color.White, 0.8f);
|
|
|
|
|
|
}
|
|
|
//Lines going down and to the left:
|
|
|
for (int x = 0; x < (int)(1.5*this.squaresAcross); x++)
|
|
|
{
|
|
|
|
|
|
float startX = (x * Tile.TileStepX) + baseOffsetX - (Tile.TileStepX / 2);
|
|
|
|
|
|
Vector2 start_reverse = new Vector2(startX, -baseOffsetY + 4);
|
|
|
Vector2 stop_reverse = new Vector2(startX + -(this.squaresAcross * Tile.TileStepX / 2),
|
|
|
(this.squaresDown * Tile.TileStepY) - baseOffsetY + 4);
|
|
|
|
|
|
Line.drawLine(batch,
|
|
|
Line.departurePoint(stop_reverse, start_reverse, this.squaresAcross * Tile.TileWidth, this.squaresDown * Tile.TileHeight),
|
|
|
Line.departurePoint(start_reverse, stop_reverse, this.squaresAcross * Tile.TileWidth, this.squaresDown * Tile.TileHeight),
|
|
|
Color.White, 0.8f);
|
|
|
|
|
|
}
|
|
|
*/
|
|
|
|
|
|
#if DEBUG
|
|
|
drawTileAt(4, 4, 140, 3);
|
|
|
drawTileAt(6, 4, 141, 3);
|
|
|
drawTileAt(8, 4, 142, 2);
|
|
|
drawTileAt(10, 4, 142, 3);
|
|
|
#endif
|
|
|
|
|
|
#region draw_cursor
|
|
|
//drawTileAt((int)this.mouseGrid.X, (int)this.mouseGrid.Y, 2, 1, 0.85f); //between tiles and gridlines
|
|
|
|
|
|
if (MathUtils.Between(this.mouseGrid.X, 0, this.simulation.map.MapWidth)
|
|
|
&& MathUtils.Between(this.mouseGrid.Y, 0, this.simulation.map.MapHeight))
|
|
|
{
|
|
|
Tile.OutlineSquare(batch, this.mouseGrid.X, this.mouseGrid.Y, Color.Yellow, 1);
|
|
|
}
|
|
|
|
|
|
#if DEBUG
|
|
|
Tile.OutlineSquare(batch, 1, 1, Color.Red, 2);
|
|
|
Tile.OutlineSquare(batch, 3, 1, Color.Blue, 2);
|
|
|
Tile.OutlineSquare(batch, 5, 1, Color.Green, 2);
|
|
|
Tile.OutlineSquare(batch, 7, 1, Color.Orange, 2);
|
|
|
Tile.OutlineSquare(batch, 9, 1, Color.Orange, 3);
|
|
|
// Tile.OutlineSquare2(batch, 12, 1, Color.Orange, 2);
|
|
|
|
|
|
//Tile.drawEdge(batch, new Edge {Start=new Vector2(14, 1), End= new Vector2(15, 1)}, Color.Orange);
|
|
|
|
|
|
//donut
|
|
|
Tile.DrawOutlinedSquares(batch, new Vector2[] {new Vector2(19, 1), new Vector2(19, 2), new Vector2(20, 1), new Vector2(21, 1),
|
|
|
new Vector2(21, 2), new Vector2(19, 3), new Vector2(20, 3), new Vector2(21, 3)}, Color.Purple);
|
|
|
|
|
|
Quad.FillSquare2(batch, 7, 4, Color.Orange, 1.0f, 0.79f);
|
|
|
Quad.FillSquare2(batch, 7, 3, Color.Yellow, 1.0f, 0.79f);
|
|
|
Quad.FillSquare2(batch, 7, 5, Color.Yellow, .5f, 0.79f);
|
|
|
Quad.FillSquare2(batch, 7, 6, Color.Yellow, .25f, 0.79f);
|
|
|
Quad.FillSquare2(batch, 7, 7, Color.Yellow, .125f, 0.79f);
|
|
|
Quad.FillSquare2(batch, 8, 5, Color.Teal, .5f, 0.79f);
|
|
|
Quad.FillSquare2(batch, 8, 6, Color.Teal, .25f, 0.79f);
|
|
|
Quad.FillSquare2(batch, 8, 7, Color.Teal, .125f, 0.79f);
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
#endregion draw_cursor
|
|
|
|
|
|
|
|
|
#region draw_trees
|
|
|
if (this.showTrees) {
|
|
|
for (int i = 0; i < this.simulation.map.MapHeight; i++)
|
|
|
{
|
|
|
for (int j = 0; j < this.simulation.map.MapWidth; j += 1)
|
|
|
{
|
|
|
|
|
|
if (this.simulation.map.cells[i][j].hasTree)
|
|
|
{ //until we actually simulate:
|
|
|
drawTileAt(i, j, 142, 2);
|
|
|
// if ((i + j) % 8 == 0)
|
|
|
// {
|
|
|
// drawTileAt(i, j, 141, 2);
|
|
|
// }
|
|
|
// else
|
|
|
// {
|
|
|
// drawTileAt(i, j, 142, 2);
|
|
|
// }
|
|
|
}
|
|
|
else if (this.simulation.map.cells[i][j].status == CellStatus.DeadTree) {
|
|
|
drawTileAt(i, j, 141, 2);
|
|
|
// System.Console.WriteLine(String.Format("Drew Dead Tree at {0},{1}", i, j));
|
|
|
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
#endregion draw_trees
|
|
|
|
|
|
#if DEBUG
|
|
|
drawTileAt(2, 2, 140, 2);
|
|
|
drawTileAt(1, 1, 140, 2);
|
|
|
drawTileAt(3, 2, 140, 2);
|
|
|
#endif
|
|
|
|
|
|
_imGuiRenderer.BeforeLayout(gameTime);
|
|
|
World.Draw();
|
|
|
// _imGuiRenderer.AfterLayout();
|
|
|
batch.End();
|
|
|
|
|
|
#region draw_header
|
|
|
batch.Begin(SpriteSortMode.BackToFront,
|
|
|
BlendState.AlphaBlend,
|
|
|
null,
|
|
|
null,
|
|
|
null,
|
|
|
null);
|
|
|
|
|
|
bool has_tree = false;
|
|
|
if (MathUtils.BetweenExclusive(this.mouseGrid.X, 0, this.squaresAcross) && MathUtils.BetweenExclusive(this.mouseGrid.Y, 0, this.squaresAcross))
|
|
|
{
|
|
|
has_tree = this.simulation.map.cells[(int)this.mouseGrid.X][(int)this.mouseGrid.Y].hasTree;
|
|
|
}
|
|
|
//*/
|
|
|
|
|
|
String status_left = "";
|
|
|
if (MathUtils.BetweenExclusive(this.mouseGrid.X, -1, this.simulation.map.MapWidth) && MathUtils.BetweenExclusive(this.mouseGrid.Y, -1, this.simulation.map.MapHeight))
|
|
|
{
|
|
|
status_left = String.Format("{0:},{1:} {2} ({3})", this.mouseGrid.X, this.mouseGrid.Y,
|
|
|
this.simulation.map.cells[(int)this.mouseGrid.X][(int)this.mouseGrid.Y].status,
|
|
|
this.in_zone ? "Contracted" : "Unzoned"
|
|
|
);
|
|
|
}
|
|
|
|
|
|
String header_left = String.Format("${0:}|{1:} \ue124", this.simulation.money, this.simulation.map.tree_count);
|
|
|
String header_middle = String.Format("{0:MMMMM yyyy} ({1:})", this.simulation.DateTime, this.simulation.Season);
|
|
|
// String header_right = String.Format("Press H for help.");
|
|
|
String header_right = "";
|
|
|
|
|
|
this.Window.Title = String.Format("Isometric Park [{0:}]", header_middle);
|
|
|
Vector2 middle_dimensions = monoFont.MeasureString(header_middle);
|
|
|
Vector2 right_dimensions = monoFont.MeasureString(header_right);
|
|
|
|
|
|
float middle_start = (int)((FNAGame.width / 2) - (middle_dimensions.X / 2));
|
|
|
float right_start = (int)(FNAGame.width - right_dimensions.X - 10.0f);
|
|
|
float top = (float)Math.Round(FNAGame.height - middle_dimensions.Y); // Rounding so the int and float versions are closer.
|
|
|
|
|
|
|
|
|
FilledRectangle.drawFilledRectangle(batch, new Rectangle(0, (int)top, width, (int)middle_dimensions.Y), Color.White, 0.51f);
|
|
|
|
|
|
|
|
|
batch.DrawString(monoFont, status_left, new Vector2(1, top), Color.Black, 0.0f, Vector2.Zero, 1.0f, SpriteEffects.None, 0.5f);
|
|
|
batch.DrawString(monoFont, header_left, new Vector2(1, 1), Color.Black, 0.0f, Vector2.Zero, 1.0f, SpriteEffects.None, 0.5f);
|
|
|
batch.DrawString(monoFont, header_middle, new Vector2(middle_start, 1), Color.Black, 0.0f, Vector2.Zero, 1.0f, SpriteEffects.None, 0.5f);
|
|
|
// batch.DrawString(monoFont, header_right, new Vector2(right_start, 1), Color.Black, 0.0f, Vector2.Zero, 1.0f, SpriteEffects.None, 0.5f);
|
|
|
#endregion draw_header
|
|
|
|
|
|
|
|
|
#region budget
|
|
|
|
|
|
if (this.showBudget)
|
|
|
{
|
|
|
budgetWindow.draw(batch);
|
|
|
}
|
|
|
|
|
|
#endregion budget
|
|
|
|
|
|
batch.End();
|
|
|
|
|
|
|
|
|
#region debug_window
|
|
|
//Calcs for debug window:
|
|
|
if ((this.frameCounter % 15) == 0)
|
|
|
{
|
|
|
past_fps.Enqueue(this.frameRate);
|
|
|
|
|
|
/*
|
|
|
if (this.frameRate > 60.0)
|
|
|
{
|
|
|
Logging.Warning(String.Format("Framerate is higher than limit: {0}", this.frameRate));
|
|
|
}
|
|
|
if (this.frameRate < 30.0)
|
|
|
{
|
|
|
Logging.Warning(String.Format("Framerate is lower than desired: {0}", this.frameRate));
|
|
|
}*/
|
|
|
}
|
|
|
/*
|
|
|
if (this.frameRate > 120.0)
|
|
|
{
|
|
|
Logging.Error(String.Format("Framerate is much higher than limit: {0}", this.frameRate));
|
|
|
}
|
|
|
else if (this.frameRate < 15.0)
|
|
|
{
|
|
|
Logging.Error(String.Format("Framerate is much lower than desired: {0}", this.frameRate));
|
|
|
}
|
|
|
*/
|
|
|
|
|
|
DebugInfo debugInfo = new DebugInfo
|
|
|
{ fps = this.frameRate,
|
|
|
pastFps = past_fps.ToArray(),
|
|
|
cameraPosition = camera.position,
|
|
|
drawTime = this.drawTime,
|
|
|
updateTime = this.updateTime,
|
|
|
treeCount = this.simulation.map.tree_count,
|
|
|
mouseGrid = this.mouseGrid,
|
|
|
hasTree = has_tree,
|
|
|
tilesDrawn = this.tilesDrawn
|
|
|
};
|
|
|
|
|
|
//Finally, draw the debug window
|
|
|
// _imGuiRenderer.BeforeLayout(gameTime);
|
|
|
|
|
|
var additionalInfo = new Dictionary<string, string>();
|
|
|
|
|
|
Vector2 cameraMiddle = this.camera.position + new Vector2(FNAGame.width / 2, FNAGame.height / 2);
|
|
|
var state = Mouse.GetState();
|
|
|
Vector2 delta = this.camera.position - this.original_point;
|
|
|
|
|
|
additionalInfo.Add("cameraMiddle", cameraMiddle.ToString());
|
|
|
additionalInfo.Add("mouse ", String.Format("{0}, {1}", state.X, state.Y));
|
|
|
additionalInfo.Add("mouse delta", delta.ToString());
|
|
|
|
|
|
additionalInfo.Add("Tracery Test", this.output);
|
|
|
additionalInfo.Add("Log Entry", string.Format("{0} {1}", Logging.entries[Logging.entries.Count-1].level, Logging.entries[Logging.entries.Count-1].message));
|
|
|
|
|
|
debugWindow.Layout(debugInfo, additionalInfo, ref show_another_window);
|
|
|
|
|
|
|
|
|
//debugWindow.ImGuiLayout();
|
|
|
//String[] messages = { "Message1", "Message2" };
|
|
|
|
|
|
//DialogOption[] dialog = { new DialogOption{ response="Welcome to your new park, director! You can use the mouse or arrow keys to move around, and the plus and minus keys to zoom in and out.", choice="Okay" },
|
|
|
// new DialogOption{ response="Make sure that you keep visitors happy and the budget in the black! You're currently getting an annual grant out of my budget—it'd sure be nice if you park were self-sufficient so we could drop that expense!", choice="And I need to keep the forest healthy, too, right?" },
|
|
|
// new DialogOption{ response="Oh yeah, of course.", choice="..." }};
|
|
|
|
|
|
|
|
|
if (this.currentNode != null)
|
|
|
{
|
|
|
this.currentNode = DialogInterface.RenderDialog(ref this.showInitial,
|
|
|
ref this.simulation.paused, debugWindow.monoFont, this.currentNode);
|
|
|
}
|
|
|
|
|
|
if (this.showForest)
|
|
|
{
|
|
|
ForestWindow.Render(this.showForest, debugWindow.monoFont, this.simulation, this.imGuiWindowBridgeEngine);
|
|
|
}
|
|
|
|
|
|
if (this.showNews)
|
|
|
{
|
|
|
NewsWindow.Render(this.showNews, debugWindow.monoFont, this.simulation, this.imGuiWindowBridgeEngine);
|
|
|
}
|
|
|
|
|
|
bool quit = false;
|
|
|
Menu.Render(debugWindow.monoFont, FNAGame.width, this.imGuiWindowBridgeEngine, ref quit, ref this.simulation.paused, ref this.simulation.currentRate, ref this.showBudget, header_left);
|
|
|
|
|
|
if (quit) {
|
|
|
System.Environment.Exit(0);
|
|
|
}
|
|
|
|
|
|
|
|
|
_imGuiRenderer.AfterLayout();
|
|
|
|
|
|
#endregion debug_window
|
|
|
|
|
|
stopWatch.Stop();
|
|
|
this.drawTime = stopWatch.Elapsed;
|
|
|
|
|
|
base.Draw(gameTime);
|
|
|
}
|
|
|
}
|
|
|
|