Skip to content

Commit

Permalink
Added speed monitor for all games
Browse files Browse the repository at this point in the history
  • Loading branch information
rtsonneveld committed Mar 26, 2023
1 parent 566d2a3 commit 51e501c
Show file tree
Hide file tree
Showing 9 changed files with 332 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ public DonaldGameManager()
//Extras
ExtraActions = new ObservableCollection<ExtraAction>()
{
new GenericSpeedMonitorExtra(this),
new DonaldLivesExtra(this),
};

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
using System.Numerics;
using System.Windows;

namespace OpenSpaceToolbox
{
public class GenericSpeedMonitorExtra : OpenspaceExtraAction
{
public GenericSpeedMonitorExtra(OpenspaceGameManager gameManager) : base(gameManager)
{
Name = "Speed Monitor";
ShortName = "Speed Monitor";
}

public Vector3 PlayerCoordinates
{
get
{
var playerCoords = GameManager.PlayerCoordinates;

return new Vector3(
playerCoords.Item1,
playerCoords.Item2,
playerCoords.Item3
);
}
}

public override void Action()
{
SpeedMonitorWindow speedWindow = new SpeedMonitorWindow(new SpeedMonitorWindowViewModel(this))
{
Owner = Application.Current.MainWindow
};
speedWindow.Show();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ public Rayman2GameManager()
//Extras
ExtraActions = new ObservableCollection<ExtraAction>()
{
new GenericSpeedMonitorExtra(this),
new Rayman2VoidExtra(this),
new Rayman2NoHpExtra(this),
new Rayman2MaxHpExtra(this),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ public Rayman3GameManager()
//Extras
ExtraActions = new ObservableCollection<ExtraAction>()
{
new GenericSpeedMonitorExtra(this),
};

//Levels
Expand Down
13 changes: 13 additions & 0 deletions OpenSpaceToolbox/OpenSpaceToolbox.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,9 @@
</Reference>
<Reference Include="System" />
<Reference Include="System.Data" />
<Reference Include="System.Numerics.Vectors, Version=4.1.4.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.Numerics.Vectors.4.5.0\lib\portable-net45+win8+wp8+wpa81\System.Numerics.Vectors.dll</HintPath>
</Reference>
<Reference Include="System.ValueTuple, Version=4.0.3.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>..\packages\System.ValueTuple.4.5.0\lib\netstandard1.0\System.ValueTuple.dll</HintPath>
</Reference>
Expand All @@ -92,10 +95,12 @@
<Compile Include="Converters\IsValidIndexConverter.cs" />
<Compile Include="DataModels\GameItem.cs" />
<Compile Include="DataModels\GameList.cs" />
<Compile Include="GameManager\Games\Generic\GenericSpeedMonitorExtra.cs" />
<Compile Include="GameManager\Games\Rayman2\Rayman2MaxHpExtra.cs" />
<Compile Include="GameManager\Games\Rayman2\Rayman2ProgressArrayExtra.cs" />
<Compile Include="GameManager\Games\Rayman3\Rayman3GameManager.cs" />
<Compile Include="Helpers\ArrayUtil.cs" />
<Compile Include="ViewModels\SpeedMonitorWindowViewModel.cs" />
<Compile Include="ViewModels\ProgressArrayWindowViewModel.cs" />
<Compile Include="Windows\GameChooser.xaml.cs">
<DependentUpon>GameChooser.xaml</DependentUpon>
Expand Down Expand Up @@ -135,6 +140,9 @@
<Compile Include="Views\GameManagerMinimizedView.xaml.cs">
<DependentUpon>GameManagerMinimizedView.xaml</DependentUpon>
</Compile>
<Compile Include="Windows\SpeedMonitorWindow.xaml.cs">
<DependentUpon>SpeedMonitorWindow.xaml</DependentUpon>
</Compile>
<Compile Include="Windows\ProgressArrayWindow.xaml.cs">
<DependentUpon>ProgressArrayWindow.xaml</DependentUpon>
</Compile>
Expand All @@ -156,6 +164,10 @@
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Windows\SpeedMonitorWindow.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
<Page Include="Windows\ProgressArrayWindow.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
Expand Down Expand Up @@ -211,6 +223,7 @@
<ItemGroup>
<Resource Include="OpenSpaceIcon.ico" />
</ItemGroup>
<ItemGroup />
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
Expand Down
132 changes: 132 additions & 0 deletions OpenSpaceToolbox/ViewModels/SpeedMonitorWindowViewModel.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Numerics;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Input;
using System.Windows.Threading;

namespace OpenSpaceToolbox
{
/// <summary>
/// View model for the Speed Monitor
/// </summary>
public class SpeedMonitorWindowViewModel : BaseViewModel
{
#region Constructor

public SpeedMonitorWindowViewModel(GenericSpeedMonitorExtra extra)
{
Extra = extra;

Task.Run(UpdateSpeedTask);
}

#endregion

#region Public Properties

public float PositionX => _lastPosition.X;
public float PositionY => _lastPosition.Y;
public float PositionZ => _lastPosition.Z;

public float SpeedX => _speed.X;
public float SpeedY => _speed.Y;
public float SpeedZ => _speed.Z;
public float SpeedXY => new Vector2(_speed.X, _speed.Y).Length();
public float SpeedXYZ => _speed.Length();

public float AverageSpeedX => _averageSpeed.X;
public float AverageSpeedY => _averageSpeed.Y;
public float AverageSpeedZ => _averageSpeed.Z;
public float AverageSpeedXY => new Vector2(_averageSpeed.X, _averageSpeed.Y).Length();
public float AverageSpeedXYZ => _averageSpeed.Length();

public float AverageSpeedDuration { get; set; } = 5.0f;

public bool Active { get; set; } = true;

#endregion

#region Private Properties

private GenericSpeedMonitorExtra Extra { get; }

#endregion

#region Fields

private Vector3 _speed;
private Vector3 _averageSpeed;

private Vector3 _lastPosition;
private long _lastTime;

private Dictionary<long, Vector3> _speedHistory;

#endregion

#region Public Methods

public async Task UpdateSpeedTask()
{
_speedHistory = new Dictionary<long, Vector3>();

await Task.Run(async () =>
{
while (Active) {
try {
int processHandle = Extra.GameManager.GetProcessHandle(false);

if (processHandle >= 0) {

var position = Extra.PlayerCoordinates;
var newTime = DateTime.Now.Ticks;
float timeDelta = (newTime - _lastTime) / (float)TimeSpan.TicksPerSecond;

if (timeDelta > 0) {
_speed = (position - _lastPosition) / timeDelta;
_speedHistory.Add(newTime, _speed);
}

// Remove old speeds from the history
long cutoffTime = newTime - (long)(AverageSpeedDuration * TimeSpan.TicksPerSecond);
_speedHistory = _speedHistory.
Where(kv => kv.Key > cutoffTime).
ToDictionary(kv=>kv.Key, kv=>kv.Value);

_averageSpeed = _speedHistory.Aggregate(Vector3.Zero,
(s, v) => s + v.Value) / _speedHistory.Count;

_lastPosition = position;
_lastTime = DateTime.Now.Ticks;

OnPropertyChanged(nameof(PositionX));
OnPropertyChanged(nameof(PositionY));
OnPropertyChanged(nameof(PositionZ));

OnPropertyChanged(nameof(SpeedX));
OnPropertyChanged(nameof(SpeedY));
OnPropertyChanged(nameof(SpeedZ));
OnPropertyChanged(nameof(SpeedXY));
OnPropertyChanged(nameof(SpeedXYZ));

OnPropertyChanged(nameof(AverageSpeedX));
OnPropertyChanged(nameof(AverageSpeedY));
OnPropertyChanged(nameof(AverageSpeedZ));
OnPropertyChanged(nameof(AverageSpeedXY));
OnPropertyChanged(nameof(AverageSpeedXYZ));
}

await Task.Delay(100);
} catch (Exception ex) {
MessageBox.Show(ex.Message);
}
}
});
}

#endregion
}
}
120 changes: 120 additions & 0 deletions OpenSpaceToolbox/Windows/SpeedMonitorWindow.xaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
<Window x:Class="OpenSpaceToolbox.SpeedMonitorWindow"
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:OpenSpaceToolbox"
mc:Ignorable="d"
Title="Speed Monitor"
MinWidth="280"
MinHeight="220"
ResizeMode="NoResize"
SnapsToDevicePixels="True"
d:DataContext="{d:DesignInstance local:SpeedMonitorWindowViewModel}" SizeToContent="WidthAndHeight" Closing="Window_Closing">
<Window.Resources>
<Style TargetType="{x:Type Button}" BasedOn="{StaticResource {x:Type Button}}">
<Setter Property="Padding" Value="5 2" />
</Style>
</Window.Resources>
<StackPanel Margin="10">
<Grid>
<Grid.RowDefinitions>
<RowDefinition MinHeight="50" />
<RowDefinition MinHeight="50" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition MinWidth="50" />
<ColumnDefinition MinWidth="50" />
</Grid.ColumnDefinitions>
<GroupBox Grid.Column="0"
Grid.Row="0"
Margin="0 0 0 0">
<GroupBox.Header>
<TextBlock FontWeight="Bold"
Text="Speed" />
</GroupBox.Header>
<StackPanel Margin="5">
<StackPanel Orientation="Horizontal">
<TextBlock Text="X: " />
<TextBlock Text="{Binding Path=SpeedX, StringFormat={}{0:F3}}" />
</StackPanel>
<StackPanel Orientation="Horizontal">
<TextBlock Text="Y: " />
<TextBlock Text="{Binding Path=SpeedY, StringFormat={}{0:F3}}" />
</StackPanel>
<StackPanel Orientation="Horizontal">
<TextBlock Text="Z: " />
<TextBlock Text="{Binding Path=SpeedZ, StringFormat={}{0:F3}}" />
</StackPanel>
<StackPanel Orientation="Horizontal">
<TextBlock Text="|XY|:" />
<TextBlock Text="{Binding SpeedXY, StringFormat=\{0:F3\}}" />
</StackPanel>
<StackPanel Orientation="Horizontal">
<TextBlock Text="|XYZ|:" />
<TextBlock Text="{Binding SpeedXYZ, StringFormat=\{0:F3\}}" />
</StackPanel>
</StackPanel>
</GroupBox>
<GroupBox Grid.Column="0"
Grid.Row="1"
Margin="0,0,0,0">
<GroupBox.Header>
<TextBlock FontWeight="Bold"
Text="Live Coordinates"
/>
</GroupBox.Header>
<StackPanel Margin="5">
<StackPanel Orientation="Horizontal">
<TextBlock Text="X: " />
<TextBlock Text="{Binding Path=PositionX, StringFormat={}{0:F3}}" />
</StackPanel>
<StackPanel Orientation="Horizontal">
<TextBlock Text="Y: " />
<TextBlock Text="{Binding Path=PositionY, StringFormat={}{0:F3}}" />
</StackPanel>
<StackPanel Orientation="Horizontal">
<TextBlock Text="Z: " />
<TextBlock Text="{Binding Path=PositionZ, StringFormat={}{0:F3}}" />
</StackPanel>
</StackPanel>
</GroupBox>
<GroupBox Grid.Column="1"
Margin="0,0,0,0">
<GroupBox.Header>
<TextBlock FontWeight="Bold"
Text="Average Speed" />
</GroupBox.Header>
<StackPanel Margin="5">
<StackPanel Orientation="Horizontal">
<TextBlock Text="X: " />
<TextBlock Text="{Binding Path=AverageSpeedX, StringFormat={}{0:F3}}" />
</StackPanel>
<StackPanel Orientation="Horizontal">
<TextBlock Text="Y: " />
<TextBlock Text="{Binding Path=AverageSpeedY, StringFormat={}{0:F3}}" />
</StackPanel>
<StackPanel Orientation="Horizontal">
<TextBlock Text="Z: " />
<TextBlock Text="{Binding Path=AverageSpeedZ, StringFormat={}{0:F3}}" />
</StackPanel>
<StackPanel Orientation="Horizontal">
<TextBlock Text="|XY|: " />
<TextBlock Text="{Binding Path=AverageSpeedXY, StringFormat={}{0:F3}}" />
</StackPanel>
<StackPanel Orientation="Horizontal">
<TextBlock Text="|XYZ|: " />
<TextBlock Text="{Binding Path=AverageSpeedXYZ, StringFormat={}{0:F3}}" />
</StackPanel>
<StackPanel Orientation="Horizontal">
<TextBlock Text="Duration: " />
<TextBlock Text="{Binding Path=AverageSpeedDuration, StringFormat={}{0:F1} s}" />
</StackPanel>
<Grid HorizontalAlignment="Stretch">
<Slider Value="{Binding Path=AverageSpeedDuration}" Minimum="0.1" Maximum="20.0" IsSnapToTickEnabled="True" TickFrequency="0.1"></Slider>
</Grid>
</StackPanel>
</GroupBox>
</Grid>
</StackPanel>
</Window>
26 changes: 26 additions & 0 deletions OpenSpaceToolbox/Windows/SpeedMonitorWindow.xaml.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
using System.Threading.Tasks;
using System.Windows;

namespace OpenSpaceToolbox
{
/// <summary>
/// Interaction logic for GlmWindow.xaml
/// </summary>
public partial class SpeedMonitorWindow : Window
{
public SpeedMonitorWindow(SpeedMonitorWindowViewModel viewModel)
{
InitializeComponent();

DataContext = ViewModel = viewModel;
//Task.Run(viewModel.UpdateSpeed);
}

private SpeedMonitorWindowViewModel ViewModel { get; }

private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
{
ViewModel.Active = false;
}
}
}
Loading

0 comments on commit 51e501c

Please sign in to comment.