Cleaned some code; added dynamic loading of sprites

This commit is contained in:
Brychan Dempsey 2021-08-29 21:12:37 +12:00
parent 9b5f08e86f
commit 453dcd52bd
3 changed files with 229 additions and 162 deletions

View File

@ -4,7 +4,7 @@
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d" mc:Ignorable="d"
Title="PDG Server" Height="600" Width="800"> Title="PDG Server" Height="768" Width="1024" Background="#FF4B4B4B">
<Grid> <Grid>
<Grid.ColumnDefinitions> <Grid.ColumnDefinitions>
<ColumnDefinition/> <ColumnDefinition/>
@ -16,30 +16,33 @@
<ColumnDefinition/> <ColumnDefinition/>
</Grid.ColumnDefinitions> </Grid.ColumnDefinitions>
<StackPanel> <StackPanel>
<TextBox x:Name="ImageSourceTextBox" Text="Source" TextWrapping="Wrap" LostFocus="ImageSourceTextBox_LostFocus"/> <TextBlock Text="Game Board File Path" TextWrapping="Wrap" Padding="0,10,0,0" Foreground="White" Margin="2,5,2,0"/>
<Button x:Name="BrowseButton" Content="Browse" Height="20" Width="40" Click="BrowseButton_Click"/> <TextBox x:Name="ImageSourceTextBox" TextWrapping="Wrap" LostFocus="ImageSourceTextBox_LostFocus" Margin="2,5,2,0"/>
<TextBlock Text="Number of Rows" TextWrapping="Wrap" Padding="0,10,0,0"/> <Button x:Name="BrowseButton" Content="Browse" Click="BrowseButton_Click" Margin="10,5,10,0"/>
<Slider x:Name="NumberOfRows" IsSnapToTickEnabled="True" Minimum="1" TickPlacement="BottomRight" AutoToolTipPlacement="BottomRight" ValueChanged="NumberOfRows_ValueChanged" Value="9"/> <TextBlock Text="Game Sprites Files" TextWrapping="Wrap" Padding="0,10,0,0" Foreground="White" Margin="2,0,2,0"/>
<TextBlock Text="Number of Columns:" TextWrapping="Wrap" Padding="0,10,0,0"/> <TextBox x:Name="ImageSourceTextBox_Copy" TextWrapping="Wrap" LostFocus="ImageSourceTextBox_LostFocus" Margin="2,5,2,0"/>
<Slider x:Name="NumberOfColumns" IsSnapToTickEnabled="True" Minimum="1" TickPlacement="BottomRight" AutoToolTipPlacement="BottomRight" ValueChanged="NumberOfColumns_ValueChanged" Value="9"/> <Button x:Name="GameSpritesBrowser" Content="Browse" Click="GameSpritesBrowser_Click" Margin="10,5,10,0"/>
<TextBlock Text="Starting Row" TextWrapping="Wrap" Padding="0,10,0,0"/> <TextBlock Text="Number of Rows" TextWrapping="Wrap" Padding="0,10,0,0" Foreground="White" Margin="2,0,2,0"/>
<Slider x:Name="StartingRow" IsSnapToTickEnabled="True" Value="8" AutoToolTipPlacement="BottomRight" TickPlacement="BottomRight" ValueChanged="Sliders_ValueChanged" Maximum="9"/> <Slider x:Name="NumberOfRows" IsSnapToTickEnabled="True" Minimum="1" TickPlacement="BottomRight" AutoToolTipPlacement="BottomRight" ValueChanged="NumberOfRows_ValueChanged" Value="9" Margin="2,0,2,0"/>
<TextBlock Text="Starting Column" TextWrapping="Wrap" Padding="0,10,0,0"/> <TextBlock Text="Number of Columns:" TextWrapping="Wrap" Padding="0,10,0,0" Foreground="White" Margin="2,0,2,0"/>
<Slider x:Name="StartingColumn" IsSnapToTickEnabled="True" AutoToolTipPlacement="BottomRight" TickPlacement="BottomRight" ValueChanged="Sliders_ValueChanged" Maximum="9"/> <Slider x:Name="NumberOfColumns" IsSnapToTickEnabled="True" Minimum="1" TickPlacement="BottomRight" AutoToolTipPlacement="BottomRight" ValueChanged="NumberOfColumns_ValueChanged" Value="9" Margin="2,0,2,0"/>
<TextBlock Text="Zoom Box Starting Row" TextWrapping="Wrap" Padding="0,10,0,0"/> <TextBlock Text="Starting Row" TextWrapping="Wrap" Padding="0,10,0,0" Foreground="White" Margin="2,0,2,0"/>
<Slider x:Name="ZoomBoxStartRow" IsSnapToTickEnabled="True" AutoToolTipPlacement="BottomRight" TickPlacement="BottomRight" Value="3" ValueChanged="Sliders_ValueChanged" Maximum="9"/> <Slider x:Name="StartingRow" IsSnapToTickEnabled="True" Value="8" AutoToolTipPlacement="BottomRight" TickPlacement="BottomRight" ValueChanged="Sliders_ValueChanged" Maximum="9" Margin="2,0,2,0"/>
<TextBlock Text="Zoom Box Starting Column" TextWrapping="Wrap" Padding="0,10,0,0"/> <TextBlock Text="Starting Column" TextWrapping="Wrap" Padding="0,10,0,0" Foreground="White" Margin="2,0,2,0"/>
<Slider x:Name="ZoomBoxStartColumn" IsSnapToTickEnabled="True" AutoToolTipPlacement="BottomRight" TickPlacement="BottomRight" Value="3" ValueChanged="Sliders_ValueChanged" Maximum="9"/> <Slider x:Name="StartingColumn" IsSnapToTickEnabled="True" AutoToolTipPlacement="BottomRight" TickPlacement="BottomRight" ValueChanged="Sliders_ValueChanged" Maximum="9" Margin="2,0,2,0"/>
<TextBlock Text="Zoom Box Span" TextWrapping="Wrap" Padding="0,10,0,0"/> <TextBlock Text="Zoom Box Starting Row" TextWrapping="Wrap" Padding="0,10,0,0" Foreground="White" Margin="2,0,2,0"/>
<Slider x:Name="ZoomBoxSpan" IsSnapToTickEnabled="True" AutoToolTipPlacement="BottomRight" TickPlacement="BottomRight" Value="3" ValueChanged="Sliders_ValueChanged" Minimum="1" Maximum="6"/> <Slider x:Name="ZoomBoxStartRow" IsSnapToTickEnabled="True" AutoToolTipPlacement="BottomRight" TickPlacement="BottomRight" Value="3" ValueChanged="Sliders_ValueChanged" Maximum="9" Margin="2,0,2,0"/>
<Button x:Name="GridVisibilityToggleButton" Content="Show/Hide Grid" Click="GridVisibilityToggleButton_Click"/> <TextBlock Text="Zoom Box Starting Column" TextWrapping="Wrap" Padding="0,10,0,0" Foreground="White" Margin="2,0,2,0"/>
<Button x:Name="StartServerButton" Content="Start Server" HorizontalAlignment="Center" Margin="0,25,0,0" Click="StartServerButton_Click"/> <Slider x:Name="ZoomBoxStartColumn" IsSnapToTickEnabled="True" AutoToolTipPlacement="BottomRight" TickPlacement="BottomRight" Value="3" ValueChanged="Sliders_ValueChanged" Maximum="9" Margin="2,0,2,0"/>
<Button x:Name="DrawRandomizedPlayers" Content="Draw Random Players" Margin="0,25,0,0" Click="DrawRandomizedPlayers_Click"/> <TextBlock Text="Zoom Box Span" TextWrapping="Wrap" Padding="0,10,0,0" Foreground="White" Margin="2,0,2,0"/>
<WrapPanel Height="100"> <Slider x:Name="ZoomBoxSpan" IsSnapToTickEnabled="True" AutoToolTipPlacement="BottomRight" TickPlacement="BottomRight" Value="3" ValueChanged="Sliders_ValueChanged" Minimum="1" Maximum="6" Margin="2,0,2,0"/>
</WrapPanel> <Button x:Name="GridVisibilityToggleButton" Content="Show/Hide Grid" Click="GridVisibilityToggleButton_Click" Margin="10,10,10,0"/>
<Button x:Name="StartServerButton" Content="Start Server" HorizontalAlignment="Stretch" Margin="10,25,10,0" Click="StartServerButton_Click" Background="#955FF17A" Foreground="White"/>
<Button x:Name="DrawRandomizedPlayers" Content="Draw Random Players" Margin="10,25,10,0" Click="DrawRandomizedPlayers_Click"/>
<UniformGrid x:Name="LoadedSprites" Columns="6" Margin="2,0,2,0" Rows="6" MinHeight="120" />
</StackPanel> </StackPanel>
<Border Grid.Column="1" BorderThickness="1,1,1,1" Background="#54D3D3D3" BorderBrush="DarkGray"> <Border Grid.Column="1" BorderThickness="1,1,1,1" BorderBrush="DarkGray" Background="#19000000">
<ListView x:Name="PlayersList"> <ListView x:Name="PlayersList" Background="{x:Null}">
<ListView.View> <ListView.View>
<GridView> <GridView>
<GridViewColumn/> <GridViewColumn/>

View File

@ -1,7 +1,10 @@
using Microsoft.Win32; using Microsoft.Win32;
using System; using System;
using System.Collections.Concurrent;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Threading;
using System.Threading.Tasks;
using System.Windows; using System.Windows;
using System.Windows.Controls; using System.Windows.Controls;
using System.Windows.Controls.Primitives; using System.Windows.Controls.Primitives;
@ -22,7 +25,6 @@ namespace RBG_Server.WPF
public MainWindow() public MainWindow()
{ {
InitializeComponent(); InitializeComponent();
//gameServer = new GameServer(8, 0, 9, 9, 3, 3, 3, 3, null);
} }
/// <summary> /// <summary>
@ -33,7 +35,7 @@ namespace RBG_Server.WPF
private void BrowseButton_Click(object sender, RoutedEventArgs e) private void BrowseButton_Click(object sender, RoutedEventArgs e)
{ {
OpenFileDialog ofd = new(); OpenFileDialog ofd = new();
ofd.Filter = "Image Files (.png; .jpg)|*.png;*.jpg"; ofd.Filter = "Image Files|*.png;*.jpg";
if (ofd.ShowDialog() == true) if (ofd.ShowDialog() == true)
{ {
ImageSourceTextBox.Text = ofd.FileName; ImageSourceTextBox.Text = ofd.FileName;
@ -81,7 +83,7 @@ namespace RBG_Server.WPF
/// <param name="e"></param> /// <param name="e"></param>
private void StartServerButton_Click(object sender, RoutedEventArgs e) private void StartServerButton_Click(object sender, RoutedEventArgs e)
{ {
gameServer = new((int)StartingRow.Value, (int)StartingColumn.Value, (int)NumberOfRows.Value, (int)NumberOfColumns.Value, (int)ZoomBoxStartRow.Value, (int)ZoomBoxStartColumn.Value, (int)ZoomBoxSpan.Value, (int)ZoomBoxSpan.Value, gameBoard); gameServer = new((byte)StartingRow.Value, (byte)StartingColumn.Value, (byte)NumberOfRows.Value, (byte)NumberOfColumns.Value, (byte)ZoomBoxStartRow.Value, (byte)ZoomBoxStartColumn.Value, (byte)ZoomBoxSpan.Value, (byte)ZoomBoxSpan.Value, gameBoard);
} }
@ -285,6 +287,68 @@ namespace RBG_Server.WPF
GenerateGameBoard(randPlayers); GenerateGameBoard(randPlayers);
} }
ConcurrentDictionary<string, MemoryStream> loadedSprites = new();
Task loadingFiles;
private void GameSpritesBrowser_Click(object sender, RoutedEventArgs e)
{
OpenFileDialog ofd = new();
ofd.Filter = "Image Files|*.png;*.jpg";
ofd.Multiselect = true;
if (ofd.ShowDialog() == true)
{
string[] resultFiles = ofd.FileNames;
loadedSprites.Clear();
// Run the following work in a separate thread
loadingFiles = Task.Run(() =>
{
// Continue in parallel
_ = Parallel.ForEach(resultFiles, (file) =>
{
MemoryStream ms = new();
using FileStream fs = File.OpenRead(file);
if (new FileInfo(file).Length > 512e6) // greater than 512 kB; resize the sprite to something more reasonable
{
BitmapImage gameBoardImage = new();
gameBoardImage.BeginInit();
gameBoardImage.StreamSource = fs;
gameBoardImage.CacheOption = BitmapCacheOption.Default;
gameBoardImage.EndInit();
double vRate = 128 / (double)gameBoardImage.PixelHeight; // Resize so the largest dimension is 128 px
double hRate = 128 / (double)gameBoardImage.PixelWidth;
TransformedBitmap modified = new(gameBoardImage, new ScaleTransform(gameBoardImage.PixelWidth * Math.Min(vRate, hRate), gameBoardImage.PixelHeight * Math.Min(vRate, hRate)));
PngBitmapEncoder encoder = new();
encoder.Frames.Add(BitmapFrame.Create(modified));
encoder.Save(ms);
}
else
{
fs.CopyTo(ms);
}
_ = loadedSprites.TryAdd(file, ms);
});
// Invoke the dispatcher to add all of the sprites to the loaded sprites list
_ = Application.Current.Dispatcher.BeginInvoke(System.Windows.Threading.DispatcherPriority.Render, new Action(() =>
{
LoadedSprites.Children.Clear();
foreach (KeyValuePair<string, MemoryStream> item in loadedSprites)
{
BitmapImage image = new();
image.BeginInit();
image.StreamSource = item.Value;
image.EndInit();
Image spriteImage = new()
{
Source = image
};
_ = LoadedSprites.Children.Add(spriteImage);
}
}));
});
}
}
} }
} }

View File

@ -27,16 +27,16 @@ namespace RBG_Server
/// <param name="startRow">The starting row of the board</param> /// <param name="startRow">The starting row of the board</param>
/// <param name="startColumn">The starting column of the board</param> /// <param name="startColumn">The starting column of the board</param>
/// <param name="boardImage">The full-scale board image</param> /// <param name="boardImage">The full-scale board image</param>
public GameServer(int startRow, int startColumn, int rowSize, int columnSize, int zoomRow, int zoomCol, int zoomRowSpan, int zoomColSpan, Stream boardImage) public GameServer(byte startRow, byte startColumn, byte rowSize, byte columnSize, byte zoomRow, byte zoomCol, byte zoomRowSpan, byte zoomColSpan, Stream boardImage)
{ {
this.startRow = (byte)startRow; this.startRow = startRow;
this.startColumn = (byte)startColumn; this.startColumn = startColumn;
this.rowSize = (byte)rowSize; this.rowSize = rowSize;
this.columnSize = (byte)columnSize; this.columnSize = columnSize;
this.zoomRow = (byte)zoomRow; this.zoomRow = zoomRow;
this.zoomCol = (byte)zoomCol; this.zoomCol = zoomCol;
this.zoomRowSpan = (byte)zoomRowSpan; this.zoomRowSpan = zoomRowSpan;
this.zoomColSpan = (byte)zoomColSpan; this.zoomColSpan = zoomColSpan;
BitmapImage gameBoardImage = new(); BitmapImage gameBoardImage = new();
gameBoardImage.StreamSource = boardImage; gameBoardImage.StreamSource = boardImage;
// Hold images // Hold images
@ -194,7 +194,7 @@ namespace RBG_Server
stream.Write(boardImages[index]); stream.Write(boardImages[index]);
} }
static int currentTurn = 0; static int currentTurn;
void ServerUpdate() void ServerUpdate()
{ {
@ -224,7 +224,7 @@ namespace RBG_Server
// ***** Recieve Data ***** // ***** Recieve Data *****
// *************************** // ***************************
// Data are recieved in parallel, so that it may be processed quickly // Data are recieved in parallel, so that it may be processed quickly
Parallel.ForEach(clients, (item) => _ = Parallel.ForEach(clients, (item) =>
{ {
Player player = item.Value; Player player = item.Value;
if (!item.Key.Connected) if (!item.Key.Connected)
@ -246,7 +246,7 @@ namespace RBG_Server
// Grab the stream to read from/write to // Grab the stream to read from/write to
NetworkStream clientStream = item.Key.GetStream(); NetworkStream clientStream = item.Key.GetStream();
// read the buffer to the end // read the buffer to the end
clientStream.Read(receivedBytes, player.UnhandledBuffer.Length, availableBytes); _ = clientStream.Read(receivedBytes, player.UnhandledBuffer.Length, availableBytes);
// Copy the unhandled buffer to the recieved bytes // Copy the unhandled buffer to the recieved bytes
player.UnhandledBuffer.CopyTo(receivedBytes, 0); player.UnhandledBuffer.CopyTo(receivedBytes, 0);
@ -344,7 +344,7 @@ namespace RBG_Server
// a response // a response
else if (TimeSpan.FromTicks(DateTime.Now.Ticks - item.Value.LastTime) > TimeSpan.FromSeconds(5)) else if (TimeSpan.FromTicks(DateTime.Now.Ticks - item.Value.LastTime) > TimeSpan.FromSeconds(5))
{ {
item.Key.GetStream().Write(new byte[] { (byte)(Players.IndexOf(item.Value)), 0xFF }); // Heartbeat is 0x0, 0x1 item.Key.GetStream().Write(new byte[] { (byte)Players.IndexOf(item.Value), 0xFF }); // Heartbeat is 0x0, 0x1
Player curr = item.Value; Player curr = item.Value;
curr.LastTime = DateTime.Now.Ticks; curr.LastTime = DateTime.Now.Ticks;
} }
@ -359,7 +359,7 @@ namespace RBG_Server
// *************************** // ***************************
// ** Remove old connections** // ** Remove old connections**
// *************************** // ***************************
foreach (var item in closedClients) foreach (TcpClient item in closedClients)
{ {
_ = Players.Remove(clients[item]); _ = Players.Remove(clients[item]);
_ = clients.Remove(item); _ = clients.Remove(item);