Created
March 5, 2021 21:38
-
-
Save ScottLilly/73386968a73657e88185578006a43d9f to your computer and use it in GitHub Desktop.
Lesson 18.5: Update game loading and saving
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<Window x:Class="WPFUI.MainWindow" | |
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" | |
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" | |
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" | |
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" | |
xmlns:viewModels="clr-namespace:Engine.ViewModels;assembly=Engine" | |
d:DataContext="{d:DesignInstance viewModels:GameSession}" | |
mc:Ignorable="d" | |
FontSize="11pt" | |
Title="{Binding GameDetails.Title}" Height="768" Width="1024" | |
KeyDown="MainWindow_OnKeyDown" | |
Closing="MainWindow_OnClosing"> | |
<Window.Resources> | |
<BooleanToVisibilityConverter x:Key="BooleanToVisibility" /> | |
</Window.Resources> | |
<Grid> | |
<Grid.RowDefinitions> | |
<RowDefinition Height="Auto"/> | |
<RowDefinition Height="*"/> | |
<RowDefinition Height="225"/> | |
</Grid.RowDefinitions> | |
<Grid.ColumnDefinitions> | |
<ColumnDefinition Width="250"/> | |
<ColumnDefinition Width="*"/> | |
</Grid.ColumnDefinitions> | |
<!-- Menu --> | |
<Menu Grid.Row="0" Grid.Column="0" | |
Grid.ColumnSpan="2" | |
FontSize="11pt" | |
Background="AliceBlue"> | |
<MenuItem Header="File"> | |
<MenuItem Header="New Game" | |
Click="StartNewGame_OnClick"/> | |
<MenuItem Header="Save Game" | |
Click="SaveGame_OnClick"/> | |
<Separator/> | |
<MenuItem Header="Exit" | |
Click="Exit_OnClick"/> | |
</MenuItem> | |
<MenuItem Header="Help"> | |
<MenuItem Header="Help" | |
IsEnabled="False"/> | |
<Separator/> | |
<MenuItem Header="About" | |
IsEnabled="False"/> | |
</MenuItem> | |
</Menu> | |
<!-- Player stats --> | |
<Grid Grid.Row="1" Grid.Column="0" Background="Aquamarine"> | |
<Grid.RowDefinitions> | |
<RowDefinition Height="Auto"/> | |
<RowDefinition Height="Auto"/> | |
<RowDefinition Height="Auto"/> | |
<RowDefinition Height="Auto"/> | |
<RowDefinition Height="Auto"/> | |
<RowDefinition Height="Auto"/> | |
</Grid.RowDefinitions> | |
<Grid.ColumnDefinitions> | |
<ColumnDefinition Width="Auto"/> | |
<ColumnDefinition Width="Auto"/> | |
</Grid.ColumnDefinitions> | |
<Label Grid.Row="0" Grid.Column="0" Content="Name:"/> | |
<Label Grid.Row="0" Grid.Column="1" Content="{Binding CurrentPlayer.Name}"/> | |
<Label Grid.Row="1" Grid.Column="0" Content="Hit points:"/> | |
<Label Grid.Row="1" Grid.Column="1" Content="{Binding CurrentPlayer.CurrentHitPoints}"/> | |
<Label Grid.Row="2" Grid.Column="0" Content="Gold:"/> | |
<Label Grid.Row="2" Grid.Column="1" Content="{Binding CurrentPlayer.Gold}"/> | |
<Label Grid.Row="3" Grid.Column="0" Content="XP:"/> | |
<Label Grid.Row="3" Grid.Column="1" Content="{Binding CurrentPlayer.ExperiencePoints}"/> | |
<Label Grid.Row="4" Grid.Column="0" Content="Level:"/> | |
<Label Grid.Row="4" Grid.Column="1" Content="{Binding CurrentPlayer.Level}"/> | |
<!-- Player Attributes --> | |
<ListBox Grid.Row="5" Grid.Column="0" | |
Grid.ColumnSpan="2" | |
Background="Aquamarine" | |
BorderThickness="0" | |
Grid.IsSharedSizeScope="True" | |
ItemsSource="{Binding CurrentPlayer.Attributes}"> | |
<ListBox.ItemTemplate> | |
<DataTemplate> | |
<StackPanel Orientation="Horizontal"> | |
<Grid> | |
<Grid.ColumnDefinitions> | |
<ColumnDefinition SharedSizeGroup="Description"/> | |
</Grid.ColumnDefinitions> | |
<TextBlock Text="{Binding DisplayName}" | |
HorizontalAlignment="Left" | |
MinWidth="100"/> | |
</Grid> | |
<Grid> | |
<Grid.ColumnDefinitions> | |
<ColumnDefinition SharedSizeGroup="ModifiedValue"/> | |
</Grid.ColumnDefinitions> | |
<TextBlock Text="{Binding ModifiedValue}" | |
HorizontalAlignment="Right"/> | |
</Grid> | |
</StackPanel> | |
</DataTemplate> | |
</ListBox.ItemTemplate> | |
</ListBox> | |
</Grid> | |
<!-- Gameplay --> | |
<Grid Grid.Row="1" Grid.Column="1" | |
Background="Beige"> | |
<Grid.RowDefinitions> | |
<RowDefinition Height="*"/> | |
<RowDefinition Height="*"/> | |
</Grid.RowDefinitions> | |
<Grid.ColumnDefinitions> | |
<ColumnDefinition Width="3*"/> | |
<ColumnDefinition Width="2*"/> | |
</Grid.ColumnDefinitions> | |
<!-- Game Messages --> | |
<Border Grid.Row="0" Grid.Column="0" | |
Grid.RowSpan="2" | |
BorderBrush="Gainsboro" | |
BorderThickness="1"> | |
<RichTextBox x:Name="GameMessages" | |
Background="Beige" | |
VerticalScrollBarVisibility="Auto"> | |
<RichTextBox.Resources> | |
<Style TargetType="{x:Type Paragraph}"> | |
<Setter Property="Margin" Value="0"/> | |
</Style> | |
</RichTextBox.Resources> | |
</RichTextBox> | |
</Border> | |
<!-- Location information --> | |
<Border Grid.Row="0" Grid.Column="1" | |
BorderBrush="Gainsboro" | |
BorderThickness="1"> | |
<Grid Margin="3"> | |
<Grid.RowDefinitions> | |
<RowDefinition Height="Auto"/> | |
<RowDefinition Height="*"/> | |
<RowDefinition Height="Auto"/> | |
</Grid.RowDefinitions> | |
<TextBlock Grid.Row="0" | |
HorizontalAlignment="Center" | |
Text="{Binding CurrentLocation.Name}"/> | |
<Image Grid.Row="1" | |
HorizontalAlignment="Center" | |
VerticalAlignment="Center" | |
Height="125" | |
Width="125" | |
Source="{Binding CurrentLocation.ImageName, | |
Converter={StaticResource FileToBitmapConverter}}"/> | |
<TextBlock Grid.Row="2" | |
HorizontalAlignment="Center" | |
Text="{Binding CurrentLocation.Description}" | |
TextWrapping="Wrap"/> | |
</Grid> | |
</Border> | |
<!-- Monster information --> | |
<Border Grid.Row="1" Grid.Column="1" | |
BorderBrush="Gainsboro" | |
BorderThickness="1"> | |
<Grid> | |
<Grid.RowDefinitions> | |
<RowDefinition Height="Auto" /> | |
<RowDefinition Height="*" /> | |
<RowDefinition Height="Auto" /> | |
</Grid.RowDefinitions> | |
<TextBlock Grid.Row="0" | |
HorizontalAlignment="Center" | |
Height="Auto" | |
Text="{Binding CurrentMonster.Name}" /> | |
<Image Grid.Row="1" | |
HorizontalAlignment="Center" | |
VerticalAlignment="Center" | |
Height="125" | |
Width="125" | |
Source="{Binding CurrentMonster.ImageName, | |
Converter={StaticResource FileToBitmapConverter}}"/> | |
<StackPanel Grid.Row="2" | |
Visibility="{Binding HasMonster, Converter={StaticResource BooleanToVisibility}}" | |
HorizontalAlignment="Center" | |
Orientation="Horizontal"> | |
<TextBlock>Current Hit Points:</TextBlock> | |
<TextBlock Text="{Binding CurrentMonster.CurrentHitPoints}" /> | |
</StackPanel> | |
</Grid> | |
</Border> | |
</Grid> | |
<!-- Inventory, Quests, and Recipes --> | |
<Grid Grid.Row="2" Grid.Column="0" | |
Background="BurlyWood"> | |
<TabControl x:Name="PlayerDataTabControl"> | |
<TabItem Header="Inventory" | |
x:Name="InventoryTabItem"> | |
<DataGrid ItemsSource="{Binding CurrentPlayer.Inventory.GroupedInventory}" | |
AutoGenerateColumns="False" | |
HeadersVisibility="Column"> | |
<DataGrid.Columns> | |
<DataGridTextColumn Header="Description" | |
Binding="{Binding Item.Name, Mode=OneWay}" | |
Width="*"/> | |
<DataGridTextColumn Header="Qty" | |
IsReadOnly="True" | |
Width="Auto" | |
Binding="{Binding Quantity, Mode=OneWay}"/> | |
<DataGridTextColumn Header="Price" | |
Binding="{Binding Item.Price, Mode=OneWay}" | |
Width="Auto"/> | |
</DataGrid.Columns> | |
</DataGrid> | |
</TabItem> | |
<TabItem Header="Quests" | |
x:Name="QuestsTabItem"> | |
<DataGrid ItemsSource="{Binding CurrentPlayer.Quests}" | |
AutoGenerateColumns="False" | |
HeadersVisibility="Column"> | |
<DataGrid.Columns> | |
<DataGridTextColumn Header="Name" | |
Binding="{Binding PlayerQuest.Name, Mode=OneWay}" | |
Width="*"> | |
<DataGridTextColumn.CellStyle> | |
<Style TargetType="DataGridCell"> | |
<Setter Property="ToolTip" | |
Value="{Binding PlayerQuest.ToolTipContents}"/> | |
</Style> | |
</DataGridTextColumn.CellStyle> | |
</DataGridTextColumn> | |
<DataGridTextColumn Header="Done?" | |
Binding="{Binding IsCompleted, Mode=OneWay}" | |
Width="Auto"/> | |
</DataGrid.Columns> | |
</DataGrid> | |
</TabItem> | |
<TabItem Header="Recipes" | |
x:Name="RecipesTabItem"> | |
<DataGrid ItemsSource="{Binding CurrentPlayer.Recipes}" | |
AutoGenerateColumns="False" | |
HeadersVisibility="Column"> | |
<DataGrid.Columns> | |
<DataGridTextColumn Header="Name" | |
Binding="{Binding Name, Mode=OneWay}" | |
Width="*"> | |
<DataGridTextColumn.CellStyle> | |
<Style TargetType="DataGridCell"> | |
<Setter Property="ToolTip" | |
Value="{Binding ToolTipContents}"/> | |
</Style> | |
</DataGridTextColumn.CellStyle> | |
</DataGridTextColumn> | |
<DataGridTemplateColumn MinWidth="75"> | |
<DataGridTemplateColumn.CellTemplate> | |
<DataTemplate> | |
<Button Click="OnClick_Craft" | |
Width="55" | |
Content="Craft"/> | |
</DataTemplate> | |
</DataGridTemplateColumn.CellTemplate> | |
</DataGridTemplateColumn> | |
</DataGrid.Columns> | |
</DataGrid> | |
</TabItem> | |
</TabControl> | |
</Grid> | |
<!-- Action controls --> | |
<Grid Grid.Row="2" Grid.Column="1" | |
Background="Lavender"> | |
<Grid.RowDefinitions> | |
<RowDefinition Height="*" /> | |
</Grid.RowDefinitions> | |
<Grid.ColumnDefinitions> | |
<ColumnDefinition Width="*" /> | |
<ColumnDefinition Width="255" /> | |
</Grid.ColumnDefinitions> | |
<!-- Combat Controls --> | |
<Grid Grid.Row="0" Grid.Column="0" | |
HorizontalAlignment="Center" | |
VerticalAlignment="Center"> | |
<Grid.RowDefinitions> | |
<RowDefinition Height="Auto"/> | |
<RowDefinition Height="Auto"/> | |
</Grid.RowDefinitions> | |
<Grid.ColumnDefinitions> | |
<ColumnDefinition Width="150"/> | |
<ColumnDefinition Width="10"/> | |
<ColumnDefinition Width="50"/> | |
</Grid.ColumnDefinitions> | |
<ComboBox Grid.Row="0" Grid.Column="0" | |
Visibility="{Binding HasMonster, Converter={StaticResource BooleanToVisibility}}" | |
ItemsSource="{Binding CurrentPlayer.Inventory.Weapons}" | |
SelectedItem="{Binding CurrentPlayer.CurrentWeapon}" | |
DisplayMemberPath="Name"/> | |
<Button Grid.Row="0" Grid.Column="2" | |
Visibility="{Binding HasMonster, Converter={StaticResource BooleanToVisibility}}" | |
Content="Use" | |
Click="OnClick_AttackMonster"/> | |
<ComboBox Grid.Row="1" Grid.Column="0" | |
Visibility="{Binding CurrentPlayer.Inventory.HasConsumable, Converter={StaticResource BooleanToVisibility}}" | |
ItemsSource="{Binding CurrentPlayer.Inventory.Consumables}" | |
SelectedItem="{Binding CurrentPlayer.CurrentConsumable}" | |
DisplayMemberPath="Name"/> | |
<Button Grid.Row="1" Grid.Column="2" | |
Visibility="{Binding CurrentPlayer.Inventory.HasConsumable, Converter={StaticResource BooleanToVisibility}}" | |
Content="Use" | |
Click="OnClick_UseCurrentConsumable"/> | |
</Grid> | |
<!-- Movement Controls --> | |
<Grid Grid.Row="0" Grid.Column="1"> | |
<Grid.RowDefinitions> | |
<RowDefinition Height="*" /> | |
<RowDefinition Height="*" /> | |
<RowDefinition Height="*" /> | |
</Grid.RowDefinitions> | |
<Grid.ColumnDefinitions> | |
<ColumnDefinition Width="*" /> | |
<ColumnDefinition Width="*" /> | |
<ColumnDefinition Width="*" /> | |
</Grid.ColumnDefinitions> | |
<Button Grid.Row="0" Grid.Column="1" | |
Height="25" Width="65" Margin="10" | |
Click="OnClick_MoveNorth" | |
Visibility="{Binding HasLocationToNorth, Converter={StaticResource BooleanToVisibility}}" | |
Content="North"/> | |
<Button Grid.Row="1" Grid.Column="0" | |
Height="25" Width="65" Margin="10" | |
Click="OnClick_MoveWest" | |
Visibility="{Binding HasLocationToWest, Converter={StaticResource BooleanToVisibility}}" | |
Content="West"/> | |
<Button Grid.Row="1" Grid.Column="1" | |
Height="25" Width="65" Margin="10" | |
Click="OnClick_DisplayTradeScreen" | |
Visibility="{Binding HasTrader, Converter={StaticResource BooleanToVisibility}}" | |
Content="Trade"/> | |
<Button Grid.Row="1" Grid.Column="2" | |
Height="25" Width="65" Margin="10" | |
Click="OnClick_MoveEast" | |
Visibility="{Binding HasLocationToEast, Converter={StaticResource BooleanToVisibility}}" | |
Content="East"/> | |
<Button Grid.Row="2" Grid.Column="1" | |
Height="25" Width="65" Margin="10" | |
Click="OnClick_MoveSouth" | |
Visibility="{Binding HasLocationToSouth, Converter={StaticResource BooleanToVisibility}}" | |
Content="South"/> | |
</Grid> | |
</Grid> | |
</Grid> | |
</Window> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.ComponentModel; | |
using System.Windows; | |
using System.Windows.Controls; | |
using System.Windows.Documents; | |
using System.Windows.Input; | |
using Engine.EventArgs; | |
using Engine.Models; | |
using Engine.Services; | |
using Engine.ViewModels; | |
using Microsoft.Win32; | |
using WPFUI.Windows; | |
namespace WPFUI | |
{ | |
public partial class MainWindow : Window | |
{ | |
private const string SAVE_GAME_FILE_EXTENSION = "soscsrpg"; | |
private readonly MessageBroker _messageBroker = MessageBroker.GetInstance(); | |
private readonly Dictionary<Key, Action> _userInputActions = | |
new Dictionary<Key, Action>(); | |
private GameSession _gameSession; | |
public MainWindow(Player player, int xLocation = 0, int yLocation = 0) | |
{ | |
InitializeComponent(); | |
InitializeUserInputActions(); | |
SetActiveGameSessionTo(new GameSession(player, xLocation, yLocation)); | |
} | |
private void OnClick_MoveNorth(object sender, RoutedEventArgs e) | |
{ | |
_gameSession.MoveNorth(); | |
} | |
private void OnClick_MoveWest(object sender, RoutedEventArgs e) | |
{ | |
_gameSession.MoveWest(); | |
} | |
private void OnClick_MoveEast(object sender, RoutedEventArgs e) | |
{ | |
_gameSession.MoveEast(); | |
} | |
private void OnClick_MoveSouth(object sender, RoutedEventArgs e) | |
{ | |
_gameSession.MoveSouth(); | |
} | |
private void OnClick_AttackMonster(object sender, RoutedEventArgs e) | |
{ | |
_gameSession.AttackCurrentMonster(); | |
} | |
private void OnClick_UseCurrentConsumable(object sender, RoutedEventArgs e) | |
{ | |
_gameSession.UseCurrentConsumable(); | |
} | |
private void OnGameMessageRaised(object sender, GameMessageEventArgs e) | |
{ | |
GameMessages.Document.Blocks.Add(new Paragraph(new Run(e.Message))); | |
GameMessages.ScrollToEnd(); | |
} | |
private void OnClick_DisplayTradeScreen(object sender, RoutedEventArgs e) | |
{ | |
if(_gameSession.CurrentTrader != null) | |
{ | |
TradeScreen tradeScreen = new TradeScreen(); | |
tradeScreen.Owner = this; | |
tradeScreen.DataContext = _gameSession; | |
tradeScreen.ShowDialog(); | |
} | |
} | |
private void OnClick_Craft(object sender, RoutedEventArgs e) | |
{ | |
Recipe recipe = ((FrameworkElement)sender).DataContext as Recipe; | |
_gameSession.CraftItemUsing(recipe); | |
} | |
private void InitializeUserInputActions() | |
{ | |
_userInputActions.Add(Key.W, () => _gameSession.MoveNorth()); | |
_userInputActions.Add(Key.A, () => _gameSession.MoveWest()); | |
_userInputActions.Add(Key.S, () => _gameSession.MoveSouth()); | |
_userInputActions.Add(Key.D, () => _gameSession.MoveEast()); | |
_userInputActions.Add(Key.Z, () => _gameSession.AttackCurrentMonster()); | |
_userInputActions.Add(Key.C, () => _gameSession.UseCurrentConsumable()); | |
_userInputActions.Add(Key.I, () => SetTabFocusTo("InventoryTabItem")); | |
_userInputActions.Add(Key.Q, () => SetTabFocusTo("QuestsTabItem")); | |
_userInputActions.Add(Key.R, () => SetTabFocusTo("RecipesTabItem")); | |
_userInputActions.Add(Key.T, () => OnClick_DisplayTradeScreen(this, new RoutedEventArgs())); | |
} | |
private void MainWindow_OnKeyDown(object sender, KeyEventArgs e) | |
{ | |
if(_userInputActions.ContainsKey(e.Key)) | |
{ | |
_userInputActions[e.Key].Invoke(); | |
} | |
} | |
private void SetTabFocusTo(string tabName) | |
{ | |
foreach(object item in PlayerDataTabControl.Items) | |
{ | |
if (item is TabItem tabItem) | |
{ | |
if (tabItem.Name == tabName) | |
{ | |
tabItem.IsSelected = true; | |
return; | |
} | |
} | |
} | |
} | |
private void SetActiveGameSessionTo(GameSession gameSession) | |
{ | |
// Unsubscribe from OnMessageRaised, or we will get double messages | |
_messageBroker.OnMessageRaised -= OnGameMessageRaised; | |
_gameSession = gameSession; | |
DataContext = _gameSession; | |
// Clear out previous game's messages | |
GameMessages.Document.Blocks.Clear(); | |
_messageBroker.OnMessageRaised += OnGameMessageRaised; | |
} | |
private void StartNewGame_OnClick(object sender, RoutedEventArgs e) | |
{ | |
Startup startup = new Startup(); | |
startup.Show(); | |
Close(); | |
} | |
private void SaveGame_OnClick(object sender, RoutedEventArgs e) | |
{ | |
SaveGame(); | |
} | |
private void Exit_OnClick(object sender, RoutedEventArgs e) | |
{ | |
Close(); | |
} | |
private void MainWindow_OnClosing(object sender, CancelEventArgs e) | |
{ | |
AskToSaveGame(); | |
} | |
private void AskToSaveGame() | |
{ | |
YesNoWindow message = | |
new YesNoWindow("Save Game", "Do you want to save your game?"); | |
message.Owner = GetWindow(this); | |
message.ShowDialog(); | |
if(message.ClickedYes) | |
{ | |
SaveGame(); | |
} | |
} | |
private void SaveGame() | |
{ | |
SaveFileDialog saveFileDialog = | |
new SaveFileDialog | |
{ | |
InitialDirectory = AppDomain.CurrentDomain.BaseDirectory, | |
Filter = $"Saved games (*.{SAVE_GAME_FILE_EXTENSION})|*.{SAVE_GAME_FILE_EXTENSION}" | |
}; | |
if (saveFileDialog.ShowDialog() == true) | |
{ | |
SaveGameService.Save(_gameSession, saveFileDialog.FileName); | |
} | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.IO; | |
using Engine.Factories; | |
using Engine.Models; | |
using Engine.ViewModels; | |
using Newtonsoft.Json; | |
using Newtonsoft.Json.Linq; | |
namespace Engine.Services | |
{ | |
public static class SaveGameService | |
{ | |
public static void Save(GameSession gameSession, string fileName) | |
{ | |
File.WriteAllText(fileName, | |
JsonConvert.SerializeObject(gameSession, Formatting.Indented)); | |
} | |
public static GameSession LoadLastSaveOrCreateNew(string fileName) | |
{ | |
if (!File.Exists(fileName)) | |
{ | |
throw new FileNotFoundException($"Filename: {fileName}"); | |
} | |
// Save game file exists, so create the GameSession object from it. | |
try | |
{ | |
JObject data = JObject.Parse(File.ReadAllText(fileName)); | |
// Populate Player object | |
Player player = CreatePlayer(data); | |
int x = (int)data[nameof(GameSession.CurrentLocation)][nameof(Location.XCoordinate)]; | |
int y = (int)data[nameof(GameSession.CurrentLocation)][nameof(Location.YCoordinate)]; | |
// Create GameSession object with saved game data | |
return new GameSession(player, x, y); | |
} | |
catch | |
{ | |
throw new FormatException($"Error reading: {fileName}"); | |
} | |
} | |
private static Player CreatePlayer(JObject data) | |
{ | |
Player player = | |
new Player((string)data[nameof(GameSession.CurrentPlayer)][nameof(Player.Name)], | |
(int)data[nameof(GameSession.CurrentPlayer)][nameof(Player.ExperiencePoints)], | |
(int)data[nameof(GameSession.CurrentPlayer)][nameof(Player.MaximumHitPoints)], | |
(int)data[nameof(GameSession.CurrentPlayer)][nameof(Player.CurrentHitPoints)], | |
GetPlayerAttributes(data), | |
(int)data[nameof(GameSession.CurrentPlayer)][nameof(Player.Gold)]); | |
PopulatePlayerInventory(data, player); | |
PopulatePlayerQuests(data, player); | |
PopulatePlayerRecipes(data, player); | |
return player; | |
} | |
private static IEnumerable<PlayerAttribute> GetPlayerAttributes(JObject data) | |
{ | |
List<PlayerAttribute> attributes = | |
new List<PlayerAttribute>(); | |
foreach(JToken itemToken in (JArray)data[nameof(GameSession.CurrentPlayer)] | |
[nameof(Player.Attributes)]) | |
{ | |
attributes.Add(new PlayerAttribute( | |
(string)itemToken[nameof(PlayerAttribute.Key)], | |
(string)itemToken[nameof(PlayerAttribute.DisplayName)], | |
(string)itemToken[nameof(PlayerAttribute.DiceNotation)], | |
(int)itemToken[nameof(PlayerAttribute.BaseValue)], | |
(int)itemToken[nameof(PlayerAttribute.ModifiedValue)])); | |
} | |
return attributes; | |
} | |
private static void PopulatePlayerInventory(JObject data, Player player) | |
{ | |
foreach(JToken itemToken in (JArray)data[nameof(GameSession.CurrentPlayer)] | |
[nameof(Player.Inventory)] | |
[nameof(Inventory.Items)]) | |
{ | |
int itemId = (int)itemToken[nameof(GameItem.ItemTypeID)]; | |
player.AddItemToInventory(ItemFactory.CreateGameItem(itemId)); | |
} | |
} | |
private static void PopulatePlayerQuests(JObject data, Player player) | |
{ | |
foreach(JToken questToken in (JArray)data[nameof(GameSession.CurrentPlayer)] | |
[nameof(Player.Quests)]) | |
{ | |
int questId = | |
(int)questToken[nameof(QuestStatus.PlayerQuest)][nameof(QuestStatus.PlayerQuest.ID)]; | |
Quest quest = QuestFactory.GetQuestByID(questId); | |
QuestStatus questStatus = new QuestStatus(quest); | |
questStatus.IsCompleted = (bool)questToken[nameof(QuestStatus.IsCompleted)]; | |
player.Quests.Add(questStatus); | |
} | |
} | |
private static void PopulatePlayerRecipes(JObject data, Player player) | |
{ | |
foreach(JToken recipeToken in | |
(JArray)data[nameof(GameSession.CurrentPlayer)][nameof(Player.Recipes)]) | |
{ | |
int recipeId = (int)recipeToken[nameof(Recipe.ID)]; | |
Recipe recipe = RecipeFactory.RecipeByID(recipeId); | |
player.Recipes.Add(recipe); | |
} | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<Window x:Class="WPFUI.Startup" | |
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" | |
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" | |
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" | |
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" | |
xmlns:local="clr-namespace:WPFUI" | |
xmlns:viewModels="clr-namespace:Engine.Models;assembly=Engine" | |
d:DataContext="{d:DesignInstance viewModels:GameDetails}" | |
mc:Ignorable="d" | |
FontSize="11pt" | |
Title="{Binding Title}" Height="400" Width="400"> | |
<Grid Margin="10,10,10,10"> | |
<Grid.RowDefinitions> | |
<RowDefinition Height="Auto"/> | |
<RowDefinition Height="Auto"/> | |
<RowDefinition Height="Auto"/> | |
</Grid.RowDefinitions> | |
<Grid.ColumnDefinitions> | |
<ColumnDefinition Width="*"/> | |
</Grid.ColumnDefinitions> | |
<Button Grid.Row="0" Grid.Column="0" | |
Margin="0,5,0,5" | |
HorizontalAlignment="Center" | |
Width="125" | |
Content="Start new game" | |
Click="StartNewGame_OnClick"/> | |
<Button Grid.Row="1" Grid.Column="0" | |
Margin="0,5,0,5" | |
HorizontalAlignment="Center" | |
Width="125" | |
Content="Load saved game" | |
Click="LoadSavedGame_OnClick"/> | |
<Button Grid.Row="2" Grid.Column="0" | |
Margin="0,5,0,5" | |
HorizontalAlignment="Center" | |
Width="125" | |
Content="Exit" | |
Click="Exit_OnClick"/> | |
</Grid> | |
</Window> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Windows; | |
using Engine.Services; | |
using Engine.ViewModels; | |
using Microsoft.Win32; | |
namespace WPFUI | |
{ | |
public partial class Startup : Window | |
{ | |
private const string SAVE_GAME_FILE_EXTENSION = "soscsrpg"; | |
public Startup() | |
{ | |
InitializeComponent(); | |
DataContext = GameDetailsService.ReadGameDetails(); | |
} | |
private void StartNewGame_OnClick(object sender, RoutedEventArgs e) | |
{ | |
CharacterCreation characterCreationWindow = new CharacterCreation(); | |
characterCreationWindow.Show(); | |
Close(); | |
} | |
private void LoadSavedGame_OnClick(object sender, RoutedEventArgs e) | |
{ | |
OpenFileDialog openFileDialog = | |
new OpenFileDialog | |
{ | |
InitialDirectory = AppDomain.CurrentDomain.BaseDirectory, | |
Filter = $"Saved games (*.{SAVE_GAME_FILE_EXTENSION})|*.{SAVE_GAME_FILE_EXTENSION}" | |
}; | |
if (openFileDialog.ShowDialog() == true) | |
{ | |
GameSession gameSession = | |
SaveGameService.LoadLastSaveOrCreateNew(openFileDialog.FileName); | |
MainWindow mainWindow = | |
new MainWindow(gameSession.CurrentPlayer, | |
gameSession.CurrentLocation.XCoordinate, | |
gameSession.CurrentLocation.YCoordinate); | |
mainWindow.Show(); | |
Close(); | |
} | |
} | |
private void Exit_OnClick(object sender, RoutedEventArgs e) | |
{ | |
Close(); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment