1027 lines
42 KiB
C#
1027 lines
42 KiB
C#
using Microsoft.AspNetCore.SignalR.Client;
|
|
using Microsoft.Xna.Framework;
|
|
using Microsoft.Xna.Framework.Graphics;
|
|
using Microsoft.Xna.Framework.Input;
|
|
using Myra;
|
|
using Myra.Graphics2D.Brushes;
|
|
using Myra.Graphics2D.TextureAtlases;
|
|
using Myra.Graphics2D.UI;
|
|
using Myra.Graphics2D.UI.File;
|
|
using Newtonsoft.Json;
|
|
using System.Collections.Generic;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using System;
|
|
using System.Collections.Concurrent;
|
|
using Sledgemapper.Shared.Entities;
|
|
|
|
namespace Sledgemapper
|
|
{
|
|
public class Sledgemapper : Game
|
|
{
|
|
private GraphicsDeviceManager _graphics;
|
|
private SpriteBatch _spriteBatch;
|
|
private Tile _selectedTile = new Tile { X = 1, Y = 1 };
|
|
private Tile _hoveredTile = new Tile { X = 1, Y = 1 };
|
|
private Wall _selectedWall = new Wall { X = 1, Y = 1 };
|
|
private Overlay _selectedOverlay = new Overlay { X = 1, Y = 1 };
|
|
private int _tileSize = 30;
|
|
private HubConnection connection;
|
|
private readonly Desktop _desktop;
|
|
private string _currentTileId = "";
|
|
private string _currentWallId = "";
|
|
private string _currentOverlayId = "";
|
|
private InsertMode _insertMode;
|
|
private string _session;
|
|
private KeyboardState oldState;
|
|
private MouseState oldMouseState;
|
|
|
|
private Vector3 _viewportCenter = new Vector3(0, 0, 0);
|
|
private SpriteFont font;
|
|
private Dictionary<string, SpriteFont> _fonts;
|
|
private SessionData _sessionData;
|
|
|
|
public Sledgemapper()
|
|
{
|
|
_graphics = new GraphicsDeviceManager(this);
|
|
Content.RootDirectory = "Content";
|
|
_desktop = new Desktop();
|
|
MyraEnvironment.Game = this;
|
|
_sessionData = new SessionData();
|
|
IsFixedTimeStep = false;
|
|
}
|
|
|
|
protected override void Initialize()
|
|
{
|
|
// TODO: Add your initialization logic here
|
|
IsMouseVisible = true;
|
|
Window.AllowUserResizing = true;
|
|
Players = new List<Player>();
|
|
connection = new HubConnectionBuilder()
|
|
// .WithAutomaticReconnect()
|
|
|
|
.WithUrl("http://localhost:5000/SledgemapperHub")
|
|
|
|
// .WithUrl("http://hub.michelescandura.com:5000/SledgemapperHub")
|
|
.Build();
|
|
|
|
connection.On<SessionData>("UpdateMap", (map) =>
|
|
{
|
|
_sessionData.Map = map.Map;
|
|
_sessionData.Walls = map.Walls;
|
|
_sessionData.Overlays = map.Overlays;
|
|
|
|
});
|
|
|
|
connection.On<Player>("PlayerUpdate", (player) =>
|
|
{
|
|
var p = Players.FirstOrDefault(m => m.ConnectionId == player.ConnectionId);
|
|
if (p != null)
|
|
{
|
|
p.Position = player.Position;
|
|
}
|
|
});
|
|
|
|
connection.On<Tile>("DeleteTile", (tile) =>
|
|
{
|
|
_sessionData.Map.Remove(tile.ToString(), out var rtile);
|
|
});
|
|
|
|
connection.On<Wall>("DeleteWall", (tile) =>
|
|
{
|
|
_sessionData.Walls.Remove(tile.ToString(), out var rtile);
|
|
});
|
|
|
|
connection.On<Overlay>("DeleteOverlay", (tile) =>
|
|
{
|
|
_sessionData.Overlays.Remove(tile.ToString(), out var rtile);
|
|
});
|
|
|
|
connection.On<Tile>("NewTile", (tile) =>
|
|
{
|
|
_sessionData.Map.Remove(tile.ToString(), out var rtile);
|
|
_sessionData.Map.TryAdd(tile.ToString(), tile);
|
|
});
|
|
|
|
connection.On<Wall>("NewWall", (tile) =>
|
|
{
|
|
_sessionData.Walls.Remove(tile.ToString(), out var rtile);
|
|
_sessionData.Walls.TryAdd(tile.ToString(), tile);
|
|
});
|
|
|
|
connection.On<Overlay>("NewOverlay", (tile) =>
|
|
{
|
|
_sessionData.Overlays.Remove(tile.ToString(), out var rtile);
|
|
_sessionData.Overlays.TryAdd(tile.ToString(), tile);
|
|
});
|
|
|
|
|
|
connection.On<Player>("NewPlayer", (player) =>
|
|
{
|
|
var p = Players.FirstOrDefault(m => m.ConnectionId == player.ConnectionId);
|
|
if (p is null)
|
|
{
|
|
Players.Add(player);
|
|
}
|
|
else
|
|
{
|
|
p.Color = player.Color;
|
|
p.Position = player.Position;
|
|
}
|
|
});
|
|
|
|
base.Initialize();
|
|
}
|
|
|
|
public List<Player> Players { get; set; }
|
|
|
|
private HorizontalMenu BuildMenu()
|
|
{
|
|
var menu = new HorizontalMenu();
|
|
var menuFile = new MenuItem("_file", "File");
|
|
var menuFileLoad = new MenuItem("_file_load", "Load");
|
|
var menuFileSave = new MenuItem("_file_save", "Save");
|
|
var menuConnect = new MenuItem("_connect", "Connect");
|
|
var menuConnectNew = new MenuItem("_connect_new", "New");
|
|
var menuConnectJoin = new MenuItem("_connect_join", "Join");
|
|
var menuConnectSync = new MenuItem("_connect_sync", "Sync");
|
|
|
|
menuConnectSync.Selected += async (s, e) =>
|
|
{
|
|
await connection?.InvokeAsync("Sync", _session, _sessionData);
|
|
};
|
|
|
|
menuFileLoad.Selected += (s, e) =>
|
|
{
|
|
FileDialog dialog = new FileDialog(FileDialogMode.OpenFile)
|
|
{
|
|
Filter = "*.map"
|
|
//Folder = @"D:\Temp"
|
|
};
|
|
|
|
dialog.Closed += (s, a) =>
|
|
{
|
|
if (!dialog.Result)
|
|
{
|
|
// "Cancel" or Escape
|
|
return;
|
|
}
|
|
using (StreamReader file = File.OpenText(dialog.FilePath))
|
|
{
|
|
JsonSerializer serializer = new JsonSerializer();
|
|
_sessionData = (SessionData)serializer.Deserialize(file, typeof(SessionData));
|
|
}
|
|
// "Ok" or Enter
|
|
// ...
|
|
};
|
|
|
|
dialog.ShowModal(_desktop);
|
|
};
|
|
|
|
menuFileSave.Selected += (s, e) =>
|
|
{
|
|
FileDialog dialog = new FileDialog(FileDialogMode.SaveFile)
|
|
{
|
|
Filter = "*.map"
|
|
//Folder = @"D:\Temp"
|
|
};
|
|
|
|
dialog.Closed += (s, a) =>
|
|
{
|
|
if (!dialog.Result)
|
|
{
|
|
// "Cancel" or Escape
|
|
return;
|
|
}
|
|
|
|
using (StreamWriter file = File.CreateText(dialog.FilePath))
|
|
{
|
|
JsonSerializer serializer = new JsonSerializer();
|
|
serializer.Serialize(file, _sessionData);
|
|
}
|
|
// "Ok" or Enter
|
|
// ...
|
|
};
|
|
|
|
dialog.ShowModal(_desktop);
|
|
};
|
|
|
|
menuConnectNew.Selected += (s, e) =>
|
|
{
|
|
Window window = new Window
|
|
{
|
|
Title = "New mapping session"
|
|
};
|
|
var content = new VerticalStackPanel();
|
|
var grid = new Grid
|
|
{
|
|
Width = 200,
|
|
ShowGridLines = false,
|
|
ColumnSpacing = 8,
|
|
RowSpacing = 3,
|
|
};
|
|
|
|
// Set partitioning configuration
|
|
grid.ColumnsProportions.Add(new Proportion(ProportionType.Auto));
|
|
grid.ColumnsProportions.Add(new Proportion(ProportionType.Fill));
|
|
grid.RowsProportions.Add(new Proportion(ProportionType.Auto));
|
|
grid.RowsProportions.Add(new Proportion(ProportionType.Auto));
|
|
var sessionNameLabel = new Label { Text = "Session Name:" };
|
|
var initialsLabel = new Label { Text = "Initials:", GridRow = 1 };
|
|
var textbox = new TextBox { GridColumn = 1 };
|
|
var initialsTextbox = new TextBox { GridColumn = 1, GridRow = 1 };
|
|
TextButton button = new TextButton
|
|
{
|
|
Text = "Start",
|
|
HorizontalAlignment = HorizontalAlignment.Center
|
|
};
|
|
grid.Widgets.Add(textbox);
|
|
grid.Widgets.Add(initialsTextbox);
|
|
grid.Widgets.Add(sessionNameLabel);
|
|
grid.Widgets.Add(initialsLabel);
|
|
|
|
content.Widgets.Add(grid);
|
|
|
|
button.Click += async (s, e) =>
|
|
{
|
|
if (string.IsNullOrWhiteSpace(textbox.Text))
|
|
{
|
|
return;
|
|
}
|
|
if (connection.State != HubConnectionState.Connected)
|
|
{ await connection.StartAsync(); }
|
|
var successful = false;
|
|
try
|
|
{
|
|
var session = await connection?.InvokeAsync<SessionData>("NewSession", textbox.Text, initialsTextbox.Text);
|
|
if (session != null)
|
|
{
|
|
Players = session.Players;
|
|
|
|
}
|
|
successful = session != null;
|
|
}
|
|
catch (Exception ex)
|
|
|
|
{
|
|
|
|
}
|
|
if (successful)
|
|
{
|
|
_session = textbox.Text;
|
|
window.Close();
|
|
}
|
|
};
|
|
|
|
|
|
content.Widgets.Add(button);
|
|
window.Content = content;
|
|
|
|
window.Closed += (s, a) =>
|
|
{
|
|
// Called when window is closed
|
|
};
|
|
|
|
window.ShowModal(_desktop);
|
|
};
|
|
|
|
menuConnectJoin.Selected += (s, e) =>
|
|
{
|
|
Window window = new Window
|
|
{
|
|
Title = "Join mapping session"
|
|
};
|
|
var content = new VerticalStackPanel();
|
|
var grid = new Grid
|
|
{
|
|
Width = 200,
|
|
ShowGridLines = false,
|
|
ColumnSpacing = 8,
|
|
RowSpacing = 3,
|
|
};
|
|
|
|
// Set partitioning configuration
|
|
grid.ColumnsProportions.Add(new Proportion(ProportionType.Auto));
|
|
grid.ColumnsProportions.Add(new Proportion(ProportionType.Fill));
|
|
grid.RowsProportions.Add(new Proportion(ProportionType.Auto));
|
|
grid.RowsProportions.Add(new Proportion(ProportionType.Auto));
|
|
var sessionNameLabel = new Label { Text = "Session Name:" };
|
|
var initialsLabel = new Label { Text = "Initials:", GridRow = 1 };
|
|
var textbox = new TextBox { GridColumn = 1 };
|
|
var initialsTextbox = new TextBox { GridColumn = 1, GridRow = 1 };
|
|
TextButton button = new TextButton
|
|
{
|
|
Text = "Start",
|
|
HorizontalAlignment = HorizontalAlignment.Center
|
|
};
|
|
grid.Widgets.Add(textbox);
|
|
grid.Widgets.Add(initialsTextbox);
|
|
grid.Widgets.Add(sessionNameLabel);
|
|
grid.Widgets.Add(initialsLabel);
|
|
|
|
content.Widgets.Add(grid);
|
|
|
|
// var content = new VerticalStackPanel();
|
|
// var textbox = new TextBox();
|
|
// TextButton button = new TextButton
|
|
// {
|
|
// Text = "Start",
|
|
// HorizontalAlignment = HorizontalAlignment.Center
|
|
// };
|
|
button.Click += async (s, e) =>
|
|
{
|
|
if (string.IsNullOrWhiteSpace(textbox.Text))
|
|
{
|
|
return;
|
|
}
|
|
if (connection.State != HubConnectionState.Connected)
|
|
{ await connection.StartAsync(); }
|
|
var successful = false;
|
|
try
|
|
{
|
|
var result = await connection?.InvokeAsync<SessionData>("JoinSession", textbox.Text, initialsTextbox.Text);
|
|
if (result != null)
|
|
{
|
|
_sessionData.Map = result.Map;
|
|
_sessionData.Walls = result.Walls;
|
|
_sessionData.Overlays = result.Overlays;
|
|
Players = result.Players;
|
|
}
|
|
successful = result != null; ;
|
|
}
|
|
catch { }
|
|
if (successful)
|
|
{
|
|
_session = textbox.Text;
|
|
window.Close();
|
|
}
|
|
};
|
|
//content.Widgets.Add(textbox);
|
|
content.Widgets.Add(button);
|
|
window.Content = content;
|
|
|
|
window.Closed += (s, a) =>
|
|
{
|
|
// Called when window is closed
|
|
};
|
|
|
|
window.ShowModal(_desktop);
|
|
};
|
|
|
|
menuConnect.Items.Add(menuConnectNew);
|
|
menuConnect.Items.Add(menuConnectJoin);
|
|
menuConnect.Items.Add(menuConnectSync);
|
|
menu.Items.Add(menuConnect);
|
|
menuFile.Items.Add(menuFileLoad);
|
|
menuFile.Items.Add(menuFileSave);
|
|
menu.Items.Add(menuFile);
|
|
menu.Items.Add(menuConnect);
|
|
|
|
return menu;
|
|
}
|
|
|
|
protected override void LoadContent()
|
|
{
|
|
_spriteBatch = new SpriteBatch(GraphicsDevice);
|
|
MyraEnvironment.Game = this;
|
|
|
|
var mainPanel = new VerticalStackPanel();
|
|
|
|
var menu = BuildMenu();
|
|
mainPanel.Widgets.Add(menu);
|
|
|
|
var sidePanel = new VerticalStackPanel { Layout2d = new Myra.Graphics2D.UI.Properties.Layout2D("this.w=200;this.h=W.h"), Background = new SolidBrush(Color.DarkGray) };
|
|
|
|
var tileScrollView = new ScrollViewer { Layout2d = new Myra.Graphics2D.UI.Properties.Layout2D("this.w=200;this.h=W.h/3") };
|
|
var tileGrid = new Grid { ColumnSpacing = 3, RowSpacing = 3, Layout2d = new Myra.Graphics2D.UI.Properties.Layout2D("this.w=200"), Background = new SolidBrush(Color.DarkGray) };
|
|
tileScrollView.Content = tileGrid;
|
|
sidePanel.Widgets.Add(tileScrollView);
|
|
|
|
var wallScrollView = new ScrollViewer { Layout2d = new Myra.Graphics2D.UI.Properties.Layout2D("this.w=200;this.h=W.h/3") };
|
|
var wallGrid = new Grid { ColumnSpacing = 3, RowSpacing = 3, Layout2d = new Myra.Graphics2D.UI.Properties.Layout2D("this.w=200"), Background = new SolidBrush(Color.DarkGray) };
|
|
wallScrollView.Content = wallGrid;
|
|
sidePanel.Widgets.Add(wallScrollView);
|
|
|
|
var overlayScrollView = new ScrollViewer { Layout2d = new Myra.Graphics2D.UI.Properties.Layout2D("this.w=200;this.h=W.h/3") };
|
|
var overlayGrid = new Grid { ColumnSpacing = 3, RowSpacing = 3, Layout2d = new Myra.Graphics2D.UI.Properties.Layout2D("this.w=200"), Background = new SolidBrush(Color.DarkGray) };
|
|
overlayScrollView.Content = overlayGrid;
|
|
sidePanel.Widgets.Add(overlayScrollView);
|
|
|
|
mainPanel.Widgets.Add(sidePanel);
|
|
|
|
var tilesFolderContent = Content.LoadContentFolder<Texture2D>("tiles");
|
|
var indexX = 0;
|
|
var indexY = 0;
|
|
|
|
foreach (var item in tilesFolderContent)
|
|
{
|
|
var tileButton = new ImageButton { Image = new TextureRegion(item.Value), GridColumn = indexY, GridRow = indexX, Id = item.Key, Width = 40, Height = 40 };
|
|
tileButton.Click += (s, e) =>
|
|
{
|
|
_currentTileId = ((ImageButton)s).Id;
|
|
|
|
ClearSelection(wallGrid);
|
|
ClearSelection(tileGrid);
|
|
ClearSelection(overlayGrid);
|
|
|
|
((ImageButton)s).Border = new SolidBrush(Color.Red);
|
|
((ImageButton)s).BorderThickness = new Myra.Graphics2D.Thickness(2);
|
|
_insertMode = InsertMode.Tile;
|
|
};
|
|
tileGrid.Widgets.Add(tileButton);
|
|
indexY++;
|
|
if (indexY == 4)
|
|
{
|
|
indexY = 0;
|
|
indexX++;
|
|
}
|
|
}
|
|
|
|
var wallsFolderContent = Content.LoadContentFolder<Texture2D>("walls");
|
|
indexX = 0;
|
|
indexY = 0;
|
|
|
|
foreach (var item in wallsFolderContent)
|
|
{
|
|
var wallButton = new ImageButton { Image = new TextureRegion(item.Value), GridColumn = indexY, GridRow = indexX, Id = item.Key, Width = 40, Height = 40 };
|
|
wallButton.Click += (s, e) =>
|
|
{
|
|
_currentWallId = ((ImageButton)s).Id;
|
|
ClearSelection(wallGrid);
|
|
ClearSelection(tileGrid);
|
|
ClearSelection(overlayGrid);
|
|
|
|
|
|
((ImageButton)s).Border = new SolidBrush(Color.Red);
|
|
((ImageButton)s).BorderThickness = new Myra.Graphics2D.Thickness(2);
|
|
_insertMode = InsertMode.Wall;
|
|
|
|
};
|
|
wallGrid.Widgets.Add(wallButton);
|
|
indexY++;
|
|
if (indexY == 4)
|
|
{
|
|
indexY = 0;
|
|
indexX++;
|
|
}
|
|
}
|
|
|
|
var overlayFolderContent = Content.LoadContentFolder<Texture2D>("overlays");
|
|
indexX = 0;
|
|
indexY = 0;
|
|
|
|
foreach (var item in overlayFolderContent)
|
|
{
|
|
var overlayButton = new ImageButton { Image = new TextureRegion(item.Value), GridColumn = indexY, GridRow = indexX, Id = item.Key, Width = 40, Height = 40 };
|
|
overlayButton.Click += (s, e) =>
|
|
{
|
|
_currentOverlayId = ((ImageButton)s).Id;
|
|
ClearSelection(wallGrid);
|
|
ClearSelection(tileGrid);
|
|
ClearSelection(overlayGrid);
|
|
|
|
|
|
((ImageButton)s).Border = new SolidBrush(Color.Red);
|
|
((ImageButton)s).BorderThickness = new Myra.Graphics2D.Thickness(2);
|
|
_insertMode = InsertMode.Overlay;
|
|
|
|
};
|
|
overlayGrid.Widgets.Add(overlayButton);
|
|
indexY++;
|
|
if (indexY == 4)
|
|
{
|
|
indexY = 0;
|
|
indexX++;
|
|
}
|
|
}
|
|
|
|
_fonts = Content.LoadContentFolder<SpriteFont>("fonts");
|
|
|
|
|
|
// Add it to the desktop
|
|
// _desktop = new Desktop();
|
|
_desktop.Root = mainPanel;
|
|
// TODO: use this.Content to load your game content here
|
|
}
|
|
bool _draw;
|
|
protected override void Update(GameTime gameTime)
|
|
{
|
|
// if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed || Keyboard.GetState().IsKeyDown(Keys.Escape))
|
|
// Exit();
|
|
KeyboardState newState = Keyboard.GetState();
|
|
// TODO: Add your update logic here
|
|
if (IsActive && GraphicsDevice.Viewport.Bounds.Contains(Mouse.GetState().Position) && !_desktop.IsMouseOverGUI && !_desktop.HasModalWidget)
|
|
{
|
|
var mouseState = Mouse.GetState();
|
|
|
|
var screenPosition = new Point((mouseState.Position.X - (int)_viewportCenter.X), (mouseState.Position.Y - (int)_viewportCenter.Y));
|
|
|
|
_hoveredTile.X = screenPosition.X / _tileSize;
|
|
_hoveredTile.Y = screenPosition.Y / _tileSize;
|
|
if (screenPosition.X < 0)
|
|
{
|
|
_hoveredTile.X--;
|
|
}
|
|
|
|
if (screenPosition.Y < 0)
|
|
{
|
|
_hoveredTile.Y--;
|
|
}
|
|
|
|
if (_insertMode == InsertMode.Wall)
|
|
{
|
|
SelectClosestWall(screenPosition);
|
|
}
|
|
|
|
if (_insertMode == InsertMode.Overlay)
|
|
{
|
|
SelectOverlay(screenPosition);
|
|
}
|
|
|
|
if (mouseState.LeftButton == ButtonState.Pressed && mouseState.LeftButton != oldMouseState.LeftButton)
|
|
{
|
|
_selectedTile.X = _hoveredTile.X;
|
|
_selectedTile.Y = _hoveredTile.Y;
|
|
connection?.SendAsync("UpdatePosition", _session, _selectedTile);
|
|
}
|
|
|
|
if (newState.IsKeyDown(Keys.LeftControl)
|
|
&& mouseState.LeftButton == ButtonState.Pressed
|
|
&& ((mouseState.LeftButton != oldMouseState.LeftButton) || (_selectedTile.X != _hoveredTile.X && _selectedTile.Y != _hoveredTile.Y)))
|
|
{
|
|
switch (_insertMode)
|
|
{
|
|
case InsertMode.Tile:
|
|
_selectedTile.X = _hoveredTile.X;
|
|
_selectedTile.Y = _hoveredTile.Y;
|
|
connection?.SendAsync("UpdatePosition", _session, _selectedTile);
|
|
|
|
SetTile(_currentTileId);
|
|
break;
|
|
|
|
case InsertMode.Wall:
|
|
|
|
SetWall(_currentWallId);
|
|
break;
|
|
case InsertMode.Overlay:
|
|
SetOverlay(_currentOverlayId);
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (!newState.IsKeyDown(Keys.LeftControl) && mouseState.LeftButton == ButtonState.Pressed && mouseState.LeftButton == oldMouseState.LeftButton)
|
|
{
|
|
_viewportCenter = new Vector3(_viewportCenter.X + mouseState.Position.X - oldMouseState.Position.X, _viewportCenter.Y + mouseState.Position.Y - oldMouseState.Position.Y, 0);
|
|
}
|
|
|
|
if (newState.IsKeyDown(Keys.LeftControl) && mouseState.ScrollWheelValue != oldMouseState.ScrollWheelValue)
|
|
{
|
|
if (mouseState.ScrollWheelValue > oldMouseState.ScrollWheelValue)
|
|
{
|
|
_tileSize = System.Math.Min(120, _tileSize + 10);
|
|
|
|
}
|
|
else if (mouseState.ScrollWheelValue < oldMouseState.ScrollWheelValue)
|
|
{
|
|
_tileSize = System.Math.Max(10, _tileSize - 10);
|
|
}
|
|
}
|
|
|
|
oldMouseState = mouseState;
|
|
}
|
|
|
|
|
|
if (newState.IsKeyDown(Keys.Delete))
|
|
{
|
|
switch (_insertMode)
|
|
{
|
|
case InsertMode.Tile:
|
|
_selectedTile.X = _hoveredTile.X;
|
|
_selectedTile.Y = _hoveredTile.Y;
|
|
DeleteTile();
|
|
break;
|
|
|
|
case InsertMode.Wall:
|
|
|
|
DeleteWall();
|
|
break;
|
|
|
|
case InsertMode.Overlay:
|
|
|
|
DeleteOverlay();
|
|
break;
|
|
}
|
|
|
|
}
|
|
|
|
foreach (var key in newState.GetPressedKeys())
|
|
{
|
|
|
|
switch (key)
|
|
{
|
|
case Keys.Left:
|
|
if (oldState.IsKeyUp(Keys.Left) && newState.IsKeyDown(Keys.Left))
|
|
{ _selectedTile.X--; }
|
|
break;
|
|
case Keys.Right:
|
|
if (oldState.IsKeyUp(Keys.Right) && newState.IsKeyDown(Keys.Right))
|
|
{ _selectedTile.X++; }
|
|
break;
|
|
case Keys.Up:
|
|
if (oldState.IsKeyUp(Keys.Up) && newState.IsKeyDown(Keys.Up))
|
|
{ _selectedTile.Y--; }
|
|
break;
|
|
case Keys.Down:
|
|
if (oldState.IsKeyUp(Keys.Down) && newState.IsKeyDown(Keys.Down))
|
|
{ _selectedTile.Y++; }
|
|
break;
|
|
}
|
|
connection?.SendAsync("UpdatePosition", _session, _selectedTile);
|
|
|
|
}
|
|
|
|
oldState = newState;
|
|
|
|
base.Update(gameTime);
|
|
}
|
|
|
|
protected override void Draw(GameTime gameTime)
|
|
{
|
|
if (_spriteBatch is null)
|
|
{
|
|
return;
|
|
}
|
|
GraphicsDevice.Clear(Color.DarkGray);
|
|
var sessionData = _sessionData;
|
|
|
|
// TODO: Add your drawing code here
|
|
var visibleTilesX = GraphicsDevice.Viewport.Width / _tileSize + 1;
|
|
var visibleTilesY = GraphicsDevice.Viewport.Height / _tileSize + 1;
|
|
|
|
_spriteBatch.Begin(transformMatrix: Matrix.CreateTranslation(_viewportCenter));
|
|
|
|
for (var i = -1; i < visibleTilesX + 2; i++)
|
|
{
|
|
var posX1 = i * _tileSize - _viewportCenter.X;
|
|
var posY1 = -_viewportCenter.Y;
|
|
posX1 = posX1 - posX1 % _tileSize;
|
|
posY1 = posY1 - posY1 % _tileSize;
|
|
var posX2 = i * _tileSize - _viewportCenter.X;
|
|
var posY2 = GraphicsDevice.Viewport.Height - _viewportCenter.Y;
|
|
posX2 = posX2 - posX2 % _tileSize;
|
|
posY2 = posY2 - posY2 % _tileSize;
|
|
|
|
_spriteBatch.DrawLine(
|
|
posX1, posY1,
|
|
posX2,
|
|
posY2,
|
|
Color.Black);
|
|
}
|
|
|
|
for (var i = -1; i < visibleTilesY + 2; i++)
|
|
{
|
|
var posX1 = -_viewportCenter.X;
|
|
var posY1 = i * _tileSize - _viewportCenter.Y;
|
|
posX1 = posX1 - posX1 % _tileSize;
|
|
posY1 = posY1 - posY1 % _tileSize;
|
|
var posX2 = GraphicsDevice.Viewport.Width - _viewportCenter.X;
|
|
var posY2 = i * _tileSize - _viewportCenter.Y;
|
|
posX2 = posX2 - posX2 % _tileSize;
|
|
posY2 = posY2 - posY2 % _tileSize;
|
|
|
|
_spriteBatch.DrawLine(posX1, posY1,
|
|
posX2,
|
|
posY2,
|
|
Color.Black);
|
|
}
|
|
|
|
foreach (var tile in sessionData.Map.Values)
|
|
{
|
|
|
|
var content = Content.Load<Texture2D>($"tiles/{tile.ID}");
|
|
var destinationRectangle = new Rectangle(tile.X * _tileSize, tile.Y * _tileSize, _tileSize, _tileSize);
|
|
|
|
var posX = tile.X * _tileSize + _tileSize / 2f;
|
|
var posY = tile.Y * _tileSize + _tileSize / 2f;
|
|
|
|
_spriteBatch.Draw(content, new Vector2(posX, posY),
|
|
null, Color.White, MathHelper.ToRadians(90 * tile.Rotation), new Vector2(content.Width / 2, content.Height / 2), ((float)_tileSize - 1) / content.Width, SpriteEffects.None, 0);
|
|
}
|
|
|
|
foreach (var wall in sessionData.Walls.Values)
|
|
{
|
|
|
|
var content = Content.Load<Texture2D>($"walls/{wall.ID}");
|
|
var scale = _tileSize / (float)content.Height;
|
|
var offset = scale * content.Width / 2f;
|
|
var posX = wall.X * _tileSize;
|
|
var posY = wall.Y * _tileSize;
|
|
if (wall.Rotation == 1)
|
|
{
|
|
posX -= (int)offset;
|
|
}
|
|
else if (wall.Rotation == 0)
|
|
{
|
|
posY += (int)offset;
|
|
}
|
|
// _spriteBatch.Draw(content, new Vector2(posX, posY),null, Color.White, MathHelper.ToRadians(90 * (wall.Rotation - 1)), new Vector2(offset, 0), scale, SpriteEffects.None, 0);
|
|
_spriteBatch.Draw(content, new Vector2(posX, posY), null, Color.White, MathHelper.ToRadians(90 * (wall.Rotation - 1)), new Vector2(0, 0), scale, SpriteEffects.None, 0);
|
|
|
|
|
|
}
|
|
|
|
foreach (var tile in sessionData.Overlays.Values)
|
|
{
|
|
|
|
var content = Content.Load<Texture2D>($"overlays/{tile.ID}");
|
|
// System.Console.WriteLine(tile.Rotation);
|
|
if (tile.Intersection)
|
|
{
|
|
var posX = tile.X * _tileSize;
|
|
var posY = tile.Y * _tileSize;
|
|
|
|
_spriteBatch.Draw(content, new Vector2(posX, posY),
|
|
null, new Color(24, 118, 157), MathHelper.ToRadians(90 * tile.Rotation), new Vector2(content.Width / 2, content.Height / 2), ((float)_tileSize - 10) / content.Width, SpriteEffects.None, 0);
|
|
|
|
}
|
|
else
|
|
{
|
|
var posX = tile.X * _tileSize + _tileSize / 2f;
|
|
var posY = tile.Y * _tileSize + _tileSize / 2f;
|
|
|
|
_spriteBatch.Draw(content, new Vector2(posX, posY),
|
|
null, new Color(24, 118, 157), MathHelper.ToRadians(90 * tile.Rotation), new Vector2(content.Width / 2, content.Height / 2), ((float)_tileSize - 10) / content.Width, SpriteEffects.None, 0);
|
|
}
|
|
}
|
|
|
|
if (string.IsNullOrWhiteSpace(_session))
|
|
{
|
|
_spriteBatch.DrawRectangle(new Rectangle(_selectedTile.X * _tileSize, _selectedTile.Y * _tileSize, _tileSize - 1, _tileSize - 1), Color.Red, 2);
|
|
}
|
|
|
|
foreach (var player in Players.Copy<List<Player>>())
|
|
{
|
|
|
|
var hexs = player.Color.Split(2).ToArray();
|
|
var color = new Color(int.Parse(hexs[0], System.Globalization.NumberStyles.HexNumber),
|
|
int.Parse(hexs[1], System.Globalization.NumberStyles.HexNumber),
|
|
int.Parse(hexs[2], System.Globalization.NumberStyles.HexNumber));
|
|
_spriteBatch.DrawRectangle(new Rectangle(player.Position.X * _tileSize, player.Position.Y * _tileSize, _tileSize - 1, _tileSize - 1), color, 2);
|
|
|
|
var ffont = _fonts.FirstOrDefault(m => int.Parse(m.Key.Replace("font", "")) > _tileSize).Value ?? _fonts.Last().Value;
|
|
|
|
var fscale = (float)_tileSize / ((float)ffont.LineSpacing * 2);
|
|
_spriteBatch.DrawString(ffont,
|
|
player.Initials,
|
|
new Vector2(player.Position.X * _tileSize + 2, player.Position.Y * _tileSize + _tileSize - 2 - ffont.LineSpacing * fscale),
|
|
color,
|
|
0,
|
|
Vector2.Zero,
|
|
fscale,
|
|
SpriteEffects.None,
|
|
0);
|
|
}
|
|
|
|
var startWall = new Vector2(_selectedWall.X * _tileSize, _selectedWall.Y * _tileSize);
|
|
if (_insertMode == InsertMode.Wall)
|
|
{
|
|
_spriteBatch.DrawLine(startWall, _tileSize, MathHelper.ToRadians(90 * _selectedWall.Rotation), Color.Red, 2);
|
|
}
|
|
var overlay = new Vector2(_selectedOverlay.X * _tileSize, _selectedOverlay.Y * _tileSize);
|
|
if (_insertMode == InsertMode.Overlay)
|
|
{
|
|
if (_selectedOverlay.Intersection)
|
|
{
|
|
_spriteBatch.DrawCircle(overlay, _tileSize / 3, 100, Color.Red, 2);
|
|
}
|
|
}
|
|
|
|
_spriteBatch.End();
|
|
|
|
_desktop?.Render();
|
|
base.Draw(gameTime);
|
|
}
|
|
|
|
private void ClearSelection(Grid grid)
|
|
{
|
|
foreach (var widget in grid.Widgets)
|
|
{
|
|
widget.Border = null;
|
|
}
|
|
}
|
|
|
|
private float Sign(Point p1, Point p2, Point p3) { return (p1.X - p3.X) * (p2.Y - p3.Y) - (p2.X - p3.X) * (p1.Y - p3.Y); }
|
|
|
|
private bool PointInTri(Point pt, Point v1, Point v2, Point v3)
|
|
{
|
|
bool b1, b2, b3;
|
|
b1 = Sign(pt, v1, v2) < 0.0f;
|
|
b2 = Sign(pt, v2, v3) < 0.0f;
|
|
b3 = Sign(pt, v3, v1) < 0.0f;
|
|
return ((b1 == b2) && (b2 == b3));
|
|
}
|
|
|
|
private void SelectClosestWall(Point mousePosition)
|
|
{
|
|
var topLeft = new Point(_hoveredTile.X * _tileSize, _hoveredTile.Y * _tileSize);
|
|
var bottomLeft = new Point(_hoveredTile.X * _tileSize, _hoveredTile.Y * _tileSize + _tileSize);
|
|
var topRight = new Point(_hoveredTile.X * _tileSize + _tileSize, _hoveredTile.Y * _tileSize);
|
|
var bottomRight = new Point(_hoveredTile.X * _tileSize + _tileSize, _hoveredTile.Y * _tileSize + _tileSize);
|
|
var center = new Point(_hoveredTile.X * _tileSize + _tileSize / 2, _hoveredTile.Y * _tileSize + _tileSize / 2);
|
|
var leftWall = PointInTri(mousePosition, topLeft, center, bottomLeft);
|
|
var rightWall = PointInTri(mousePosition, topRight, bottomRight, center);
|
|
var topWall = PointInTri(mousePosition, topLeft, topRight, center);
|
|
var bottomtWall = PointInTri(mousePosition, bottomLeft, center, bottomRight);
|
|
|
|
if (leftWall)
|
|
{
|
|
_selectedWall.X = _hoveredTile.X;
|
|
_selectedWall.Y = _hoveredTile.Y;
|
|
_selectedWall.Rotation = 1;
|
|
}
|
|
else if (rightWall)
|
|
{
|
|
_selectedWall.X = _hoveredTile.X + 1;
|
|
_selectedWall.Y = _hoveredTile.Y;
|
|
_selectedWall.Rotation = 1;
|
|
}
|
|
else if (topWall)
|
|
{
|
|
_selectedWall.X = _hoveredTile.X;
|
|
_selectedWall.Y = _hoveredTile.Y;
|
|
_selectedWall.Rotation = 0;
|
|
}
|
|
else if (bottomtWall)
|
|
{
|
|
_selectedWall.X = _hoveredTile.X;
|
|
_selectedWall.Y = _hoveredTile.Y + 1;
|
|
_selectedWall.Rotation = 0;
|
|
}
|
|
}
|
|
|
|
private void SelectOverlay(Point mousePosition)
|
|
{
|
|
_selectedOverlay.X = _hoveredTile.X;
|
|
_selectedOverlay.Y = _hoveredTile.Y;
|
|
var q1 = System.Math.Pow(mousePosition.X - _hoveredTile.X * _tileSize, 2);
|
|
var q2 = System.Math.Pow((_hoveredTile.Y * _tileSize - mousePosition.Y), 2);
|
|
var s = System.Math.Sqrt(q1 + q2);
|
|
|
|
if (s < _tileSize / 3)
|
|
{
|
|
_selectedOverlay.Intersection = true;
|
|
return;
|
|
}
|
|
|
|
q1 = System.Math.Pow(mousePosition.X - (_hoveredTile.X + 1) * _tileSize, 2);
|
|
// var q2 = System.Math.Pow((_hoveredTile.Y * _tileSize - mousePosition.Y), 2);
|
|
s = System.Math.Sqrt(q1 + q2);
|
|
if (s < _tileSize / 3)
|
|
{
|
|
_selectedOverlay.X = _selectedOverlay.X + 1;
|
|
_selectedOverlay.Intersection = true;
|
|
return;
|
|
}
|
|
|
|
//q1 = System.Math.Pow(mousePosition.X - (_hoveredTile.X + 1) * _tileSize, 2);
|
|
q2 = System.Math.Pow(((_hoveredTile.Y + 1) * _tileSize - mousePosition.Y), 2);
|
|
s = System.Math.Sqrt(q1 + q2);
|
|
if (s < _tileSize / 3)
|
|
{
|
|
_selectedOverlay.X = _selectedOverlay.X + 1;
|
|
_selectedOverlay.Y = _selectedOverlay.Y + 1;
|
|
_selectedOverlay.Intersection = true;
|
|
return;
|
|
}
|
|
|
|
q1 = System.Math.Pow(mousePosition.X - _hoveredTile.X * _tileSize, 2);
|
|
q2 = System.Math.Pow(((_hoveredTile.Y + 1) * _tileSize - mousePosition.Y), 2);
|
|
s = System.Math.Sqrt(q1 + q2);
|
|
if (s < _tileSize / 3)
|
|
{
|
|
_selectedOverlay.X = _selectedOverlay.X;
|
|
_selectedOverlay.Y = _selectedOverlay.Y + 1;
|
|
_selectedOverlay.Intersection = true;
|
|
return;
|
|
}
|
|
|
|
_selectedOverlay.Intersection = false;
|
|
}
|
|
|
|
private void SetTile(string tileId)
|
|
{
|
|
var tileExist = _sessionData.Map.TryGetValue(_selectedTile.ToString(), out var rtile);
|
|
if (tileExist)
|
|
{
|
|
var get = _sessionData.Map.TryGetValue(_selectedTile.ToString(), out var tile);
|
|
|
|
_sessionData.Map.TryRemove(tile.ToString(), out var rrtile);
|
|
if (tile.ID == tileId)
|
|
{
|
|
var newTile = new Tile { X = _selectedTile.X, Y = _selectedTile.Y, ID = tileId, Rotation = (tile.Rotation + 1) % 4 };
|
|
_sessionData.Map.TryAdd(newTile.ToString(), newTile);
|
|
connection?.InvokeAsync("NewTile", _session, newTile);
|
|
}
|
|
else
|
|
{
|
|
var newTile = new Tile { X = _selectedTile.X, Y = _selectedTile.Y, ID = tileId };
|
|
_sessionData.Map.TryAdd(newTile.ToString(), newTile);
|
|
connection?.InvokeAsync("NewTile", _session, newTile);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
var newTile = new Tile { X = _selectedTile.X, Y = _selectedTile.Y, ID = tileId };
|
|
_sessionData.Map.TryAdd(newTile.ToString(), newTile);
|
|
connection?.InvokeAsync("NewTile", _session, newTile);
|
|
}
|
|
}
|
|
|
|
private void SetOverlay(string tileId)
|
|
{
|
|
var overlayExist = _sessionData.Overlays.TryGetValue(_selectedOverlay.ToString(), out var tile);
|
|
if (overlayExist)
|
|
{
|
|
var exist = _sessionData.Overlays.TryGetValue(_selectedOverlay.ToString(), out var overlay);
|
|
_sessionData.Overlays.TryRemove(tile.ToString(), out var rrtile);
|
|
if (overlay.ID == tileId)
|
|
{
|
|
var newOverlay = new Overlay { X = overlay.X, Y = overlay.Y, ID = tileId, Intersection = overlay.Intersection, Rotation = (overlay.Rotation + 1) % 4 };
|
|
_sessionData.Overlays.TryAdd(newOverlay.ToString(), newOverlay);
|
|
connection?.InvokeAsync("NewOverlay", _session, newOverlay);
|
|
}
|
|
else
|
|
{
|
|
var newOverlay = new Overlay { X = _selectedOverlay.X, Y = _selectedOverlay.Y, ID = tileId, Intersection = _selectedOverlay.Intersection };
|
|
_sessionData.Overlays.TryAdd(newOverlay.ToString(), newOverlay);
|
|
connection?.InvokeAsync("NewOverlay", _session, newOverlay);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
var newOverlay = new Overlay { X = _selectedOverlay.X, Y = _selectedOverlay.Y, ID = tileId, Intersection = _selectedOverlay.Intersection };
|
|
_sessionData.Overlays.TryAdd(newOverlay.ToString(), newOverlay);
|
|
connection?.InvokeAsync("NewOverlay", _session, newOverlay);
|
|
}
|
|
}
|
|
|
|
private void DeleteWall()
|
|
{
|
|
var tileExist = _sessionData.Walls.TryGetValue(_selectedWall.ToString(), out var wall);
|
|
if (tileExist)
|
|
{
|
|
//var wall = _sessionData.Walls.First(m => m.X == _selectedWall.X && m.Y == _selectedWall.Y && m.Rotation == _selectedWall.Rotation);
|
|
//var index = _sessionData.Walls.IndexOf(wall);
|
|
_sessionData.Walls.TryRemove(wall.ToString(), out var rwall);
|
|
connection?.InvokeAsync("DeleteWall", _session, wall);
|
|
}
|
|
}
|
|
|
|
private void DeleteOverlay()
|
|
{
|
|
var tileExist = _sessionData.Overlays.TryGetValue(_selectedOverlay.ToString(), out var overlay);
|
|
if (tileExist)
|
|
{
|
|
//var wall = _sessionData.Overlays.First(m => m.X == _selectedOverlay.X && m.Y == _selectedOverlay.Y && m.Intersection == _selectedOverlay.Intersection);
|
|
//var index = _sessionData.Overlays.IndexOf(wall);
|
|
_sessionData.Overlays.TryRemove(overlay.ToString(), out var roverlay);
|
|
connection?.InvokeAsync("DeleteOverlay", _session, overlay);
|
|
}
|
|
}
|
|
|
|
private void DeleteTile()
|
|
{
|
|
var tileExist = _sessionData.Map.TryGetValue(_selectedTile.ToString(), out var tile);
|
|
if (tileExist)
|
|
{
|
|
// var tile = _sessionData.Map.First(m => m.X == _selectedTile.X && m.Y == _selectedTile.Y);
|
|
// var index = _sessionData.Map.IndexOf(tile);
|
|
_sessionData.Map.TryRemove(tile.ToString(), out var rtile);
|
|
connection?.InvokeAsync("DeleteTile", _session, tile);
|
|
}
|
|
}
|
|
|
|
private void SetWall(string wallId)
|
|
{
|
|
var tileExist = _sessionData.Walls.TryGetValue(_selectedWall.ToString(), out var wall);
|
|
if (tileExist)
|
|
{
|
|
// var wall = _sessionData.Walls.First(m => m.X == _selectedWall.X && m.Y == _selectedWall.Y && m.Rotation == _selectedWall.Rotation);
|
|
// var index = _sessionData.Walls.IndexOf(wall);
|
|
_sessionData.Walls.TryRemove(wall.ToString(), out var rwall);
|
|
var newWall = new Wall { X = _selectedWall.X, Y = _selectedWall.Y, ID = wallId, Rotation = _selectedWall.Rotation };
|
|
_sessionData.Walls.TryAdd(newWall.ToString(), newWall);
|
|
connection?.InvokeAsync("NewWall", _session, newWall);
|
|
|
|
}
|
|
else
|
|
{
|
|
var newWall = new Wall { X = _selectedWall.X, Y = _selectedWall.Y, ID = wallId, Rotation = _selectedWall.Rotation };
|
|
_sessionData.Walls.TryAdd(newWall.ToString(), newWall);
|
|
connection?.InvokeAsync("NewWall", _session, newWall);
|
|
|
|
//connection?.InvokeAsync("SendMessage", $"{_selectedTile.X}:{_selectedTile.Y}", tileId.ToString(), _session);
|
|
}
|
|
}
|
|
}
|
|
}
|