diff --git a/.github/workflows/CSharpBible.yml b/.github/workflows/CSharpBible.yml index a601fb628..80e82e2a4 100644 --- a/.github/workflows/CSharpBible.yml +++ b/.github/workflows/CSharpBible.yml @@ -1,115 +1,51 @@ -# This workflow uses actions that are not certified by GitHub. -# They are provided by a third-party and are governed by -# separate terms of service, privacy policy, and support -# documentation. - -# This workflow will build, test, sign and package a WPF or Windows Forms desktop application -# built on .NET Core. -# To learn how to migrate your existing application to .NET Core, -# refer to https://docs.microsoft.com/en-us/dotnet/desktop-wpf/migration/convert-project-from-net-framework -# -# To configure this workflow: -# -# 1. Configure environment variables -# GitHub sets default environment variables for every workflow run. -# Replace the variables relative to your project in the "env" section below. -# -# 2. Signing -# Generate a signing certificate in the Windows Application -# Packaging Project or add an existing signing certificate to the project. -# Next, use PowerShell to encode the .pfx file using Base64 encoding -# by running the following Powershell script to generate the output string: -# -# $pfx_cert = Get-Content '.\SigningCertificate.pfx' -Encoding Byte -# [System.Convert]::ToBase64String($pfx_cert) | Out-File 'SigningCertificate_Encoded.txt' -# -# Open the output file, SigningCertificate_Encoded.txt, and copy the -# string inside. Then, add the string to the repo as a GitHub secret -# and name it "Base64_Encoded_Pfx." -# For more information on how to configure your signing certificate for -# this workflow, refer to https://github.com/microsoft/github-actions-for-desktop-apps#signing -# -# Finally, add the signing certificate password to the repo as a secret and name it "Pfx_Key". -# See "Build the Windows Application Packaging project" below to see how the secret is used. -# -# For more information on GitHub Actions, refer to https://github.com/features/actions -# For a complete CI/CD sample to get started with GitHub Action workflows for Desktop Applications, -# refer to https://github.com/microsoft/github-actions-for-desktop-apps - -name: .NET Core Desktop +name: CSharpBible CI3 on: push: - branches: [ "master" ] + paths: + - "CSharpBible/**" pull_request: - branches: [ "master" ] + paths: + - "CSharpBible/**" jobs: - - build: - - strategy: - matrix: - configuration: [Debug, Release] - - runs-on: windows-latest # For a list of available runner types, refer to - # https://help.github.com/en/actions/reference/workflow-syntax-for-github-actions#jobsjob_idruns-on - - env: - Solution_Name: CSharpBible.sln # Replace with your solution name, i.e. MyWpfApp.sln. - Test_Project_Path: Tests\Test.csproj # Replace with the path to your test project, i.e. MyWpfApp.Tests\MyWpfApp.Tests.csproj. - Wap_Project_Directory: CSharpBible # Replace with the Wap project directory relative to the solution, i.e. MyWpfApp.Package. - Wap_Project_Path: CSharpBible # Replace with the path to your Wap project, i.e. MyWpf.App.Package\MyWpfApp.Package.wapproj. - + build-test: + runs-on: windows-latest + defaults: + run: + working-directory: CSharpBible steps: - - name: Checkout - uses: actions/checkout@v3 - with: - fetch-depth: 0 - - # Install the .NET Core workload - - name: Install .NET Core - uses: actions/setup-dotnet@v3 - with: - dotnet-version: 6.0.x - - # Add MSBuild to the PATH: https://github.com/microsoft/setup-msbuild - - name: Setup MSBuild.exe - uses: microsoft/setup-msbuild@v1.0.2 - - # Execute all unit tests in the solution - - name: Execute unit tests - run: dotnet test - - # Restore the application to populate the obj folder with RuntimeIdentifiers - - name: Restore the application - run: msbuild $env:Solution_Name /t:Restore /p:Configuration=$env:Configuration - env: - Configuration: ${{ matrix.configuration }} - - # Decode the base 64 encoded pfx and save the Signing_Certificate - - name: Decode the pfx - run: | - $pfx_cert_byte = [System.Convert]::FromBase64String("${{ secrets.Base64_Encoded_Pfx }}") - $certificatePath = Join-Path -Path $env:Wap_Project_Directory -ChildPath GitHubActionsWorkflow.pfx - [IO.File]::WriteAllBytes("$certificatePath", $pfx_cert_byte) - - # Create the app package by building and packaging the Windows Application Packaging project - - name: Create the app package - run: msbuild $env:Wap_Project_Path /p:Configuration=$env:Configuration /p:UapAppxPackageBuildMode=$env:Appx_Package_Build_Mode /p:AppxBundle=$env:Appx_Bundle /p:PackageCertificateKeyFile=GitHubActionsWorkflow.pfx /p:PackageCertificatePassword=${{ secrets.Pfx_Key }} - env: - Appx_Bundle: Always - Appx_Bundle_Platforms: x86|x64 - Appx_Package_Build_Mode: StoreUpload - Configuration: ${{ matrix.configuration }} - - # Remove the pfx - - name: Remove the pfx - run: Remove-Item -path $env:Wap_Project_Directory\GitHubActionsWorkflow.pfx - - # Upload the MSIX package: https://github.com/marketplace/actions/upload-a-build-artifact - - name: Upload build artifacts - uses: actions/upload-artifact@v3 - with: - name: MSIX Package - path: ${{ env.Wap_Project_Directory }}\AppPackages + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup .NET 8.0 + uses: actions/setup-dotnet@v4 + with: + dotnet-version: "8.0.x" + + - name: Remove private projects + run: | + dotnet sln CSharpBible.sln remove "Mobile/MauiApp1/MauiApp1.csproj" + dotnet sln CSharpBible.sln remove "Simulation/AGVFktTests/AGVFktTests.csproj" + dotnet sln CSharpBible.sln remove "Simulation/AGVFkt/AGVFkt.csproj" + dotnet sln CSharpBible.sln remove "DB/ADO_Test/ADO_Test.csproj" + dotnet sln CSharpBible.sln remove "Libraries/CSFreeVision_/CSFreeVision.csproj" + dotnet sln CSharpBible.sln remove "Mobile/DXMauiApp1/DXMauiApp1.csproj" + dotnet sln CSharpBible.sln remove "Web/MyComponent/Client/MyComponent.Client.csproj" + dotnet sln CSharpBible.sln remove "Web/MyComponent/Server/MyComponent.Server.csproj" + dotnet sln CSharpBible.sln remove "Web/MyComponent/Shared/MyComponent.csproj" + dotnet sln CSharpBible.sln remove "WinUI/App1/App1/App1.csproj" + dotnet sln CSharpBible.sln remove "App2/App2.csproj" + dotnet sln CSharpBible.sln remove "../PackageDwnLd.csproj" + dotnet sln CSharpBible.sln remove "Web/BlazorApp1/BlazorApp1.csproj" + dotnet sln CSharpBible.sln remove "Web/WebApp1/BlazorApp2/BlazorApp2.csproj" + dotnet sln CSharpBible.sln remove "Web/WebApp1/WebApplication1/WebApplication1/WebApplication1.csproj" + + - name: Restore + run: dotnet restore CSharpBible.sln -p:TargetFramework=net8.0-windows + + - name: Build + run: dotnet build CSharpBible.sln --configuration Release --no-restore -p:TargetFramework=net8.0-windows + + - name: Test + run: dotnet test CSharpBible.sln --configuration Release --no-build --verbosity normal -p:TargetFramework=net8.0-windows diff --git a/.github/workflows/Teststatements.yml b/.github/workflows/Teststatements.yml new file mode 100644 index 000000000..ec5a8018d --- /dev/null +++ b/.github/workflows/Teststatements.yml @@ -0,0 +1,35 @@ +name: TestStatemens CI0 + +on: + push: + paths: + - "TestStatements/**" + pull_request: + paths: + - "TestStatements/**" + +jobs: + build-test: + runs-on: windows-latest + defaults: + run: + working-directory: TestStatements + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup .NET 8.0 + uses: actions/setup-dotnet@v4 + with: + dotnet-version: "8.0.x" + + - name: Remove private projects + run: | + + - name: Restore + run: dotnet restore TestStatements.sln -p:TargetFramework=net8.0-windows + + - name: Build + run: dotnet build TestStatements.sln --configuration Release --no-restore -p:TargetFramework=net8.0-windows + - name: Test + run: dotnet test TestStatements.sln --configuration Release --no-build --verbosity normal -p:TargetFramework=net8.0-windows diff --git a/.gitignore b/.gitignore index 9c1706033..0b4b38c24 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ .vs +.gitignore bin obj *.db @@ -24,7 +25,7 @@ obj /CSharpBible/Libraries/CSFreeVision_ /CSharpBible/Libraries/MathLibraryTests/TestResults /CSharpBible/Graphics/PermutationTests/TestResults -/CSharpBible/MVVM_Tutorial/UWP_00_Test +/CSharpBible/MVVM_Tutorial /CSharpBible/WinUI/App1 /TestStatements/Help /CSharpBible/Games/SharpHack.Wpf/tiles.png diff --git a/Avalonia_Apps/Libraries/BaseLib/Interfaces/IConsole.cs b/Avalonia_Apps/Libraries/BaseLib/Interfaces/IConsole.cs index 709b8e83c..51a405c64 100644 --- a/Avalonia_Apps/Libraries/BaseLib/Interfaces/IConsole.cs +++ b/Avalonia_Apps/Libraries/BaseLib/Interfaces/IConsole.cs @@ -149,6 +149,7 @@ public interface IConsole /// The next line of characters from the input stream, or an empty string if no input is available. /// string ReadLine(); + void ResetColor(); /// /// Sets the position of the cursor within the console buffer. diff --git a/Avalonia_Apps/Libraries/BaseLib/Models/ConsoleProxy.cs b/Avalonia_Apps/Libraries/BaseLib/Models/ConsoleProxy.cs index 62bba77c8..0b2ee1214 100644 --- a/Avalonia_Apps/Libraries/BaseLib/Models/ConsoleProxy.cs +++ b/Avalonia_Apps/Libraries/BaseLib/Models/ConsoleProxy.cs @@ -6,57 +6,62 @@ namespace BaseLib.Models; public class ConsoleProxy : IConsole { - MethodInfo _writeLineS = typeof(Console).GetMethod(nameof(Console.WriteLine), [typeof(string)])!; - MethodInfo _beep = typeof(Console).GetMethod(nameof(Console.Beep), [typeof(int), typeof(int)])!; + protected MethodInfo _writeLineS = typeof(Console).GetMethod(nameof(Console.WriteLine), [typeof(string)])!; + protected MethodInfo _beep = typeof(Console).GetMethod(nameof(Console.Beep), [typeof(int), typeof(int)])!; #if NET5_0_OR_GREATER - MethodInfo _GetCursorPosition = typeof(Console).GetMethod(nameof(Console.GetCursorPosition), [])!; + protected MethodInfo _GetCursorPosition = typeof(Console).GetMethod(nameof(Console.GetCursorPosition), [])!; #else - MethodInfo _CursorLeft = typeof(Console).GetMethod(nameof(Console.CursorLeft), [])!; - MethodInfo _CursorTop = typeof(Console).GetMethod(nameof(Console.CursorTop), [])!; + protected MethodInfo _CursorLeft = typeof(Console).GetMethod(nameof(Console.CursorLeft), [])!; + protected MethodInfo _CursorTop = typeof(Console).GetMethod(nameof(Console.CursorTop), [])!; #endif - MethodInfo _ReadKey = typeof(Console).GetMethod(nameof(Console.ReadKey), [])!; - MethodInfo _Readline = typeof(Console).GetMethod(nameof(Console.ReadLine), [])!; - MethodInfo _setCursorPosition = typeof(Console).GetMethod(nameof(Console.SetCursorPosition), [typeof(int), typeof(int)])!; - MethodInfo _writeCh = typeof(Console).GetMethod(nameof(Console.Write), [typeof(char)])!; - MethodInfo _writeS = typeof(Console).GetMethod(nameof(Console.Write), [typeof(string)])!; - MethodInfo _clear = typeof(Console).GetMethod(nameof(Console.Clear), [])!; - - PropertyInfo _ForegroundColor = typeof(Console).GetProperty(nameof(Console.ForegroundColor))!; - PropertyInfo _BackgroundColor = typeof(Console).GetProperty(nameof(Console.BackgroundColor))!; - PropertyInfo _IsOutputRedirected = typeof(Console).GetProperty(nameof(Console.IsOutputRedirected))!; - PropertyInfo _KeyAvailable = typeof(Console).GetProperty(nameof(Console.KeyAvailable))!; - PropertyInfo _LargestWindowHeight = typeof(Console).GetProperty(nameof(Console.LargestWindowHeight))!; - PropertyInfo _Title = typeof(Console).GetProperty(nameof(Console.Title))!; - PropertyInfo _WindowHeight = typeof(Console).GetProperty(nameof(Console.WindowHeight))!; - PropertyInfo _WindowWidth = typeof(Console).GetProperty(nameof(Console.WindowWidth))!; - PropertyInfo _CursorVisible = typeof(Console).GetProperty(nameof(Console.CursorVisible))!; - PropertyInfo _BufferWidth = typeof(Console).GetProperty(nameof(Console.BufferWidth))!; - PropertyInfo _BufferHeight = typeof(Console).GetProperty(nameof(Console.BufferHeight))!; - - public ConsoleColor ForegroundColor { get => _ForegroundColor?.GetValue(null) as ConsoleColor? ?? ConsoleColor.White; set => _ForegroundColor?.SetValue(null,value); } - public ConsoleColor BackgroundColor { get => _BackgroundColor?.GetValue(null) as ConsoleColor? ?? ConsoleColor.Black; set => _BackgroundColor?.SetValue(null, value); } - public bool IsOutputRedirected => _IsOutputRedirected?.GetValue(null) as bool? ?? false; - public bool KeyAvailable => _KeyAvailable?.GetValue(null) as bool? ?? false; - public int LargestWindowHeight => _LargestWindowHeight?.GetValue(null) as int? ?? 0; - public string Title { get => _Title?.GetValue(null) as string ?? string.Empty; set => _Title?.SetValue(null, value); } - public int WindowHeight { get => _WindowHeight?.GetValue(null) as int? ?? 0; set => _WindowHeight?.SetValue(null, value); } - public int WindowWidth { get => _WindowWidth?.GetValue(null) as int? ?? 0; set => _WindowWidth?.SetValue(null, value); } - public bool CursorVisible { get => _CursorVisible?.GetValue(null) as bool? ?? false; set => _CursorVisible?.SetValue(null, value); } - public int BufferWidth => _BufferWidth?.GetValue(null) as int? ?? 0; - public int BufferHeight => _BufferHeight?.GetValue(null) as int? ?? 0; - - - public void Beep(int freq, int len) => _beep?.Invoke(null, [freq, len]); - public void Clear() => _clear?.Invoke(null, []); + protected MethodInfo _ReadKey = typeof(Console).GetMethod(nameof(Console.ReadKey), [])!; + protected MethodInfo _Readline = typeof(Console).GetMethod(nameof(Console.ReadLine), [])!; + protected MethodInfo _setCursorPosition = typeof(Console).GetMethod(nameof(Console.SetCursorPosition), [typeof(int), typeof(int)])!; + protected MethodInfo _writeCh = typeof(Console).GetMethod(nameof(Console.Write), [typeof(char)])!; + protected MethodInfo _writeS = typeof(Console).GetMethod(nameof(Console.Write), [typeof(string)])!; + protected MethodInfo _clear = typeof(Console).GetMethod(nameof(Console.Clear), [])!; + protected MethodInfo _resetColor = typeof(Console).GetMethod(nameof(Console.ResetColor), [])!; + + protected PropertyInfo _ForegroundColor = typeof(Console).GetProperty(nameof(Console.ForegroundColor))!; + protected PropertyInfo _BackgroundColor = typeof(Console).GetProperty(nameof(Console.BackgroundColor))!; + protected PropertyInfo _IsOutputRedirected = typeof(Console).GetProperty(nameof(Console.IsOutputRedirected))!; + protected PropertyInfo _KeyAvailable = typeof(Console).GetProperty(nameof(Console.KeyAvailable))!; + protected PropertyInfo _LargestWindowHeight = typeof(Console).GetProperty(nameof(Console.LargestWindowHeight))!; + protected PropertyInfo _Title = typeof(Console).GetProperty(nameof(Console.Title))!; + protected PropertyInfo _WindowHeight = typeof(Console).GetProperty(nameof(Console.WindowHeight))!; + protected PropertyInfo _WindowWidth = typeof(Console).GetProperty(nameof(Console.WindowWidth))!; + protected PropertyInfo _CursorVisible = typeof(Console).GetProperty(nameof(Console.CursorVisible))!; + protected PropertyInfo _BufferWidth = typeof(Console).GetProperty(nameof(Console.BufferWidth))!; + protected PropertyInfo _BufferHeight = typeof(Console).GetProperty(nameof(Console.BufferHeight))!; + + protected object? instance = default; + public ConsoleColor ForegroundColor { get => _ForegroundColor?.GetValue(instance) as ConsoleColor? ?? ConsoleColor.White; set => _ForegroundColor?.SetValue(instance,value); } + public ConsoleColor BackgroundColor { get => _BackgroundColor?.GetValue(instance) as ConsoleColor? ?? ConsoleColor.Black; set => _BackgroundColor?.SetValue(instance, value); } + public bool IsOutputRedirected => _IsOutputRedirected?.GetValue(instance) as bool? ?? false; + public bool KeyAvailable => _KeyAvailable?.GetValue(instance) as bool? ?? false; + public int LargestWindowHeight => _LargestWindowHeight?.GetValue(instance) as int? ?? 0; + public string Title { get => _Title?.GetValue(instance) as string ?? string.Empty; set => _Title?.SetValue(instance, value); } + public int WindowHeight { get => _WindowHeight?.GetValue(instance) as int? ?? 0; set => _WindowHeight?.SetValue(instance, value); } + public int WindowWidth { get => _WindowWidth?.GetValue(instance) as int? ?? 0; set => _WindowWidth?.SetValue(instance, value); } + public bool CursorVisible { get => _CursorVisible?.GetValue(instance) as bool? ?? false; set => _CursorVisible?.SetValue(instance, value); } + public int BufferWidth => _BufferWidth?.GetValue(instance) as int? ?? 0; + public int BufferHeight => _BufferHeight?.GetValue(instance) as int? ?? 0; + + + public void Beep(int freq, int len) => _beep?.Invoke(instance, [freq, len]); + public void Clear() => _clear?.Invoke(instance, []); #if NET5_0_OR_GREATER - public (int Left, int Top) GetCursorPosition() => _GetCursorPosition?.Invoke(null, []) as (int, int)? ?? (0, 0); + public (int Left, int Top) GetCursorPosition() => _GetCursorPosition?.Invoke(instance, []) as (int, int)? ?? (0, 0); #else - public (int Left, int Top) GetCursorPosition() => (_CursorLeft?.Invoke(null, []) as int? ?? 0, _CursorTop?.Invoke(null, []) as int? ?? 0); + public (int Left, int Top) GetCursorPosition() => (_CursorLeft?.Invoke(instance, []) as int? ?? 0, _CursorTop?.Invoke(instance, []) as int? ?? 0); #endif - public ConsoleKeyInfo? ReadKey() => _ReadKey?.Invoke(null, []) as ConsoleKeyInfo?; - public string ReadLine() => _Readline?.Invoke(null, [])?.ToString() ?? string.Empty; - public void SetCursorPosition(int left, int top) => _setCursorPosition?.Invoke(null, [left, top]); - public void Write(char ch) => _writeCh?.Invoke(null, [ch]); - public void Write(string? st) => _writeS?.Invoke(null, [st]); - public void WriteLine(string? v) => _writeLineS?.Invoke(null, [v]); + public ConsoleKeyInfo? ReadKey() => _ReadKey?.Invoke(instance, []) as ConsoleKeyInfo?; + public string ReadLine() => _Readline?.Invoke(instance, [])?.ToString() ?? string.Empty; + + public void ResetColor() => _resetColor?.Invoke(instance, []); + + public void SetCursorPosition(int left, int top) => _setCursorPosition?.Invoke(instance, [left, top]); + public void Write(char ch) => _writeCh?.Invoke(instance, [ch]); + public void Write(string? st) => _writeS?.Invoke(instance, [st]); + public void WriteLine(string? v) => _writeLineS?.Invoke(instance, [v]); } diff --git a/CSharpBible/CSharpBible.sln b/CSharpBible/CSharpBible.sln index 2eaf51596..7b314ff76 100644 --- a/CSharpBible/CSharpBible.sln +++ b/CSharpBible/CSharpBible.sln @@ -427,7 +427,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MVVM_00_TemplateTests", "MV EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MVVM_06_Converters_4_net", "MVVM_Tutorial\MVVM_06_Converters_4\MVVM_06_Converters_4_net.csproj", "{70AD3FCB-F529-4E08-BE39-E56C940EA114}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MVVM_16_Usercontrol1_net", "MVVM_Tutorial\MVVM_16_Usercontrol1\MVVM_16_Usercontrol1_net.csproj", "{CDC8B1F7-3C94-4686-9EE0-6841231E6144}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MVVM_16_Usercontrol1_net", "MVVM_Tutorial\MVVM_16_Usercontrol1\MVVM_16_UserControl1_net.csproj", "{CDC8B1F7-3C94-4686-9EE0-6841231E6144}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Simulation", "Simulation", "{0DF8EC71-8008-41CF-9A87-946604FBD24D}" ProjectSection(SolutionItems) = preProject diff --git a/CSharpBible/ConsoleApps/TestConsoleTests/TestConsoleTests.cs b/CSharpBible/ConsoleApps/TestConsoleTests/TestConsoleTests.cs index cea8ad438..0005b7e9c 100644 --- a/CSharpBible/ConsoleApps/TestConsoleTests/TestConsoleTests.cs +++ b/CSharpBible/ConsoleApps/TestConsoleTests/TestConsoleTests.cs @@ -144,7 +144,7 @@ public void ReadKeyTest() /// /// Defines the test method SetCursorPositionTest. /// - [DataTestMethod()] + [TestMethod()] [DataRow("0,0",0,0)] [DataRow("0,1", 0, 1)] [DataRow("1,0", 1, 0)] diff --git a/CSharpBible/Games/Arkanoid.Base/Arkanoid.Base.csproj b/CSharpBible/Games/Arkanoid.Base/Arkanoid.Base.csproj index 28ead3f4a..1705ad3c5 100644 --- a/CSharpBible/Games/Arkanoid.Base/Arkanoid.Base.csproj +++ b/CSharpBible/Games/Arkanoid.Base/Arkanoid.Base.csproj @@ -15,5 +15,10 @@ $(TargetFrameworks);net10.0 + + + + + diff --git a/CSharpBible/Games/Arkanoid.Base/GameEngine.cs b/CSharpBible/Games/Arkanoid.Base/GameEngine.cs index d728522cf..ac6cb6a0c 100644 --- a/CSharpBible/Games/Arkanoid.Base/GameEngine.cs +++ b/CSharpBible/Games/Arkanoid.Base/GameEngine.cs @@ -4,15 +4,42 @@ namespace Arkanoid.Base; +/// +/// Provides the core game loop mechanics for the Arkanoid-style game, +/// including state updates, collision handling, and level setup. +/// +/// +/// This engine operates on a simple fixed-field coordinate system and updates +/// the in-place. It is intentionally lightweight and +/// deterministic for predictable gameplay behavior. +/// public class GameEngine { + /// + /// Gets the current mutable game state, including ball, paddle, bricks, score, and lives. + /// public GameState State { get; } = new(); + /// + /// Initializes a new instance of the class + /// and creates the default level layout. + /// public GameEngine() { CreateDefaultLevel(); } + /// + /// Moves the paddle horizontally according to player input and elapsed time. + /// + /// + /// The horizontal input direction, typically in the range [-1, 1], + /// where negative values move left and positive values move right. + /// + /// The elapsed time since the last update, in seconds. + /// + /// The paddle position is clamped so it cannot leave the horizontal bounds of the field. + /// public void MovePaddle(float direction, float deltaTime) { var dx = State.Paddle.Speed * direction * deltaTime; @@ -20,6 +47,14 @@ public void MovePaddle(float direction, float deltaTime) State.Paddle.Position = new Vector2(newX, State.Paddle.Position.Y); } + /// + /// Advances the simulation by the specified time step. + /// + /// The elapsed time since the last update, in seconds. + /// + /// If the game is over, no further updates are performed. + /// This method updates the ball position and resolves collisions. + /// public void Update(float deltaTime) { if (State.IsGameOver) return; @@ -31,6 +66,16 @@ public void Update(float deltaTime) HandleCollisions(); } + /// + /// Detects and resolves collisions between the ball and walls, paddle, and bricks. + /// + /// + /// - Wall collisions reflect velocity components as needed.
+ /// - Falling below the field reduces lives and resets the ball and paddle.
+ /// - Paddle collisions reflect the ball upward when moving downward.
+ /// - Brick collisions reflect vertical velocity and reduce hit points for breakable bricks.
+ /// - If all bricks are destroyed, the game ends. + ///
private void HandleCollisions() { var b = State.Ball; @@ -86,6 +131,12 @@ private void HandleCollisions() State.IsGameOver = true; } + /// + /// Resets the paddle and ball to their default starting positions and velocity. + /// + /// + /// This is invoked after losing a life or when initializing a level. + /// private void ResetBallAndPaddle() { State.Paddle.Position = new Vector2(State.FieldWidth / 2 - State.Paddle.Width / 2, State.FieldHeight - 2); @@ -93,6 +144,13 @@ private void ResetBallAndPaddle() State.Ball.Velocity = new Vector2(15, -20); } + /// + /// Creates the default level layout consisting of a rectangular grid of bricks. + /// + /// + /// The layout uses a fixed number of rows and columns and distributes bricks evenly + /// across the field width. All bricks are initialized as breakable with one hit point. + /// private void CreateDefaultLevel() { State.Bricks.Clear(); diff --git a/CSharpBible/Games/Arkanoid.Base/Models/Ball.cs b/CSharpBible/Games/Arkanoid.Base/Models/Ball.cs new file mode 100644 index 000000000..fef28322d --- /dev/null +++ b/CSharpBible/Games/Arkanoid.Base/Models/Ball.cs @@ -0,0 +1,34 @@ +namespace Arkanoid.Base.Models; +/// +/// The ball object in the Arkanoid game. +/// +/// +public class Ball : IGameObject +{ + /// + /// Gets or sets the current world-space position of the ball in game units. + /// + /// + /// The position represents the center of the ball and is typically updated each frame + /// based on and elapsed time. + /// + public Vector2 Position { get; set; } = new(10, 10); + + /// + /// Gets or sets the linear velocity of the ball in game units per second. + /// + /// + /// Positive X moves the ball to the right, and positive Y moves it upward, assuming a + /// conventional Cartesian coordinate system. + /// + public Vector2 Velocity { get; set; } = new(10, -10); // units per second + + /// + /// Gets or sets the radius of the ball in game units. + /// + /// + /// The radius is used for collision detection and rendering. The ball's diameter is + /// 2 * Radius. + /// + public float Radius { get; set; } = 0.5f; +} diff --git a/CSharpBible/Games/Arkanoid.Base/Models/Brick.cs b/CSharpBible/Games/Arkanoid.Base/Models/Brick.cs new file mode 100644 index 000000000..4dcd6b7a1 --- /dev/null +++ b/CSharpBible/Games/Arkanoid.Base/Models/Brick.cs @@ -0,0 +1,51 @@ +namespace Arkanoid.Base.Models; + +/// +/// Represents a single brick in the game arena, including its position, size, type, +/// durability, and destruction state. +/// +/// +/// A brick can be breakable or unbreakable depending on its . The +/// value defines how many hits are required to destroy it. +/// The property reflects whether the brick should be +/// considered removed from play. +/// +public class Brick : IGameObject +{ + /// + /// Gets or sets the top-left position of the brick in world coordinates. + /// + public Vector2 Position { get; set; } = new(0, 0); + + /// + /// Gets or sets the width of the brick in world units. + /// + public float Width { get; set; } = 3f; + + /// + /// Gets or sets the height of the brick in world units. + /// + public float Height { get; set; } = 1f; + + /// + /// Gets or sets the brick's type, which determines its behavior (e.g., breakable or unbreakable). + /// + public BrickType Type { get; set; } + + /// + /// Gets or sets the current hit points of the brick. + /// + /// + /// When this value reaches zero or below, the brick is considered destroyed + /// unless it is of type . + /// + public int HitPoints { get; set; } = 1; + + /// + /// Gets a value indicating whether the brick is destroyed and should be removed from play. + /// + /// + /// Unbreakable bricks are never destroyed even if is zero or negative. + /// + public bool IsDestroyed => HitPoints <= 0 && Type != BrickType.Unbreakable; +} \ No newline at end of file diff --git a/CSharpBible/Games/Arkanoid.Base/Models/BrickType.cs b/CSharpBible/Games/Arkanoid.Base/Models/BrickType.cs new file mode 100644 index 000000000..f7f21c797 --- /dev/null +++ b/CSharpBible/Games/Arkanoid.Base/Models/BrickType.cs @@ -0,0 +1,23 @@ +namespace Arkanoid.Base.Models; + +/// +/// Defines the available brick categories used by the game logic, rendering, and collision handling +/// to determine durability and behavior when hit by a ball. +/// +public enum BrickType +{ + /// + /// A standard brick that is destroyed after a single hit. + /// + Normal, + + /// + /// A reinforced brick that requires multiple hits to break. + /// + Strong, + + /// + /// An indestructible brick that never breaks when hit. + /// + Unbreakable +} diff --git a/CSharpBible/Games/Arkanoid.Base/Models/GameObjects.cs b/CSharpBible/Games/Arkanoid.Base/Models/GameObjects.cs deleted file mode 100644 index e28600a7e..000000000 --- a/CSharpBible/Games/Arkanoid.Base/Models/GameObjects.cs +++ /dev/null @@ -1,48 +0,0 @@ -using System.Collections.Generic; - -namespace Arkanoid.Base.Models; - -public enum BrickType -{ - Normal, - Strong, - Unbreakable -} - -public record Vector2(float X, float Y); - -public class Paddle -{ - public Vector2 Position { get; set; } = new(10, 20); - public float Width { get; set; } = 6f; - public float Speed { get; set; } = 25f; // units per second -} - -public class Ball -{ - public Vector2 Position { get; set; } = new(10, 10); - public Vector2 Velocity { get; set; } = new(10, -10); // units per second - public float Radius { get; set; } = 0.5f; -} - -public class Brick -{ - public Vector2 Position { get; set; } - public float Width { get; set; } = 3f; - public float Height { get; set; } = 1f; - public BrickType Type { get; set; } - public int HitPoints { get; set; } = 1; - public bool IsDestroyed => HitPoints <= 0 && Type != BrickType.Unbreakable; -} - -public class GameState -{ - public Paddle Paddle { get; } = new(); - public Ball Ball { get; } = new(); - public List Bricks { get; } = new(); - public int Score { get; set; } - public int Lives { get; set; } = 3; - public float FieldWidth { get; set; } = 80; - public float FieldHeight { get; set; } = 40; - public bool IsGameOver { get; set; } -} diff --git a/CSharpBible/Games/Arkanoid.Base/Models/GameState.cs b/CSharpBible/Games/Arkanoid.Base/Models/GameState.cs new file mode 100644 index 000000000..0ee604c9f --- /dev/null +++ b/CSharpBible/Games/Arkanoid.Base/Models/GameState.cs @@ -0,0 +1,83 @@ +namespace Arkanoid.Base.Models; + +/// +/// Represents the complete mutable state of an Arkanoid game session, including +/// player control, ball physics, level geometry, scoring, and terminal flags. +/// +/// +/// This type is intended to be the single source of truth for the game loop, +/// allowing rendering and simulation to read and update a unified model. +/// +public class GameState +{ + /// + /// Gets the player's paddle, which is responsible for reflecting the ball. + /// + /// + /// The paddle position and size are typically updated by player input and + /// used during collision checks with the ball. + /// + public Paddle Paddle { get; } = new(); + + /// + /// Gets the active ball instance used for movement, collisions, and scoring. + /// + /// + /// The ball's position and velocity are advanced each tick of the game loop + /// and are evaluated against the field bounds, paddle, and bricks. + /// + public Ball Ball { get; } = new(); + + /// + /// Gets the collection of bricks currently present in the playfield. + /// + /// + /// Bricks are typically removed when hit by the ball and may contribute + /// to the score or trigger power-ups in extended implementations. + /// + public List Bricks { get; } = new(); + + /// + /// Gets or sets the player's current score. + /// + /// + /// This value is generally increased when the ball destroys bricks or + /// completes objectives, and may be used for high score tracking. + /// + public int Score { get; set; } + + /// + /// Gets or sets the number of remaining lives. + /// + /// + /// A life is typically lost when the ball exits the bottom boundary of the field. + /// When this value reaches zero, the game is considered over. + /// + public int Lives { get; set; } = 3; + + /// + /// Gets or sets the width of the playable field in game units. + /// + /// + /// Used to clamp paddle movement and to reflect the ball from the left and right walls. + /// + public float FieldWidth { get; set; } = 80; + + /// + /// Gets or sets the height of the playable field in game units. + /// + /// + /// Used to determine the top boundary for ball reflection and the bottom + /// boundary for life loss. + /// + public float FieldHeight { get; set; } = 40; + + /// + /// Gets or sets a value indicating whether the game has ended. + /// + /// + /// This flag is typically set when reaches zero or when + /// all bricks have been cleared, depending on game rules. + /// + public bool IsGameOver { get; set; } +} diff --git a/CSharpBible/Games/Arkanoid.Base/Models/IGameObject.cs b/CSharpBible/Games/Arkanoid.Base/Models/IGameObject.cs new file mode 100644 index 000000000..e9e51160e --- /dev/null +++ b/CSharpBible/Games/Arkanoid.Base/Models/IGameObject.cs @@ -0,0 +1,14 @@ +namespace Arkanoid.Base.Models; +/// +/// Interface IGameObject +/// +public interface IGameObject +{ + /// + /// Gets or sets the position. + /// + /// + /// The position. + /// + Vector2 Position { get; set; } +} \ No newline at end of file diff --git a/CSharpBible/Games/Arkanoid.Base/Models/Paddle.cs b/CSharpBible/Games/Arkanoid.Base/Models/Paddle.cs new file mode 100644 index 000000000..60ee3568d --- /dev/null +++ b/CSharpBible/Games/Arkanoid.Base/Models/Paddle.cs @@ -0,0 +1,38 @@ +using System.Collections.Generic; + +namespace Arkanoid.Base.Models; + +/// +/// Represents the player-controlled paddle used to deflect the ball in the game. +/// +/// +/// The paddle is modeled as a horizontal segment positioned in world coordinates. +/// Movement is typically constrained to the horizontal axis by input handling elsewhere. +/// +public class Paddle : IGameObject +{ + /// + /// Gets or sets the world-space position of the paddle's reference point. + /// + /// + /// The exact interpretation of the reference point (e.g., center or left edge) + /// is defined by the rendering and collision systems that consume this model. + /// + public Vector2 Position { get; set; } = new(10, 20); + + /// + /// Gets or sets the paddle width expressed in world units. + /// + /// + /// This value is used for collision checks and rendering to determine the paddle's span. + /// + public float Width { get; set; } = 6f; + + /// + /// Gets or sets the movement speed of the paddle in world units per second. + /// + /// + /// Higher values allow faster horizontal movement when input is applied. + /// + public float Speed { get; set; } = 25f; // units per second +} diff --git a/CSharpBible/Games/Arkanoid.Base/Models/Vector2.cs b/CSharpBible/Games/Arkanoid.Base/Models/Vector2.cs new file mode 100644 index 000000000..278f9d64a --- /dev/null +++ b/CSharpBible/Games/Arkanoid.Base/Models/Vector2.cs @@ -0,0 +1,14 @@ +namespace Arkanoid.Base.Models; + +/// +/// Represents a two-dimensional vector with single-precision floating-point components, +/// commonly used to describe positions, directions, or sizes in 2D space. +/// +/// +/// The horizontal component of the vector, where positive values typically indicate movement or offset to the right. +/// +/// +/// The vertical component of the vector, where positive values typically indicate movement or offset downward in screen space, +/// depending on the coordinate system used by the game. +/// +public record Vector2(float X, float Y); \ No newline at end of file diff --git a/CSharpBible/Games/Arkanoid.Cons/Arkanoid.Cons.csproj b/CSharpBible/Games/Arkanoid.Cons/Arkanoid.Cons.csproj index 8118714f1..aeb6601b0 100644 --- a/CSharpBible/Games/Arkanoid.Cons/Arkanoid.Cons.csproj +++ b/CSharpBible/Games/Arkanoid.Cons/Arkanoid.Cons.csproj @@ -15,6 +15,11 @@ $(TargetFrameworks);net10.0 + + + + + diff --git a/CSharpBible/Games/BoxFlight/ViewModels/BoxFlightViewModel.cs b/CSharpBible/Games/BoxFlight/ViewModels/BoxFlightViewModel.cs index c729f0bac..68b81a521 100644 --- a/CSharpBible/Games/BoxFlight/ViewModels/BoxFlightViewModel.cs +++ b/CSharpBible/Games/BoxFlight/ViewModels/BoxFlightViewModel.cs @@ -36,7 +36,7 @@ public BoxFlightViewModel(IGameWorld world) { _world = world; - int width = 640, height = 360; + int width = 1280, height = 720; Frame = new WriteableBitmap(width, height, 96, 96, PixelFormats.Bgra32, null); MiniMap = new WriteableBitmap(400, 400, 96, 96, PixelFormats.Bgra32, null); _render = new RenderEntry[width]; @@ -128,7 +128,7 @@ private void DrawRenderEntries(int bd2) for (int x = 0; x < _render.Length; x++) { var re = _render[x]; - if (re.Height > re.Shad / 2) + if (re.Shad !=0 && re.Height > re.Shad / 2) DrawVLine(buffer, stride, x, bd2 + re.Shad, bd2 + re.Shad / 2, Colors.Black); int c1 = Math.Clamp(re.Light, 0, 255); diff --git a/CSharpBible/Games/BoxFlight/World/GameWorld.cs b/CSharpBible/Games/BoxFlight/World/GameWorld.cs index d93f45ce2..9b352a558 100644 --- a/CSharpBible/Games/BoxFlight/World/GameWorld.cs +++ b/CSharpBible/Games/BoxFlight/World/GameWorld.cs @@ -71,17 +71,15 @@ public void Step(int time, bool stereo, int scrollOffset, int focusX, int maxHei var lCv2 = new Vector(lCv1.Y, -lCv1.X); _cMove = _cPoint - cMoveOld; + _cPoint.X -= Math.Truncate(_cPoint.X / 400.0) * 400.0; _cPoint.Y -= Math.Truncate(_cPoint.Y / 400.0) * 400.0; - var sPnt = _cPoint; - if (stereo) { _cPoint.X += _cView.Y * 0.4; _cPoint.Y += -_cView.X * 0.4; } - else { _cPoint.X += -_cView.Y * 0.4; _cPoint.Y += _cView.X * 0.4; } - sPnt.X += _cView.X; sPnt.Y += _cView.Y; foreach (var o in Objects) { - o.Visible = false; o.Hit = false; + o.Visible = false; + o.Hit = false; if (o.Size <= 0) continue; var vp = new Vector(o.Pos.X, o.Pos.Y) + (Vector)_cPoint + new Vector(400, 400); vp -= new Vector(Math.Floor(vp.X / 400.0) * 400.0, Math.Floor(vp.Y / 400.0) * 400.0); @@ -95,20 +93,38 @@ public void Step(int time, bool stereo, int scrollOffset, int focusX, int maxHei o.Visible = vis; } + int half = render.Length / 2; int hrc2 = half / 2; int obj = -1; - for (int j = 0; j < render.Length; j++) + Parallel.For (0,render.Length, (j)=> { + var sPnt = _cPoint; double s, c; - if (j <= half) { s = Math.Sin((hrc2 - j) * 0.6 / hrc2); c = Math.Cos((hrc2 - j) * 0.6 / hrc2); } - else { s = Math.Sin((-j + hrc2 * 3) * 0.6 / hrc2); c = Math.Cos((-j + hrc2 * 3) * 0.6 / hrc2); } + if (stereo) + if (j <= half) + { + sPnt.X -= _cView.Y * 0.4; + sPnt.Y += _cView.X * 0.4; + s = Math.Sin((hrc2 - j) * 0.6 / hrc2); + c = Math.Cos((hrc2 - j) * 0.6 / hrc2); + } + else + { + sPnt.X += _cView.Y * 0.4; + sPnt.Y -= _cView.X * 0.4; + s = Math.Sin((-j + hrc2 * 3) * 0.6 / hrc2); + c = Math.Cos((-j + hrc2 * 3) * 0.6 / hrc2); + } + else + { + s = Math.Sin((half - j) * 0.6 / half); + c = Math.Cos((half - j) * 0.6 / half); + } var renDir = new Vector(_cView.X * c + _cView.Y * s, -_cView.X * s + _cView.Y * c); render[j] = Trace(maxHeight, sPnt, obj, renDir, j == focusX); - } + }); - if (stereo) { _cPoint.X += -_cView.Y * 0.8; _cPoint.Y += _cView.X * 0.8; } - else { _cPoint.X += _cView.Y * 0.8; _cPoint.Y += -_cView.X * 0.8; } cPoint2 = _cPoint2; cPoint3 = _cPoint3; } @@ -118,10 +134,10 @@ private RenderEntry Trace(int maxHeight, Point sPnt, int obj, Vector renDir, boo float rDistQ, r; double rDist; double rr = 0; int hObj = obj; var entry = new RenderEntry { Oo1 = -1, Oo2 = -1, Light = 0, Height = 0, Light2 = 0, Height2 = 0, Shad = 0 }; - if (obj >= 0 && Objects[obj].HitTest(_cPoint, renDir, out rDistQ, out r) && rDistQ > 2 && rDistQ < 300) { rDist = rDistQ; rr = r; } + if (obj >= 0 && Objects[obj].HitTest(sPnt, renDir, out rDistQ, out r) && rDistQ > 2 && rDistQ < 300) { rDist = rDistQ; rr = r; } else { obj = -1; rDist = 300.0; } - ObjHit(_cPoint, renDir, -1, ref obj, ref rDist, ref rr); + ObjHit(sPnt, renDir, -1, ref obj, ref rDist, ref rr); if (obj >= 0) { var o = Objects[obj]; @@ -155,7 +171,8 @@ private RenderEntry Trace(int maxHeight, Point sPnt, int obj, Vector renDir, boo int lsobj = hObj; double shDist = 300.0; double shRr = 0.0; ObjHit(sPnt, renDir, -1, ref lsobj, ref shDist, ref shRr); - if (lsobj >= 0) entry.Shad = (int)(maxHeight / (shDist + 1.0)); else entry.Shad = 0; + // if (lsobj >= 0) entry.Shad = (int)(maxHeight / (shDist + 1.0)); else + entry.Shad = 0; return entry; } diff --git a/CSharpBible/Games/DetectiveGame.Console/ViewModels/GameViewModel.cs b/CSharpBible/Games/DetectiveGame.Console/ViewModels/GameViewModel.cs index 68246ebdb..0d211d610 100644 --- a/CSharpBible/Games/DetectiveGame.Console/ViewModels/GameViewModel.cs +++ b/CSharpBible/Games/DetectiveGame.Console/ViewModels/GameViewModel.cs @@ -26,7 +26,7 @@ public partial class GameViewModel : ObservableObject, IGameViewModel [ObservableProperty] private string _currentTitle = "Detektivspiel"; - public bool CanInteract => _state != null && !_state.Finished; + public bool CanInteract => State != null && !State.Finished; public Action DisplayHelp { get ; set; } @@ -42,7 +42,8 @@ private void Start() Players.Clear(); History.Clear(); State = ((IGameSetup)_service).CreateNew(new[] { "Alice", "Bob", "Carol" }); - foreach (var p in _state.Players) + if (State != null) + foreach (var p in State.Players) Players.Add(p.Name); History.Add("Spiel gestartet"); UpdateTitle(); @@ -51,22 +52,22 @@ private void Start() [RelayCommand(CanExecute = nameof(CanInteract))] private void Suggest() { - if (_state == null) return; - var cur = State.Players[_state.CurrentPlayerIndex]; - var person = GameData.Persons.First(); - var weapon = GameData.Weapons.First(); - var room = GameData.Rooms.First(); - var sug = _service.MakeSuggestion(_state, cur.Id, person, weapon, room); - History.Add($"V: {cur.Name}: {person.Name}/{weapon.Name}/{room.Name} -> {(sug.RefutingPlayerId is int id ? $"von {_state.Players.First(p=>p.Id==id).Name}" : "Keiner")}"); + if (State == null) return; + var cur = State.Players[State.CurrentPlayerIndex]; + var person = GameData.Persons[0]; + var weapon = GameData.Weapons[0]; + var room = GameData.Rooms[0]; + var sug = _service.MakeSuggestion(State, cur.Id, person, weapon, room); + History.Add($"V: {cur.Name}: {person.Name}/{weapon.Name}/{room.Name} -> {(sug.RefutingPlayerId is int id ? $"von {State.Players.First(p=>p.Id==id).Name}" : "Keiner")}"); UpdateTitle(); } [RelayCommand(CanExecute = nameof(CanInteract))] private void Accuse() { - if (_state == null) return; - var cur = State.Players[_state.CurrentPlayerIndex]; - var ok = _service.MakeAccusation(_state, cur.Id, GameData.Persons.First(), GameData.Weapons.First(), GameData.Rooms.First()); + if (State == null) return; + var cur = State.Players[State.CurrentPlayerIndex]; + var ok = _service.MakeAccusation(State, cur.Id, GameData.Persons.First(), GameData.Weapons.First(), GameData.Rooms.First()); History.Add(ok ? $"{cur.Name} gewinnt" : $"{cur.Name} falsch (inaktiv)"); UpdateTitle(); } @@ -90,9 +91,9 @@ private void UpdateTitle() if (State == null) CurrentTitle = "Detektivspiel"; else if (State.Finished) - CurrentTitle = $"Ende – Sieger {_state.WinnerPlayerId}"; + CurrentTitle = $"Ende – Sieger {State.WinnerPlayerId}"; else - CurrentTitle = $"Zug: {_state.Players[_state.CurrentPlayerIndex].Name}"; + CurrentTitle = $"Zug: {State.Players[State.CurrentPlayerIndex].Name}"; } } diff --git a/CSharpBible/Games/DetectiveGame.Console/Views/SuggestionDialog.cs b/CSharpBible/Games/DetectiveGame.Console/Views/SuggestionDialog.cs index da84771cc..89d796b9f 100644 --- a/CSharpBible/Games/DetectiveGame.Console/Views/SuggestionDialog.cs +++ b/CSharpBible/Games/DetectiveGame.Console/Views/SuggestionDialog.cs @@ -104,6 +104,6 @@ public void Hide() public void Show() { Visible = true; - (Parent as IGroupControl).BringToFront(this); + (Parent as IGroupControl)?.BringToFront(this); } } diff --git a/CSharpBible/Games/Directory.Packages.props b/CSharpBible/Games/Directory.Packages.props index eb83fa4d5..56c7ac5db 100644 --- a/CSharpBible/Games/Directory.Packages.props +++ b/CSharpBible/Games/Directory.Packages.props @@ -1,7 +1,9 @@ - + - - + + + + \ No newline at end of file diff --git a/CSharpBible/Games/Galaxia_Base/Models/CorActions/DoubleJump.cs b/CSharpBible/Games/Galaxia_Base/Models/CorActions/DoubleJump.cs index c095cbafe..7f154a09c 100644 --- a/CSharpBible/Games/Galaxia_Base/Models/CorActions/DoubleJump.cs +++ b/CSharpBible/Games/Galaxia_Base/Models/CorActions/DoubleJump.cs @@ -16,7 +16,7 @@ public class DoubleJump : JumpAction, ICorAction /// /// Das Ziel-Sternensystem für den Hyperjump. /// - public IStarsystem TargetStarsystem { get; } + public IStarsystem? TargetStarsystem { get; } /// /// Erstellt eine neue DoubleJump-Aktion. @@ -24,7 +24,7 @@ public class DoubleJump : JumpAction, ICorAction /// Die ausführende Corporation. /// Die springende Flotte. /// Das Ziel-Sternensystem. - public DoubleJump(ICorporation corporation, IFleet fleet1, IFleet fleet2, IStarsystem targetStarsystem):base(corporation,fleet1) + public DoubleJump(ICorporation corporation, IFleet fleet1, IFleet fleet2, IStarsystem? targetStarsystem):base(corporation,fleet1) { Fleet2 = fleet2; TargetStarsystem = targetStarsystem; @@ -37,7 +37,7 @@ public DoubleJump(ICorporation corporation, IFleet fleet1, IFleet fleet2, IStars public override bool Execute() { // Überprüfe, ob die Flotte zur Corporation gehört und sich im Hyperspace befindet - if (Fleet.Owner != Corporation || Fleet.Container is not IHyperSlot hs ) + if (Fleet?.Owner != Corporation || Fleet.Container is not IHyperSlot hs ) return false; // Überprüfe, ob die Flotte zur Corporation gehört und sich im Hyperspace befindet @@ -58,7 +58,7 @@ public override bool Execute() // Die Flotte verlässt den HyperSlot und wird dem Zielsystem zugewiesen // Dies kann je nach Implementierung variieren TargetStarsystem.Sector.SetFleet(Fleet); - TargetStarsystem.Sector.Fleet.Join(Fleet2); + TargetStarsystem.Sector.Fleet?.Join(Fleet2); TargetStarsystem.SetFleet(Fleet); return true; } diff --git a/CSharpBible/Games/Galaxia_Base/Models/CorActions/EmbarkFleet.cs b/CSharpBible/Games/Galaxia_Base/Models/CorActions/EmbarkFleet.cs index 11ce31eff..8a3321cbe 100644 --- a/CSharpBible/Games/Galaxia_Base/Models/CorActions/EmbarkFleet.cs +++ b/CSharpBible/Games/Galaxia_Base/Models/CorActions/EmbarkFleet.cs @@ -25,7 +25,7 @@ public class EmbarkFleet : ICorAction /// /// Das Sternensystem, aus dem die Flotte startet. /// - public IStarsystem SourceStarsystem { get; } + public IStarsystem? SourceStarsystem { get; } /// /// Erstellt eine neue EmbarkFleet-Aktion. @@ -33,7 +33,7 @@ public class EmbarkFleet : ICorAction /// Die ausführende Corporation. /// Die einzuschiffende Flotte. /// Das Start-Sternensystem. - public EmbarkFleet(ICorporation corporation, IFleet fleet, IStarsystem sourceStarsystem,float fleetSize =0f) + public EmbarkFleet(ICorporation corporation, IFleet? fleet, IStarsystem? sourceStarsystem,float fleetSize =0f) { Corporation = corporation; Fleet = fleet; @@ -52,13 +52,13 @@ public bool Execute() return false; // Versuche, die Flotte ins Hyperspace-System einzuschiffen - if ((FleetSize > 1f) && (Fleet.Size > FleetSize)) + if ((FleetSize > 1f) && (Fleet!.Size > FleetSize)) { // Nicht genug Platz in den HyperSlots - return Corporation.hyperspace.Embark(Fleet.Split(FleetSize)); + return Corporation.hyperspace.Embark(Fleet.Split(FleetSize)!); } else - return Corporation.hyperspace.Embark(Fleet); + return Corporation.hyperspace.Embark(Fleet!); } } } \ No newline at end of file diff --git a/CSharpBible/Games/Galaxia_Base/Models/CorActions/JumpAction.cs b/CSharpBible/Games/Galaxia_Base/Models/CorActions/JumpAction.cs index fd1c80e13..5a07e16ba 100644 --- a/CSharpBible/Games/Galaxia_Base/Models/CorActions/JumpAction.cs +++ b/CSharpBible/Games/Galaxia_Base/Models/CorActions/JumpAction.cs @@ -1,11 +1,10 @@ using Galaxia.Models.Interfaces; -namespace Galaxia.Models.CorActions +namespace Galaxia.Models.CorActions; + +public abstract class JumpAction(ICorporation corporation, IFleet? fleet) : ICorAction { - public abstract class JumpAction(ICorporation corporation, IFleet? fleet) : ICorAction - { - public ICorporation Corporation => corporation; - public IFleet? Fleet => fleet; - public abstract bool Execute(); - } + public ICorporation Corporation => corporation; + public IFleet? Fleet => fleet; + public abstract bool Execute(); } \ No newline at end of file diff --git a/CSharpBible/Games/Galaxia_Base/Models/CorActions/SingleJump.cs b/CSharpBible/Games/Galaxia_Base/Models/CorActions/SingleJump.cs index 14e33a12b..221703672 100644 --- a/CSharpBible/Games/Galaxia_Base/Models/CorActions/SingleJump.cs +++ b/CSharpBible/Games/Galaxia_Base/Models/CorActions/SingleJump.cs @@ -8,20 +8,11 @@ namespace Galaxia.Models.CorActions /// public class SingleJump : JumpAction, ICorAction { - /// - /// Die Corporation, die die Aktion ausführt. - /// - public ICorporation Corporation { get; } - - /// - /// Die Flotte, die den Hyperjump ausführen soll. - /// - public IFleet Fleet { get; } /// /// Das Ziel-Sternensystem für den Hyperjump. /// - public IStarsystem TargetStarsystem { get; } + public IStarsystem? TargetStarsystem { get; } /// /// Erstellt eine neue SingleJump-Aktion. @@ -29,7 +20,7 @@ public class SingleJump : JumpAction, ICorAction /// Die ausführende Corporation. /// Die springende Flotte. /// Das Ziel-Sternensystem. - public SingleJump(ICorporation corporation, IFleet fleet, IStarsystem targetStarsystem):base(corporation,fleet) + public SingleJump(ICorporation corporation, IFleet? fleet, IStarsystem? targetStarsystem):base(corporation,fleet) { TargetStarsystem = targetStarsystem; } @@ -41,7 +32,7 @@ public SingleJump(ICorporation corporation, IFleet fleet, IStarsystem targetStar public override bool Execute() { // Überprüfe, ob die Flotte zur Corporation gehört und sich im Hyperspace befindet - if (Fleet.Owner != Corporation || Fleet.Container is not IHyperSlot hs ) + if (Fleet?.Owner != Corporation || Fleet.Container is not IHyperSlot hs ) return false; // Überprüfe, ob das Zielsystem erreichbar ist (optional, je nach Spielmechanik) diff --git a/CSharpBible/Games/Galaxia_Base/Models/Corporation.cs b/CSharpBible/Games/Galaxia_Base/Models/Corporation.cs index 9e1b59929..a924286a8 100644 --- a/CSharpBible/Games/Galaxia_Base/Models/Corporation.cs +++ b/CSharpBible/Games/Galaxia_Base/Models/Corporation.cs @@ -77,7 +77,7 @@ public IList GetPossibleActions() // Test if a double jump is possible (2 ships in hyperspace and combined reachable sectors) if (!Actions.Any(a => a is JumpAction) && hyperspace.CombReachableSectors().Count() > 0) { - possibleActions.Add(new DoubleJump(this, hyperspace.HyperSlots[0].Fleet, hyperspace.HyperSlots[1].Fleet, null)); + possibleActions.Add(new DoubleJump(this, hyperspace.HyperSlots[0].Fleet!, hyperspace.HyperSlots[1].Fleet!, null)); } // test if a Hyperslot is free or gets free this turn -> Embark is possible diff --git a/CSharpBible/Games/Galaxia_Base/Models/Interfaces/ICorAction.cs b/CSharpBible/Games/Galaxia_Base/Models/Interfaces/ICorAction.cs index d93c5e527..ae19db31d 100644 --- a/CSharpBible/Games/Galaxia_Base/Models/Interfaces/ICorAction.cs +++ b/CSharpBible/Games/Galaxia_Base/Models/Interfaces/ICorAction.cs @@ -7,7 +7,7 @@ public interface ICorAction /// /// The corporation. ICorporation Corporation { get; } - IFleet Fleet { get; } + IFleet? Fleet { get; } /// /// Executes this instance. diff --git a/CSharpBible/Games/Galaxia_Base/Models/Interfaces/Point3d.cs b/CSharpBible/Games/Galaxia_Base/Models/Interfaces/Point3d.cs index e24f3e442..da9f03e68 100644 --- a/CSharpBible/Games/Galaxia_Base/Models/Interfaces/Point3d.cs +++ b/CSharpBible/Games/Galaxia_Base/Models/Interfaces/Point3d.cs @@ -2,9 +2,11 @@ namespace Galaxia.Models.Interfaces; +#pragma warning disable CS0659 // Typ überschreibt Object.Equals(object o), überschreibt jedoch nicht Object.GetHashCode() public struct Point3d +#pragma warning restore CS0659 // Typ überschreibt Object.Equals(object o), überschreibt jedoch nicht Object.GetHashCode() { - internal static readonly Point3d Zero; + internal static readonly Point3d Zero=new(); public int X { get; } public int Y { get; } diff --git a/CSharpBible/Games/Galaxia_Base/Models/Starsystem.cs b/CSharpBible/Games/Galaxia_Base/Models/Starsystem.cs index d47c69bc5..ad5634c7c 100644 --- a/CSharpBible/Games/Galaxia_Base/Models/Starsystem.cs +++ b/CSharpBible/Games/Galaxia_Base/Models/Starsystem.cs @@ -41,7 +41,7 @@ public bool SetFleet(IFleet? fleet) if (Fleet != null) { if (!Fleet.Owner.Stars.Contains(this) && Fleet.Owner.Home != this) - fleet.Owner.Stars.Remove(this); + Fleet.Owner.Stars.Remove(this); } Fleet = fleet; diff --git a/CSharpBible/Games/Game_Base/Game_Base.csproj b/CSharpBible/Games/Game_Base/Game_Base.csproj index 39198c3b8..e6e47afcc 100644 --- a/CSharpBible/Games/Game_Base/Game_Base.csproj +++ b/CSharpBible/Games/Game_Base/Game_Base.csproj @@ -7,7 +7,14 @@ - + + $(TargetFrameworks);net9.0 + + + $(TargetFrameworks);net10.0 + + + diff --git a/CSharpBible/Games/Games.sln b/CSharpBible/Games/Games.sln index 83a20c7ee..af2ac8c9f 100644 --- a/CSharpBible/Games/Games.sln +++ b/CSharpBible/Games/Games.sln @@ -252,6 +252,9 @@ EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SharpHack.WPF2D", "SharpHack.WPF2D\SharpHack.WPF2D.csproj", "{9F55A149-DA32-BB7C-D552-73C3ECDF7C8B}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "TestStatements", "TestStatements", "{D44D28AA-A653-4BFC-A3CF-0CC30230A191}" + ProjectSection(SolutionItems) = preProject + ..\..\TestStatements\Solution_net.props = ..\..\TestStatements\Solution_net.props + EndProjectSection EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PluginBase", "..\..\TestStatements\PluginBase\PluginBase.csproj", "{0E45D0C0-4231-737D-1CCF-E1C23B5656E8}" EndProject @@ -261,6 +264,12 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OtherPlugin", "..\..\TestSt EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sokoban.Plugin", "Sokoban.Plugin\Sokoban.Plugin.csproj", "{D193A2C2-F42F-4172-9960-CF81051C12E9}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Werner_Flaschbier.Console2", "Werner_Flaschbier.Console2\Werner_Flaschbier.Console2.csproj", "{1895981C-B544-4BE4-EC3C-9B1034F2024E}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SharpHack.View.FirstPerson", "SharpHack.View.FirstPerson\SharpHack.View.FirstPerson.csproj", "{5601DCD5-5E75-9131-38B3-7C6275E4F1BC}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SharpHack.ViewModel.Tests", "SharpHack.ViewModel.Tests\SharpHack.ViewModel.Tests.csproj", "{A49A6D4E-4C50-8328-9779-18BFA42DB0A7}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -1471,6 +1480,42 @@ Global {D193A2C2-F42F-4172-9960-CF81051C12E9}.Release|x64.Build.0 = Release|Any CPU {D193A2C2-F42F-4172-9960-CF81051C12E9}.Release|x86.ActiveCfg = Release|Any CPU {D193A2C2-F42F-4172-9960-CF81051C12E9}.Release|x86.Build.0 = Release|Any CPU + {1895981C-B544-4BE4-EC3C-9B1034F2024E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {1895981C-B544-4BE4-EC3C-9B1034F2024E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {1895981C-B544-4BE4-EC3C-9B1034F2024E}.Debug|x64.ActiveCfg = Debug|Any CPU + {1895981C-B544-4BE4-EC3C-9B1034F2024E}.Debug|x64.Build.0 = Debug|Any CPU + {1895981C-B544-4BE4-EC3C-9B1034F2024E}.Debug|x86.ActiveCfg = Debug|Any CPU + {1895981C-B544-4BE4-EC3C-9B1034F2024E}.Debug|x86.Build.0 = Debug|Any CPU + {1895981C-B544-4BE4-EC3C-9B1034F2024E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {1895981C-B544-4BE4-EC3C-9B1034F2024E}.Release|Any CPU.Build.0 = Release|Any CPU + {1895981C-B544-4BE4-EC3C-9B1034F2024E}.Release|x64.ActiveCfg = Release|Any CPU + {1895981C-B544-4BE4-EC3C-9B1034F2024E}.Release|x64.Build.0 = Release|Any CPU + {1895981C-B544-4BE4-EC3C-9B1034F2024E}.Release|x86.ActiveCfg = Release|Any CPU + {1895981C-B544-4BE4-EC3C-9B1034F2024E}.Release|x86.Build.0 = Release|Any CPU + {5601DCD5-5E75-9131-38B3-7C6275E4F1BC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {5601DCD5-5E75-9131-38B3-7C6275E4F1BC}.Debug|Any CPU.Build.0 = Debug|Any CPU + {5601DCD5-5E75-9131-38B3-7C6275E4F1BC}.Debug|x64.ActiveCfg = Debug|Any CPU + {5601DCD5-5E75-9131-38B3-7C6275E4F1BC}.Debug|x64.Build.0 = Debug|Any CPU + {5601DCD5-5E75-9131-38B3-7C6275E4F1BC}.Debug|x86.ActiveCfg = Debug|Any CPU + {5601DCD5-5E75-9131-38B3-7C6275E4F1BC}.Debug|x86.Build.0 = Debug|Any CPU + {5601DCD5-5E75-9131-38B3-7C6275E4F1BC}.Release|Any CPU.ActiveCfg = Release|Any CPU + {5601DCD5-5E75-9131-38B3-7C6275E4F1BC}.Release|Any CPU.Build.0 = Release|Any CPU + {5601DCD5-5E75-9131-38B3-7C6275E4F1BC}.Release|x64.ActiveCfg = Release|Any CPU + {5601DCD5-5E75-9131-38B3-7C6275E4F1BC}.Release|x64.Build.0 = Release|Any CPU + {5601DCD5-5E75-9131-38B3-7C6275E4F1BC}.Release|x86.ActiveCfg = Release|Any CPU + {5601DCD5-5E75-9131-38B3-7C6275E4F1BC}.Release|x86.Build.0 = Release|Any CPU + {A49A6D4E-4C50-8328-9779-18BFA42DB0A7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A49A6D4E-4C50-8328-9779-18BFA42DB0A7}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A49A6D4E-4C50-8328-9779-18BFA42DB0A7}.Debug|x64.ActiveCfg = Debug|Any CPU + {A49A6D4E-4C50-8328-9779-18BFA42DB0A7}.Debug|x64.Build.0 = Debug|Any CPU + {A49A6D4E-4C50-8328-9779-18BFA42DB0A7}.Debug|x86.ActiveCfg = Debug|Any CPU + {A49A6D4E-4C50-8328-9779-18BFA42DB0A7}.Debug|x86.Build.0 = Debug|Any CPU + {A49A6D4E-4C50-8328-9779-18BFA42DB0A7}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A49A6D4E-4C50-8328-9779-18BFA42DB0A7}.Release|Any CPU.Build.0 = Release|Any CPU + {A49A6D4E-4C50-8328-9779-18BFA42DB0A7}.Release|x64.ActiveCfg = Release|Any CPU + {A49A6D4E-4C50-8328-9779-18BFA42DB0A7}.Release|x64.Build.0 = Release|Any CPU + {A49A6D4E-4C50-8328-9779-18BFA42DB0A7}.Release|x86.ActiveCfg = Release|Any CPU + {A49A6D4E-4C50-8328-9779-18BFA42DB0A7}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -1564,6 +1609,9 @@ Global {CE53A7C0-B60F-08B3-1E98-F00307A06E3F} = {D44D28AA-A653-4BFC-A3CF-0CC30230A191} {E953E2A6-54ED-57D7-8C8C-5FA30B2E58AF} = {D44D28AA-A653-4BFC-A3CF-0CC30230A191} {D193A2C2-F42F-4172-9960-CF81051C12E9} = {EAA6A4C4-78C2-412B-A322-0D3FA6691D50} + {1895981C-B544-4BE4-EC3C-9B1034F2024E} = {7337A459-E02B-4BD0-8271-807FD3E16A1B} + {5601DCD5-5E75-9131-38B3-7C6275E4F1BC} = {AC84E02A-08F3-46BF-9672-3BA37D5BB067} + {A49A6D4E-4C50-8328-9779-18BFA42DB0A7} = {AC84E02A-08F3-46BF-9672-3BA37D5BB067} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {51252E6F-E712-436A-B391-1C5243F65ABE} diff --git a/CSharpBible/Games/MidiSwing.MVVM/MidiSwing.MVVM.csproj b/CSharpBible/Games/MidiSwing.MVVM/MidiSwing.MVVM.csproj index 2f871f341..fb8e4cf3a 100644 --- a/CSharpBible/Games/MidiSwing.MVVM/MidiSwing.MVVM.csproj +++ b/CSharpBible/Games/MidiSwing.MVVM/MidiSwing.MVVM.csproj @@ -8,6 +8,13 @@ true + + + + + + + diff --git a/CSharpBible/Games/SharpHack.AI/SharpHack.AI.csproj b/CSharpBible/Games/SharpHack.AI/SharpHack.AI.csproj index f23578f99..388c0b5aa 100644 --- a/CSharpBible/Games/SharpHack.AI/SharpHack.AI.csproj +++ b/CSharpBible/Games/SharpHack.AI/SharpHack.AI.csproj @@ -1,11 +1,27 @@ - + + + + Library + net462;net472;net48;net481;net6.0;net7.0;net8.0 + Sokoban + AnyCPU;x64 + + + - - net10.0 - enable - enable + + $(TargetFrameworks);net9.0 + + + $(TargetFrameworks);net10.0 + + + + + + diff --git a/CSharpBible/Games/SharpHack.AITests/SharpHack.AITests.csproj b/CSharpBible/Games/SharpHack.AITests/SharpHack.AITests.csproj index 51aefe53a..59561df96 100644 --- a/CSharpBible/Games/SharpHack.AITests/SharpHack.AITests.csproj +++ b/CSharpBible/Games/SharpHack.AITests/SharpHack.AITests.csproj @@ -7,6 +7,12 @@ false + + + + + + diff --git a/CSharpBible/Games/SharpHack.Base/Interfaces/IContainerItem.cs b/CSharpBible/Games/SharpHack.Base/Interfaces/IContainerItem.cs index 6c7e5aff5..dfb7e7c0b 100644 --- a/CSharpBible/Games/SharpHack.Base/Interfaces/IContainerItem.cs +++ b/CSharpBible/Games/SharpHack.Base/Interfaces/IContainerItem.cs @@ -1,4 +1,5 @@ using SharpHack.Base.Model; +using System.Collections.Generic; namespace SharpHack.Base.Interfaces; diff --git a/CSharpBible/Games/SharpHack.Base/Interfaces/ICreature.cs b/CSharpBible/Games/SharpHack.Base/Interfaces/ICreature.cs index 2c16947b4..f7483912d 100644 --- a/CSharpBible/Games/SharpHack.Base/Interfaces/ICreature.cs +++ b/CSharpBible/Games/SharpHack.Base/Interfaces/ICreature.cs @@ -1,4 +1,5 @@ using SharpHack.Base.Model; +using System.Collections.Generic; namespace SharpHack.Base.Interfaces { diff --git a/CSharpBible/Games/SharpHack.Base/Interfaces/IGameObject.cs b/CSharpBible/Games/SharpHack.Base/Interfaces/IGameObject.cs index 09b930d1e..859fe76e4 100644 --- a/CSharpBible/Games/SharpHack.Base/Interfaces/IGameObject.cs +++ b/CSharpBible/Games/SharpHack.Base/Interfaces/IGameObject.cs @@ -1,14 +1,14 @@ using SharpHack.Base.Model; +using System; -namespace SharpHack.Base.Interfaces +namespace SharpHack.Base.Interfaces; + +public interface IGameObject { - public interface IGameObject - { - ConsoleColor Color { get; set; } - string Description { get; set; } - Guid Id { get; } - string Name { get; set; } - Point Position { get; set; } - char Symbol { get; set; } - } + ConsoleColor Color { get; set; } + string Description { get; set; } + Guid Id { get; } + string Name { get; set; } + Point Position { get; set; } + char Symbol { get; set; } } \ No newline at end of file diff --git a/CSharpBible/Games/SharpHack.Base/Interfaces/IGamePersist.cs b/CSharpBible/Games/SharpHack.Base/Interfaces/IGamePersist.cs index 0d276c4a5..9241642ac 100644 --- a/CSharpBible/Games/SharpHack.Base/Interfaces/IGamePersist.cs +++ b/CSharpBible/Games/SharpHack.Base/Interfaces/IGamePersist.cs @@ -1,4 +1,5 @@ using SharpHack.Base.Model; +using System.Collections.Generic; namespace SharpHack.Base.Interfaces; diff --git a/CSharpBible/Games/SharpHack.Base/Interfaces/ITile.cs b/CSharpBible/Games/SharpHack.Base/Interfaces/ITile.cs index f6acc35bb..8439a162a 100644 --- a/CSharpBible/Games/SharpHack.Base/Interfaces/ITile.cs +++ b/CSharpBible/Games/SharpHack.Base/Interfaces/ITile.cs @@ -1,5 +1,6 @@ using SharpHack.Base.Data; using SharpHack.Base.Model; +using System.Collections.Generic; namespace SharpHack.Base.Interfaces; diff --git a/CSharpBible/Games/SharpHack.Base/SharpHack.Base.csproj b/CSharpBible/Games/SharpHack.Base/SharpHack.Base.csproj index cd6db5978..49b654132 100644 --- a/CSharpBible/Games/SharpHack.Base/SharpHack.Base.csproj +++ b/CSharpBible/Games/SharpHack.Base/SharpHack.Base.csproj @@ -1,8 +1,20 @@ - - - net10.0 - enable - enable + + + + Library + net462;net472;net48;net481;net6.0;net7.0;net8.0 + + + + $(TargetFrameworks);net9.0 + + + $(TargetFrameworks);net10.0 + + + + + diff --git a/CSharpBible/Games/SharpHack.BaseCreatures/SharpHack.BaseCreatures.csproj b/CSharpBible/Games/SharpHack.BaseCreatures/SharpHack.BaseCreatures.csproj index 0401b2193..761cc8606 100644 --- a/CSharpBible/Games/SharpHack.BaseCreatures/SharpHack.BaseCreatures.csproj +++ b/CSharpBible/Games/SharpHack.BaseCreatures/SharpHack.BaseCreatures.csproj @@ -1,9 +1,17 @@ - + + + + Library + net462;net472;net48;net481;net6.0;net7.0;net8.0 + + + - - net10.0 - enable - enable + + $(TargetFrameworks);net9.0 + + + $(TargetFrameworks);net10.0 diff --git a/CSharpBible/Games/SharpHack.BaseItems/SharpHack.BaseItems.csproj b/CSharpBible/Games/SharpHack.BaseItems/SharpHack.BaseItems.csproj index 15462413b..a7baa2e57 100644 --- a/CSharpBible/Games/SharpHack.BaseItems/SharpHack.BaseItems.csproj +++ b/CSharpBible/Games/SharpHack.BaseItems/SharpHack.BaseItems.csproj @@ -1,9 +1,17 @@ - + + + + Library + net462;net472;net48;net481;net6.0;net7.0;net8.0 + + + - - net10.0 - enable - enable + + $(TargetFrameworks);net9.0 + + + $(TargetFrameworks);net10.0 diff --git a/CSharpBible/Games/SharpHack.BaseItemsTests/SharpHack.BaseItemsTests.csproj b/CSharpBible/Games/SharpHack.BaseItemsTests/SharpHack.BaseItemsTests.csproj index 7583d6412..d6e9103be 100644 --- a/CSharpBible/Games/SharpHack.BaseItemsTests/SharpHack.BaseItemsTests.csproj +++ b/CSharpBible/Games/SharpHack.BaseItemsTests/SharpHack.BaseItemsTests.csproj @@ -1,13 +1,20 @@ - + + + + Library + net462;net472;net48;net481;net7.0;net8.0 + + + - - net10.0 - enable - enable - false + + $(TargetFrameworks);net9.0 + + + $(TargetFrameworks);net10.0 - + diff --git a/CSharpBible/Games/SharpHack.BaseTests/SharpHack.BaseTests.csproj b/CSharpBible/Games/SharpHack.BaseTests/SharpHack.BaseTests.csproj index 09920bec8..ba89292ed 100644 --- a/CSharpBible/Games/SharpHack.BaseTests/SharpHack.BaseTests.csproj +++ b/CSharpBible/Games/SharpHack.BaseTests/SharpHack.BaseTests.csproj @@ -1,13 +1,20 @@ - + + + + Library + net462;net472;net48;net481;net7.0;net8.0 + + + - - net10.0 - enable - enable - false + + $(TargetFrameworks);net9.0 + + + $(TargetFrameworks);net10.0 - + diff --git a/CSharpBible/Games/SharpHack.Combat/SharpHack.Combat.csproj b/CSharpBible/Games/SharpHack.Combat/SharpHack.Combat.csproj index c9df3d96e..1a62f0f72 100644 --- a/CSharpBible/Games/SharpHack.Combat/SharpHack.Combat.csproj +++ b/CSharpBible/Games/SharpHack.Combat/SharpHack.Combat.csproj @@ -1,12 +1,20 @@ - + + + + Library + net462;net472;net48;net481;net6.0;net7.0;net8.0 + + + - - net10.0 - enable - enable + + $(TargetFrameworks);net9.0 + + + $(TargetFrameworks);net10.0 - + diff --git a/CSharpBible/Games/SharpHack.CombatTests/SharpHack.CombatTests.csproj b/CSharpBible/Games/SharpHack.CombatTests/SharpHack.CombatTests.csproj index 7be22461d..f483ab9fd 100644 --- a/CSharpBible/Games/SharpHack.CombatTests/SharpHack.CombatTests.csproj +++ b/CSharpBible/Games/SharpHack.CombatTests/SharpHack.CombatTests.csproj @@ -1,17 +1,24 @@ - + + + + Library + net462;net472;net48;net481;net7.0;net8.0 + + + - - net10.0 - enable - enable - false + + $(TargetFrameworks);net9.0 + + + $(TargetFrameworks);net10.0 - - - - - + + + + + diff --git a/CSharpBible/Games/SharpHack.Engine/GameSession.cs b/CSharpBible/Games/SharpHack.Engine/GameSession.cs index 64532e06b..f21083acb 100644 --- a/CSharpBible/Games/SharpHack.Engine/GameSession.cs +++ b/CSharpBible/Games/SharpHack.Engine/GameSession.cs @@ -5,6 +5,8 @@ using SharpHack.Base.Data; using SharpHack.Engine.Pathfinding; using SharpHack.BaseItems.Model; +using System.Collections.Generic; +using System; namespace SharpHack.Engine; diff --git a/CSharpBible/Games/SharpHack.Engine/Pathfinding/AStarPathfinder.cs b/CSharpBible/Games/SharpHack.Engine/Pathfinding/AStarPathfinder.cs index d284f6d90..5f27b1810 100644 --- a/CSharpBible/Games/SharpHack.Engine/Pathfinding/AStarPathfinder.cs +++ b/CSharpBible/Games/SharpHack.Engine/Pathfinding/AStarPathfinder.cs @@ -14,8 +14,11 @@ public static class AStarPathfinder { return null; } - +#if NET5_0_OR_GREATER var open = new PriorityQueue(); +#else + var open = new SimplePriorityQueue(); +#endif var cameFrom = new Dictionary(); var gScore = new Dictionary { diff --git a/CSharpBible/Games/SharpHack.Engine/Pathfinding/SimplePriorityQueue.cs b/CSharpBible/Games/SharpHack.Engine/Pathfinding/SimplePriorityQueue.cs new file mode 100644 index 000000000..ea4a8c53b --- /dev/null +++ b/CSharpBible/Games/SharpHack.Engine/Pathfinding/SimplePriorityQueue.cs @@ -0,0 +1,52 @@ +using System; +using System.Collections.Generic; + +namespace SharpHack.Engine.Pathfinding; + +public class SimplePriorityQueue where TPriority : IComparable +{ + private readonly List<(TElement Element, TPriority Priority)> _nodes = new(); + + public int Count => _nodes.Count; + + public void Enqueue(TElement element, TPriority priority) + { + _nodes.Add((element, priority)); + var i = _nodes.Count - 1; + while (i > 0) + { + var parent = (i - 1) / 2; + if (_nodes[parent].Priority.CompareTo(_nodes[i].Priority) <= 0) break; + (_nodes[parent], _nodes[i]) = (_nodes[i], _nodes[parent]); + i = parent; + } + } + + public TElement Dequeue() + { + if (_nodes.Count == 0) throw new InvalidOperationException("Queue ist leer."); + + var result = _nodes[0].Element; + _nodes[0] = _nodes[_nodes.Count - 1]; + _nodes.RemoveAt(_nodes.Count - 1); + + var i = 0; + while (true) + { + var left = i * 2 + 1; + var right = i * 2 + 2; + var smallest = i; + + if (left < _nodes.Count && _nodes[left].Priority.CompareTo(_nodes[smallest].Priority) < 0) + smallest = left; + if (right < _nodes.Count && _nodes[right].Priority.CompareTo(_nodes[smallest].Priority) < 0) + smallest = right; + + if (smallest == i) break; + (_nodes[i], _nodes[smallest]) = (_nodes[smallest], _nodes[i]); + i = smallest; + } + + return result; + } +} \ No newline at end of file diff --git a/CSharpBible/Games/SharpHack.Engine/SharpHack.Engine.csproj b/CSharpBible/Games/SharpHack.Engine/SharpHack.Engine.csproj index 3447ad059..02a2f09f4 100644 --- a/CSharpBible/Games/SharpHack.Engine/SharpHack.Engine.csproj +++ b/CSharpBible/Games/SharpHack.Engine/SharpHack.Engine.csproj @@ -1,16 +1,29 @@ - + + + + Library + net462;net472;net48;net481;net6.0;net7.0;net8.0 + + + - - net10.0 - enable - enable + + $(TargetFrameworks);net9.0 + + + $(TargetFrameworks);net10.0 - - - - - + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + diff --git a/CSharpBible/Games/SharpHack.EngineTests/SharpHack.EngineTests.csproj b/CSharpBible/Games/SharpHack.EngineTests/SharpHack.EngineTests.csproj index c1fcefb4e..57f9bc0b9 100644 --- a/CSharpBible/Games/SharpHack.EngineTests/SharpHack.EngineTests.csproj +++ b/CSharpBible/Games/SharpHack.EngineTests/SharpHack.EngineTests.csproj @@ -1,17 +1,24 @@ - + + + + Library + net462;net472;net48;net481;net7.0;net8.0 + + + - - net10.0 - enable - enable - false + + $(TargetFrameworks);net9.0 + + + $(TargetFrameworks);net10.0 - - - - - + + + + + diff --git a/CSharpBible/Games/SharpHack.LevelGen/BSP/BSPMapGenerator.cs b/CSharpBible/Games/SharpHack.LevelGen/BSP/BSPMapGenerator.cs index 33cab31a9..32d5608ab 100644 --- a/CSharpBible/Games/SharpHack.LevelGen/BSP/BSPMapGenerator.cs +++ b/CSharpBible/Games/SharpHack.LevelGen/BSP/BSPMapGenerator.cs @@ -6,7 +6,8 @@ using Point = SharpHack.Base.Model.Point; using SharpHack.Base.Data; using SharpHack.Base.Interfaces; -using SharpHack.Engine.Pathfinding; // Resolve ambiguity with System.Drawing.Point +using SharpHack.Engine.Pathfinding; +using System.Linq; // Resolve ambiguity with System.Drawing.Point namespace SharpHack.LevelGen.BSP; @@ -61,8 +62,13 @@ private void CreateStart(BSPNode root, Map map, Point point) int w = _random.Next(MinRoomSize, Math.Max(MinRoomSize, node.Bounds.Width - 2)); int h = _random.Next(MinRoomSize, Math.Max(MinRoomSize, node.Bounds.Height - 2)); // make sure the random room contains the point +#if NET5_0_OR_GREATER int x = Math.Clamp(point.X - w / 2, node.Bounds.X, node.Bounds.Right - w); int y = Math.Clamp(point.Y - h / 2, node.Bounds.Y, node.Bounds.Bottom - h); +#else + int x = Math.Max(node.Bounds.X, Math.Min(point.X - w / 2, node.Bounds.Right - w)); + int y = Math.Max(node.Bounds.Y, Math.Min(point.Y - h / 2, node.Bounds.Bottom - h)); +#endif node.Room = new Rectangle(x, y, w, h); for (int rx = x; rx < x + w; rx++) { @@ -209,7 +215,11 @@ private static (Point door, Point outside) PickRoomDoorAndOutside(Rectangle room { bool toRight = dx >= 0; int doorX = toRight ? room.Right : room.Left-1; +#if NET5_0_OR_GREATER int doorY = Math.Clamp(otherCenterY, room.Top + 1, room.Bottom - 1); +#else + int doorY = Math.Max(room.Top + 1, Math.Min(otherCenterY, room.Bottom - 1)); +#endif var door = new Point(doorX, doorY); var outside = new Point(doorX + (toRight ? 1 : -1), doorY); return (door, outside); @@ -218,7 +228,11 @@ private static (Point door, Point outside) PickRoomDoorAndOutside(Rectangle room { bool toDown = dy >= 0; int doorY = toDown ? room.Bottom : room.Top-1; +#if NET5_0_OR_GREATER int doorX = Math.Clamp(otherCenterX, room.Left + 1, room.Right - 1); +#else + int doorX = Math.Max(room.Left + 1, Math.Min(otherCenterX, room.Right - 1)); +#endif var door = new Point(doorX, doorY); var outside = new Point(doorX, doorY + (toDown ? 1 : -1)); return (door, outside); @@ -323,7 +337,15 @@ private void CreateCorridor(BSPNode node, IMap map, Point start, Point end, List blocked = true; room.Inflate(-1, -1); var d = (room.X + room.Width / 2 - end.X, room.Y + room.Height / 2 - end.Y); - d = Math.Abs(d.Item1)>Math.Abs(d.Item2)?(Math.Clamp(d.Item1, -1, 1), 0):(0, Math.Clamp(d.Item2, -1, 1)); +#if NET5_0_OR_GREATER + d = Math.Abs(d.Item1)>Math.Abs(d.Item2)? + (Math.Clamp(d.Item1, -1, 1), 0): + (0, Math.Clamp(d.Item2, -1, 1)); +#else + d = Math.Abs(d.Item1)>Math.Abs(d.Item2)? + (d.Item1<0?-1:d.Item1>0?1:0, 0): + (0, d.Item2<0?-1:d.Item2>0?1:0); +#endif room.Offset(d.Item1, d.Item2); if (d.Item1 * (end.X - x) + d.Item2 * (end.Y - y) < 3) { @@ -333,7 +355,12 @@ private void CreateCorridor(BSPNode node, IMap map, Point start, Point end, List { var rm = (room.X + room.Width / 2 - x, room.Y + room.Height / 2 - y); // we are about to carve into a room wall, compute, to get around it. +#if NET5_0_OR_GREATER (x, y) = (x + Math.Clamp((rm.Item1 * 2 + 1) * -Math.Abs(d.Item2), -1, 1), y + Math.Clamp((rm.Item2 * 2 + 1) * -Math.Abs(d.Item1), -1, 1)); +#else + (x, y) = (x + ((rm.Item1 * 2 + 1) * -Math.Abs(d.Item2) < 0 ? -1 : ((rm.Item1 * 2 + 1) * -Math.Abs(d.Item2) > 0 ? 1 : 0)), + y + ((rm.Item2 * 2 + 1) * -Math.Abs(d.Item1) < 0 ? -1 : ((rm.Item2 * 2 + 1) * -Math.Abs(d.Item1) > 0 ? 1 : 0))); +#endif } else (x, y) = (x - d.Item1, y - d.Item2); diff --git a/CSharpBible/Games/SharpHack.LevelGen/BSP/BSPRoomMazeMapGenerator.cs b/CSharpBible/Games/SharpHack.LevelGen/BSP/BSPRoomMazeMapGenerator.cs index 8e0bc1337..c1bb8fa98 100644 --- a/CSharpBible/Games/SharpHack.LevelGen/BSP/BSPRoomMazeMapGenerator.cs +++ b/CSharpBible/Games/SharpHack.LevelGen/BSP/BSPRoomMazeMapGenerator.cs @@ -340,7 +340,11 @@ private void ApplyDoors(Map map, List doorCandidates) private static int ClampEven(int value, int min, int max) { +#if NET5_0_OR_GREATER int v = Math.Clamp(value, min, max); +#else + int v = Math.Max(min, Math.Min(max, value)); +#endif if ((v & 1) == 1) { if (v + 1 <= max) v++; diff --git a/CSharpBible/Games/SharpHack.LevelGen/SharpHack.LevelGen.csproj b/CSharpBible/Games/SharpHack.LevelGen/SharpHack.LevelGen.csproj index 585be23d6..9e11dfb86 100644 --- a/CSharpBible/Games/SharpHack.LevelGen/SharpHack.LevelGen.csproj +++ b/CSharpBible/Games/SharpHack.LevelGen/SharpHack.LevelGen.csproj @@ -1,16 +1,28 @@ - + + + + Library + net462;net472;net48;net481;net6.0;net7.0;net8.0 + + + - - net10.0 - enable - enable + + $(TargetFrameworks);net9.0 + + + $(TargetFrameworks);net10.0 - - - - - + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + diff --git a/CSharpBible/Games/SharpHack.LevelGenTests/SharpHack.LevelGenTests.csproj b/CSharpBible/Games/SharpHack.LevelGenTests/SharpHack.LevelGenTests.csproj index 2809b428e..7764ff80e 100644 --- a/CSharpBible/Games/SharpHack.LevelGenTests/SharpHack.LevelGenTests.csproj +++ b/CSharpBible/Games/SharpHack.LevelGenTests/SharpHack.LevelGenTests.csproj @@ -1,17 +1,24 @@ - + + + + Library + net462;net472;net48;net481;net7.0;net8.0 + + + - - net10.0 - enable - enable - false + + $(TargetFrameworks);net9.0 + + + $(TargetFrameworks);net10.0 - - - - - + + + + + diff --git a/CSharpBible/Games/SharpHack.Magic/SharpHack.Magic.csproj b/CSharpBible/Games/SharpHack.Magic/SharpHack.Magic.csproj index c9df3d96e..3878bc2bc 100644 --- a/CSharpBible/Games/SharpHack.Magic/SharpHack.Magic.csproj +++ b/CSharpBible/Games/SharpHack.Magic/SharpHack.Magic.csproj @@ -1,16 +1,24 @@ - + + + + Library + net462;net472;net48;net481;net6.0;net7.0;net8.0 + + + - - net10.0 - enable - enable + + $(TargetFrameworks);net9.0 + + + $(TargetFrameworks);net10.0 - - - - - + + + + + diff --git a/CSharpBible/Games/SharpHack.MapExport/SharpHack.MapExport.csproj b/CSharpBible/Games/SharpHack.MapExport/SharpHack.MapExport.csproj index 06d75777a..367b8ee67 100644 --- a/CSharpBible/Games/SharpHack.MapExport/SharpHack.MapExport.csproj +++ b/CSharpBible/Games/SharpHack.MapExport/SharpHack.MapExport.csproj @@ -1,4 +1,4 @@ - + Exe net10.0-windows @@ -6,6 +6,12 @@ true enable + + + + + + diff --git a/CSharpBible/Games/SharpHack.Persist/InMemoryGamePersist.cs b/CSharpBible/Games/SharpHack.Persist/InMemoryGamePersist.cs index 8a21f8672..7b1dfb5f7 100644 --- a/CSharpBible/Games/SharpHack.Persist/InMemoryGamePersist.cs +++ b/CSharpBible/Games/SharpHack.Persist/InMemoryGamePersist.cs @@ -1,5 +1,6 @@ using SharpHack.Base.Interfaces; using SharpHack.Base.Model; +using System.Collections.Generic; namespace SharpHack.Persist; diff --git a/CSharpBible/Games/SharpHack.Persist/SharpHack.Persist.csproj b/CSharpBible/Games/SharpHack.Persist/SharpHack.Persist.csproj index f23578f99..638b1784a 100644 --- a/CSharpBible/Games/SharpHack.Persist/SharpHack.Persist.csproj +++ b/CSharpBible/Games/SharpHack.Persist/SharpHack.Persist.csproj @@ -1,11 +1,25 @@ - + + + + Library + net462;net472;net48;net481;net6.0;net7.0;net8.0 + + + - - net10.0 - enable - enable + + $(TargetFrameworks);net9.0 + + + $(TargetFrameworks);net10.0 + + + + + + diff --git a/CSharpBible/Games/SharpHack.Server/SharpHack.Server.csproj b/CSharpBible/Games/SharpHack.Server/SharpHack.Server.csproj index 5b022d74a..5dfc74145 100644 --- a/CSharpBible/Games/SharpHack.Server/SharpHack.Server.csproj +++ b/CSharpBible/Games/SharpHack.Server/SharpHack.Server.csproj @@ -9,8 +9,11 @@ + + + diff --git a/CSharpBible/Games/SharpHack.Terminal/SharpHack.Terminal.csproj b/CSharpBible/Games/SharpHack.Terminal/SharpHack.Terminal.csproj index 42ca14001..220eb6968 100644 --- a/CSharpBible/Games/SharpHack.Terminal/SharpHack.Terminal.csproj +++ b/CSharpBible/Games/SharpHack.Terminal/SharpHack.Terminal.csproj @@ -7,6 +7,12 @@ enable + + + + + + diff --git a/CSharpBible/Games/SharpHack.View.FirstPerson/App.xaml b/CSharpBible/Games/SharpHack.View.FirstPerson/App.xaml new file mode 100644 index 000000000..a9f70bb6a --- /dev/null +++ b/CSharpBible/Games/SharpHack.View.FirstPerson/App.xaml @@ -0,0 +1,7 @@ + + + + + diff --git a/CSharpBible/Games/SharpHack.View.FirstPerson/App.xaml.cs b/CSharpBible/Games/SharpHack.View.FirstPerson/App.xaml.cs new file mode 100644 index 000000000..4b20616d4 --- /dev/null +++ b/CSharpBible/Games/SharpHack.View.FirstPerson/App.xaml.cs @@ -0,0 +1,65 @@ +using System.Windows; +using Microsoft.Extensions.DependencyInjection; +using SharpHack.ViewModel; +using SharpHack.Engine; +using SharpHack.LevelGen.BSP; +using SharpHack.Combat; +using SharpHack.AI; +using BaseLib.Models; +using BaseLib.Models.Interfaces; +using SharpHack.Base.Interfaces; +using SharpHack.Persist; + +namespace SharpHack.View.FirstPerson; + +/// +/// Interaction logic for App.xaml +/// +public partial class App : Application +{ + private ServiceProvider _serviceProvider; + + /// + /// Initializes a new instance of the class. + /// + public App() + { + ServiceCollection services = new ServiceCollection(); + ConfigureServices(services); + _serviceProvider = services.BuildServiceProvider(); + } + + /// + /// Configures the services for the application. + /// + /// The service collection to add services to. + private void ConfigureServices(ServiceCollection services) + { + // Core Services + services.AddSingleton(); + services.AddSingleton(); + services.AddSingleton(); + services.AddSingleton(); + services.AddSingleton(); + services.AddSingleton(); + + // Game Session + services.AddSingleton(); + + // ViewModel + services.AddSingleton(); + + // View + services.AddSingleton(); + } + + /// + /// Raises the event. + /// + /// A that contains the event data. + protected override void OnStartup(StartupEventArgs e) + { + var mainWindow = _serviceProvider.GetRequiredService(); + mainWindow.Show(); + } +} diff --git a/CSharpBible/Games/SharpHack.View.FirstPerson/MainWindow.xaml b/CSharpBible/Games/SharpHack.View.FirstPerson/MainWindow.xaml new file mode 100644 index 000000000..fd9e4f2c0 --- /dev/null +++ b/CSharpBible/Games/SharpHack.View.FirstPerson/MainWindow.xaml @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/CSharpBible/Games/SharpHack.View.FirstPerson/MainWindow.xaml.cs b/CSharpBible/Games/SharpHack.View.FirstPerson/MainWindow.xaml.cs new file mode 100644 index 000000000..0555a69e2 --- /dev/null +++ b/CSharpBible/Games/SharpHack.View.FirstPerson/MainWindow.xaml.cs @@ -0,0 +1,20 @@ +using System.Windows; +using SharpHack.ViewModel; + +namespace SharpHack.View.FirstPerson; + +/// +/// Interaction logic for MainWindow.xaml +/// +public partial class MainWindow : Window +{ + /// + /// Initializes a new instance of the class. + /// + /// The view model. + public MainWindow(FirstPersonGameViewModel viewModel) + { + InitializeComponent(); + DataContext = viewModel; + } +} diff --git a/CSharpBible/Games/SharpHack.View.FirstPerson/Properties/Resources.Designer.cs b/CSharpBible/Games/SharpHack.View.FirstPerson/Properties/Resources.Designer.cs new file mode 100644 index 000000000..f1917bf4c --- /dev/null +++ b/CSharpBible/Games/SharpHack.View.FirstPerson/Properties/Resources.Designer.cs @@ -0,0 +1,90 @@ +//------------------------------------------------------------------------------ +// +// Dieser Code wurde von einem Tool generiert. +// Laufzeitversion:4.0.30319.42000 +// +// Änderungen an dieser Datei können falsches Verhalten verursachen und gehen verloren, wenn +// der Code erneut generiert wird. +// +//------------------------------------------------------------------------------ + +namespace SharpHack.View.FirstPerson.Properties { + using System; + + + /// + /// Eine stark typisierte Ressourcenklasse zum Suchen von lokalisierten Zeichenfolgen usw. + /// + // Diese Klasse wurde von der StronglyTypedResourceBuilder automatisch generiert + // -Klasse über ein Tool wie ResGen oder Visual Studio automatisch generiert. + // Um einen Member hinzuzufügen oder zu entfernen, bearbeiten Sie die .ResX-Datei und führen dann ResGen + // mit der /str-Option erneut aus, oder Sie erstellen Ihr VS-Projekt neu. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "18.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + public class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// Gibt die zwischengespeicherte ResourceManager-Instanz zurück, die von dieser Klasse verwendet wird. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + public static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("SharpHack.View.FirstPerson.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Überschreibt die CurrentUICulture-Eigenschaft des aktuellen Threads für alle + /// Ressourcenzuordnungen, die diese stark typisierte Ressourcenklasse verwenden. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + public static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// Sucht eine lokalisierte Zeichenfolge, die SharpHack First Person ähnelt. + /// + public static string AppTitle { + get { + return ResourceManager.GetString("AppTitle", resourceCulture); + } + } + + /// + /// Sucht eine lokalisierte Zeichenfolge, die HP: ähnelt. + /// + public static string HPLabel { + get { + return ResourceManager.GetString("HPLabel", resourceCulture); + } + } + + /// + /// Sucht eine lokalisierte Zeichenfolge, die Level: ähnelt. + /// + public static string LevelLabel { + get { + return ResourceManager.GetString("LevelLabel", resourceCulture); + } + } + } +} diff --git a/CSharpBible/Games/SharpHack.View.FirstPerson/Properties/Resources.resx b/CSharpBible/Games/SharpHack.View.FirstPerson/Properties/Resources.resx new file mode 100644 index 000000000..1e55a5757 --- /dev/null +++ b/CSharpBible/Games/SharpHack.View.FirstPerson/Properties/Resources.resx @@ -0,0 +1,62 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + SharpHack First Person + + + HP: + + + Level: + + diff --git a/CSharpBible/Games/SharpHack.View.FirstPerson/SharpHack.View.FirstPerson.csproj b/CSharpBible/Games/SharpHack.View.FirstPerson/SharpHack.View.FirstPerson.csproj new file mode 100644 index 000000000..421bb029a --- /dev/null +++ b/CSharpBible/Games/SharpHack.View.FirstPerson/SharpHack.View.FirstPerson.csproj @@ -0,0 +1,39 @@ + + + WinExe + net10.0-windows + enable + true + enable + + + + + + + + + + + + + + + + + + + True + True + Resources.resx + + + + + + PublicResXFileCodeGenerator + Resources.Designer.cs + + + + diff --git a/CSharpBible/Games/SharpHack.View.FirstPerson/Views/FirstPersonView.xaml b/CSharpBible/Games/SharpHack.View.FirstPerson/Views/FirstPersonView.xaml new file mode 100644 index 000000000..61e9e51ba --- /dev/null +++ b/CSharpBible/Games/SharpHack.View.FirstPerson/Views/FirstPersonView.xaml @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + public static class Program { + private static readonly string SOKOSERVER_TLS_CERT_PATH= "SOKOSERVER_TLS_CERT_PATH"; + private static readonly string SOKOSERVER_TLS_CERT_PASSWORD = "SOKOSERVER_TLS_CERT_PASSWORD"; + private static readonly string SOKOSERVER_TLS = "SOKOSERVER_TLS"; public static async Task Main(string[] args) { @@ -30,11 +34,11 @@ public static async Task Main(string[] args) var listener = new TcpListener(IPAddress.Any, port); listener.Start(); - System.Console.WriteLine($"SharpHack server listening on 0.0.0.0:{port}"); + System.Console.WriteLine($"{Assembly.GetExecutingAssembly().GetName().Name} server listening on 0.0.0.0:{port}"); if (useTls) { System.Console.WriteLine("TLS enabled: connect with an SSL/TLS capable client, then use TELNET/RAW over the secure channel."); - System.Console.WriteLine($"Certificate: {(string.IsNullOrWhiteSpace(certPath) ? "" : certPath)}"); + System.Console.WriteLine($"Certificate: {(string.IsNullOrWhiteSpace(certPath) ? $"" : certPath)}"); } else { @@ -178,19 +182,19 @@ private static void ParseArgs(string[] args, ref int port, ref bool useTls, ref if (!useTls) { - var envTls = Environment.GetEnvironmentVariable("SHARPHACK_TLS") ?? Environment.GetEnvironmentVariable("SHARPHACK_SSL"); + var envTls = Environment.GetEnvironmentVariable(SOKOSERVER_TLS) ?? Environment.GetEnvironmentVariable("SHARPHACK_SSL"); if (!string.IsNullOrWhiteSpace(envTls) && (envTls.Equals("1") || envTls.Equals("true", StringComparison.OrdinalIgnoreCase) || envTls.Equals("yes", StringComparison.OrdinalIgnoreCase))) { useTls = true; } } - certPath ??= Environment.GetEnvironmentVariable("SHARPHACK_TLS_CERT_PATH"); - certPassword ??= Environment.GetEnvironmentVariable("SHARPHACK_TLS_CERT_PASSWORD"); + certPath ??= Environment.GetEnvironmentVariable(SOKOSERVER_TLS_CERT_PATH); + certPassword ??= Environment.GetEnvironmentVariable(SOKOSERVER_TLS_CERT_PASSWORD); if (useTls && string.IsNullOrWhiteSpace(certPath)) { - throw new InvalidOperationException("TLS is enabled but no certificate was provided. Use --cert or set SHARPHACK_TLS_CERT_PATH."); + throw new InvalidOperationException($"TLS is enabled but no certificate was provided. Use --cert or set {SOKOSERVER_TLS_CERT_PATH}."); } } diff --git a/CSharpBible/Games/Sokoban.Server/Sokoban.Server.csproj b/CSharpBible/Games/Sokoban.Server/Sokoban.Server.csproj index 13255fa4b..b56b76480 100644 --- a/CSharpBible/Games/Sokoban.Server/Sokoban.Server.csproj +++ b/CSharpBible/Games/Sokoban.Server/Sokoban.Server.csproj @@ -14,8 +14,8 @@ - + diff --git a/CSharpBible/Games/Sokoban/Program.cs b/CSharpBible/Games/Sokoban/Program.cs index b5408ce7d..a84680939 100644 --- a/CSharpBible/Games/Sokoban/Program.cs +++ b/CSharpBible/Games/Sokoban/Program.cs @@ -50,7 +50,7 @@ public static void Cleanup() public static void Run() { UserAction? direction = null; - while (direction!=UserAction.Quit && LabDefs.SLevels.Length > _SokobanGame.level) + while (direction!=UserAction.Quit && LabDefs.SLevels.Length > _SokobanGame?.level) { direction = _SokobanGame?.Run(); } diff --git a/CSharpBible/Games/Sokoban_Base/Sokoban_Base.csproj b/CSharpBible/Games/Sokoban_Base/Sokoban_Base.csproj index 54e62e3ef..5b8e9d0c0 100644 --- a/CSharpBible/Games/Sokoban_Base/Sokoban_Base.csproj +++ b/CSharpBible/Games/Sokoban_Base/Sokoban_Base.csproj @@ -60,7 +60,7 @@ - + diff --git a/CSharpBible/Games/Sokoban_BaseTests/Models/StoneTests.cs b/CSharpBible/Games/Sokoban_BaseTests/Models/StoneTests.cs index 8c5df47fc..3010c116e 100644 --- a/CSharpBible/Games/Sokoban_BaseTests/Models/StoneTests.cs +++ b/CSharpBible/Games/Sokoban_BaseTests/Models/StoneTests.cs @@ -1,5 +1,6 @@ using Microsoft.VisualStudio.TestTools.UnitTesting; using Sokoban.Models; +using Sokoban.Models.Interfaces; using System.Drawing; namespace Sokoban.Models.Tests @@ -38,8 +39,8 @@ public void SetupTest() [DataRow(1, 1, Direction.East, false)] public void TestMoveTest(int x,int y,Direction d,bool xExp) { - if (y>0) - pf[new Point(x,y)].Item = testItem; + if (y>0 && pf[new Point(x, y)] is IField fld ) + fld.Item = testItem; else if (x > 0) new Floor(Point.Empty,null).Item = testItem; Assert.AreEqual(xExp,testItem.TestMove(d)); @@ -56,8 +57,8 @@ public void TestMoveTest(int x,int y,Direction d,bool xExp) [DataRow(1, 1, Direction.East, false)] public void TryMoveTest(int x, int y, Direction d, bool xExp) { - if (y > 0) - pf[new Point(x, y)].Item = testItem; + if (y > 0 && pf[new Point(x, y)] is IField fld) + fld.Item = testItem; else if (x>0) new Floor(Point.Empty,null).Item = testItem; Assert.AreEqual(xExp, testItem.TryMove(d)); diff --git a/CSharpBible/Games/Sudoku_Base/Models/UndoInformation.cs b/CSharpBible/Games/Sudoku_Base/Models/UndoInformation.cs index 4528b60ea..05797738b 100644 --- a/CSharpBible/Games/Sudoku_Base/Models/UndoInformation.cs +++ b/CSharpBible/Games/Sudoku_Base/Models/UndoInformation.cs @@ -27,14 +27,14 @@ public void Redo() } else if (ov is int i && xf && f!.Value == i || ov == null && xf) { - f.Value = nv as int?; + f!.Value = nv as int?; } else if (nv is IList li && xf) { - f.PossibleValues.Clear(); + f?.PossibleValues.Clear(); foreach (var l in li) { - f.PossibleValues.Add(l); + f?.PossibleValues.Add(l); } } } @@ -51,14 +51,14 @@ public void Undo() } else if (nv is int i && xf && f!.Value == i || nv == null && xf) { - f.Value = ov as int?; + f!.Value = ov as int?; } else if (ov is IList li && xf) { - f.PossibleValues.Clear(); + f?.PossibleValues.Clear(); foreach (var l in li) { - f.PossibleValues.Add(l); + f?.PossibleValues.Add(l); } } } diff --git a/CSharpBible/Games/Sudoku_BaseTests/Models/SudokuFieldTests.cs b/CSharpBible/Games/Sudoku_BaseTests/Models/SudokuFieldTests.cs index 81500f9e9..45f5c79f9 100644 --- a/CSharpBible/Games/Sudoku_BaseTests/Models/SudokuFieldTests.cs +++ b/CSharpBible/Games/Sudoku_BaseTests/Models/SudokuFieldTests.cs @@ -82,7 +82,7 @@ public void ReadFromStreamTest(byte[] bytes, SudokuField field) // Act testModel.ReadFromStream(stream); // Assert - AssertAreEqual(field, testModel, []); + AssertAreEqual(field, testModel, [nameof(testModel.PossibleValues)]); } [TestMethod()] diff --git a/CSharpBible/Games/Tetris_Base/View/Visual.cs b/CSharpBible/Games/Tetris_Base/View/Visual.cs index 39f58eebe..985b077eb 100644 --- a/CSharpBible/Games/Tetris_Base/View/Visual.cs +++ b/CSharpBible/Games/Tetris_Base/View/Visual.cs @@ -31,7 +31,6 @@ public static class Visual /// The display2 /// static public Display display2 = new Display(18, 2, 6, 6); - private static bool flag; /// /// Gets or sets the console. diff --git a/CSharpBible/Games/TileSetAnimator.Tests/TileSetAnimator.Tests.csproj b/CSharpBible/Games/TileSetAnimator.Tests/TileSetAnimator.Tests.csproj index 885c5aef2..b0d45bcf7 100644 --- a/CSharpBible/Games/TileSetAnimator.Tests/TileSetAnimator.Tests.csproj +++ b/CSharpBible/Games/TileSetAnimator.Tests/TileSetAnimator.Tests.csproj @@ -8,6 +8,13 @@ enable + + + + + + + diff --git a/CSharpBible/Games/TileSetAnimator/TileSetAnimator.csproj b/CSharpBible/Games/TileSetAnimator/TileSetAnimator.csproj index 214539916..d28784a93 100644 --- a/CSharpBible/Games/TileSetAnimator/TileSetAnimator.csproj +++ b/CSharpBible/Games/TileSetAnimator/TileSetAnimator.csproj @@ -8,6 +8,12 @@ preview true + + + + + + diff --git a/CSharpBible/Games/VTileEdit/Models/VisTileData.cs b/CSharpBible/Games/VTileEdit/Models/VisTileData.cs index 2188af055..fd0ffd2ef 100644 --- a/CSharpBible/Games/VTileEdit/Models/VisTileData.cs +++ b/CSharpBible/Games/VTileEdit/Models/VisTileData.cs @@ -16,7 +16,9 @@ namespace VTileEdit.Models; +#pragma warning disable CS0659 // Typ überschreibt Object.Equals(object o), überschreibt jedoch nicht Object.GetHashCode() public class VisTileData : ITileDef +#pragma warning restore CS0659 // Typ überschreibt Object.Equals(object o), überschreibt jedoch nicht Object.GetHashCode() { private sealed class TileEntry { @@ -293,9 +295,10 @@ public bool LoadFromStream(Stream stream, EStreamType eStreamType) { Dictionary? data = []; var lst = JsonSerializer.Deserialize>>>(new StreamReader(stream).ReadToEnd()); - KeyTypeStr = lst.Item1 ?? ""; - _size = lst.Item2; - foreach (var itm in lst.Item3) + KeyTypeStr = lst?.Item1 ?? ""; + _size = lst?.Item2 ?? default; + if (lst?.Item3 != null) + foreach (var itm in lst!.Item3) { data.Add(itm.Item1, new TileEntry(itm.Item2, TileInfo.Default)); } @@ -446,6 +449,7 @@ public bool WriteToStream(Stream stream, EStreamType eStreamType) return new Json2Data.TileEntry( (int)(object)v.Key, + tags.ToArray(), tile.lines, tile.colors.Select(c => (byte)(((int)c.bgr) * 16 + (byte)c.fgr)).ToArray(), diff --git a/CSharpBible/Games/VTileEditTests/Models/VisTileDataTests.cs b/CSharpBible/Games/VTileEditTests/Models/VisTileDataTests.cs index ca62efb26..98b6b2dde 100644 --- a/CSharpBible/Games/VTileEditTests/Models/VisTileDataTests.cs +++ b/CSharpBible/Games/VTileEditTests/Models/VisTileDataTests.cs @@ -655,7 +655,7 @@ private static string Decompress(string input) return reader.ReadToEnd(); } } - catch (Exception ex) + catch (Exception) { return input; } @@ -673,7 +673,7 @@ private static byte[] DecompressBinary(string input) return reader.ToArray(); } } - catch (Exception ex) + catch (Exception) { return Encoding.UTF8.GetBytes( input); } diff --git a/CSharpBible/Games/Werner_Flaschbier.Console2/Program.cs b/CSharpBible/Games/Werner_Flaschbier.Console2/Program.cs new file mode 100644 index 000000000..719cf2566 --- /dev/null +++ b/CSharpBible/Games/Werner_Flaschbier.Console2/Program.cs @@ -0,0 +1,56 @@ +using BaseLib.Helper; +using BaseLib.Interfaces; +using BaseLib.Models; +using ConsoleDisplay.View; +using Microsoft.Extensions.DependencyInjection; +using System.Threading; +using Werner_Flaschbier.Console2.View; +using Werner_Flaschbier_Base.Model; +using Werner_Flaschbier_Base.ViewModels; + +namespace Werner_Flaschbier.Console2; + +public class Programm +{ + private IWernerGame? game; + private IVisual? visual; + + private void OnStartUp() + { + var sc = new ServiceCollection() + .AddSingleton() + .AddTransient() + .AddSingleton() + .AddSingleton() + .AddSingleton(); + + var sp = sc.BuildServiceProvider(); + + IoC.Configure(sp); + } + + public static void Main(params string[] args) + { + var program = new Programm(); + program.Initialize(args); + program.Run(); + } + + public void Run() + { + while (game!.isRunning) + { + visual?.CheckUserAction(); + var delay = game.GameStep(); + Thread.Sleep(delay); + } + } + + public void Initialize(string[] args) + { + OnStartUp(); + + game = IoC.GetRequiredService(); + visual = IoC.GetRequiredService(); + } +} diff --git a/CSharpBible/Games/Werner_Flaschbier.Console2/View/IVisual.cs b/CSharpBible/Games/Werner_Flaschbier.Console2/View/IVisual.cs new file mode 100644 index 000000000..9248641d3 --- /dev/null +++ b/CSharpBible/Games/Werner_Flaschbier.Console2/View/IVisual.cs @@ -0,0 +1,19 @@ +// *********************************************************************** +// Assembly : Werner_Flaschbier_Base +// Author : Mir +// Created : 08-02-2022 +// +// Last Modified By : Mir +// Last Modified On : 09-09-2022 +// *********************************************************************** +// +// Copyright (c) JC-Soft. All rights reserved. +// +// +// *********************************************************************** +namespace Werner_Flaschbier.Console2.View; + +public interface IVisual +{ + bool CheckUserAction(); +} \ No newline at end of file diff --git a/CSharpBible/Games/Werner_Flaschbier.Console2/View/VTileDef.cs b/CSharpBible/Games/Werner_Flaschbier.Console2/View/VTileDef.cs new file mode 100644 index 000000000..56f8560f7 --- /dev/null +++ b/CSharpBible/Games/Werner_Flaschbier.Console2/View/VTileDef.cs @@ -0,0 +1,106 @@ +// *********************************************************************** +// Assembly : Werner_Flaschbier_Base +// Author : Mir +// Created : 08-02-2022 +// +// Last Modified By : Mir +// Last Modified On : 09-09-2022 +// *********************************************************************** +// +// Copyright (c) JC-Soft. All rights reserved. +// +// +// *********************************************************************** +using System; +using System.Drawing; +using ConsoleDisplay.View; + +namespace Werner_Flaschbier.Console2.View +{ + + /// + /// Class VTileDef. + /// + public class VTileDef : TileDefBase, ITileDef { + /// + /// The v tile definition string + /// + private string[][] _vTileDefStr = [ + [" ", " "], + ["=-=-", "-=-="], + ["─┴┬─", "─┬┴─"], + [" â•“â•– ", "â–“â–‘â–’â–“"], + ["âŒÂ°@)", " ⌡⌡‼"], + [@"/¯¯\", @"\__/"], + ["]°°[", "_!!_"], + ["◄°@[",@"_!!\"], + ["]oo[", "_!!_"], + ["]@°►", "/!!_"], + [@"/╨╨\", @"\__/"], + [" +*∩", "╘â•â—Š@"], + [" ", " "], + ["─┴┬┴", "─┬┴─"], + ["┬┴┬─", "┴┬┴─"], + ["┬┴┬┴", "┴┬┴─"], + + ["┬┴┬─", "┴┬┴┬"], + ["┬┴┬┴", "┴┬┴┬"], + ["┬┴┬─", "┴┬┴┬"], + ["┬┴┬┴", "┴┬┴┬"], + + ["─┴┬─", "─┬┴─"], + ["─┴┬┴", "─┬┴─"], + ["┬┴┬─", "┴┬┴─"], + ["┬┴┬┴", "┴┬┴─"], + + ["┬┴┬─", "┴┬┴┬"], + ["┬┴┬┴", "┴┬┴┬"], + ["┬┴┬─", "┴┬┴┬"], + ["┬┴┬┴", "┴┬┴┬"] + ]; + + /// + /// The v tile colors + /// + private byte[][] _vTileColors = + [ + [0x00], + [0x6E], + [0x4F], + [0x0E, 0x0E, 0x0E, 0x0E, 0x2A, 0x22, 0x02, 0x22], + [0x6F], + [0x6E], + [0x1A,0xA0,0xA0,0x1A,0x1A,0xA0,0xA0,0x1A], + [0x1A,0xA0,0xA0,0x1A,0x1A,0xA0,0xA0,0x1A], + [0x1A,0xA0,0xA0,0x1A,0x1A,0xA0,0xA0,0x1A], + [0x1A,0xA0,0xA0,0x1A,0x1A,0xA0,0xA0,0x1A], + [0x6E], + [0x6F], + [0x6E], + [0x4F], + + ]; + + public new Size TileSize => new Size(4,2); + + /// + /// Gets the tile colors. + /// + /// The tile. + /// FullColor[]. + private (ConsoleColor fgr, ConsoleColor bgr)[] GetTileColors(Enum? tile) + { + var result = new (ConsoleColor fgr, ConsoleColor bgr)[8]; + byte[] colDef = GetArrayElement(_vTileColors, tile); + for (var i =0;i> 4)); + } + return result; + } + + public override (string[] lines, (ConsoleColor fgr, ConsoleColor bgr)[] colors) GetTileDef(Enum? tile) + => (GetArrayElement(_vTileDefStr, tile), GetTileColors((Enum?)tile)); + } +} diff --git a/CSharpBible/Games/Werner_Flaschbier.Console2/View/Visual.cs b/CSharpBible/Games/Werner_Flaschbier.Console2/View/Visual.cs new file mode 100644 index 000000000..bcdcb6579 --- /dev/null +++ b/CSharpBible/Games/Werner_Flaschbier.Console2/View/Visual.cs @@ -0,0 +1,136 @@ +using BaseLib.Interfaces; +using ConsoleDisplay.View; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Drawing; +using System.Linq; +using Werner_Flaschbier_Base.Model; +using Werner_Flaschbier_Base.ViewModels; + +namespace Werner_Flaschbier.Console2.View +{ + public class Visual : IVisual + { + private readonly TileDisplay _display; + private readonly IWernerViewModel _viewModel; + private readonly IConsole _console; + private readonly List _actionBuffer = new List(); + + public static Dictionary keyAction = new Dictionary { + { 'I', UserAction.GoUp }, + { 'J', UserAction.GoWest }, + { 'K', UserAction.GoDown }, + { 'L', UserAction.GoEast }, + { '?', UserAction.Help }, + { 'H', UserAction.Help }, + { 'R', UserAction.Restart }, + { 'Q', UserAction.Quit }, +#if DEBUG + { 'N', UserAction.NextLvl }, + { 'V', UserAction.PrevLvl }, +#endif + { '\u001b', UserAction.Quit } }; + + public Visual(IWernerViewModel viewModel, IConsole console, ITileDef tileDef) + { + _viewModel = viewModel; + _console = console; + _console.CursorVisible = false; + _display = new TileDisplay(console, tileDef); + _display.FncGetTile = (p) => (Tiles)_viewModel.Tiles[p]; + _display.FncOldPos = (p) => _viewModel.OldPos(p); + _display.SetDispSize(_viewModel.size); + + _viewModel.PropertyChanged += OnPropertyChanged; + FullRedraw(); + } + + private void OnPropertyChanged(object? sender, PropertyChangedEventArgs e) + { + if (e.PropertyName == "Tiles") + { + _display.Update(_viewModel!.HalfStep); + _console.SetCursorPosition(0, 24); + _console.BackgroundColor = ConsoleColor.Black; + _console.ForegroundColor = ConsoleColor.Yellow; + } + else if (e.PropertyName == "Level") + FullRedraw(); + } + + public void FullRedraw(object? sender = null, EventArgs? e = null) + { + if (_viewModel == null) return; + _display.FullRedraw(); + ShowStatistics(); + } + + private void ShowStatistics() + { + if (_viewModel == null) return; + _console.SetCursorPosition(0, 24); + _console.BackgroundColor = ConsoleColor.Black; + _console.ForegroundColor = ConsoleColor.Yellow; + _console.Write($"\t{_viewModel.Level + 1}\t\t{_viewModel.Score}\t\t{_viewModel.Lives}/{_viewModel.MaxLives} \t\t{Math.Floor(_viewModel.TimeLeft)}\t\x08"); + } + + public void WriteTile(PointF p, Tiles tile) + { + _display.WriteTile(p, tile); + } + + public void Sound(GameSound gs) + { + switch (gs) + { + case GameSound.NoSound: + break; + case GameSound.Tick: + _console.Beep(1000, 10); + break; + case GameSound.DeepBoom: + _console.Beep(300, 20); + break; + default: + break; + } + } + + public bool CheckUserAction() + { + while (_console.KeyAvailable) + { + var ch = char.ToUpper(_console.ReadKey()?.KeyChar ?? '\x00'); + if (keyAction.TryGetValue(ch, out var action)) + { + int sameCount = 0; + for (int i = _actionBuffer.Count - 1; i >= 0 && _actionBuffer[i] == action; i--) + { + sameCount++; + } + + if (sameCount < 2) + { + _actionBuffer.Add(action); + } + if (_actionBuffer.Count > 2) + { + _actionBuffer.RemoveAt(0); + } + } + } + UserAction currentAction = UserAction.Nop; + bool result = _actionBuffer.Count > 0; + + if (result) + { + currentAction = _actionBuffer[0]; + _actionBuffer.RemoveAt(0); + } + + _viewModel?.HandleUserAction(currentAction); + return result; + } + } +} diff --git a/CSharpBible/Games/Werner_Flaschbier.Console2/Werner_Flaschbier.Console2.csproj b/CSharpBible/Games/Werner_Flaschbier.Console2/Werner_Flaschbier.Console2.csproj new file mode 100644 index 000000000..d2a6da173 --- /dev/null +++ b/CSharpBible/Games/Werner_Flaschbier.Console2/Werner_Flaschbier.Console2.csproj @@ -0,0 +1,30 @@ + + + + net462;net472;net48;net481;net6.0;net7.0;net8.0;net9.0 + Exe + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/CSharpBible/Games/Werner_Flaschbier/Model/WernerGame.cs b/CSharpBible/Games/Werner_Flaschbier/Model/WernerGame.cs index b4dd809a1..ab4907147 100644 --- a/CSharpBible/Games/Werner_Flaschbier/Model/WernerGame.cs +++ b/CSharpBible/Games/Werner_Flaschbier/Model/WernerGame.cs @@ -163,7 +163,7 @@ public Tiles GetTile(Point p) public Point OldPos(Point p) { var field = playfield[p]; - if (field is Space s && s.Item != null) + if (field is Space s && s.Item != null && !(s.Item is Dirt) ) return s.Item.OldPosition; else return p; @@ -242,7 +242,11 @@ public int GameStep() foreach (PlayObject po in playfield.ActiveObjects) po.Handled = false; foreach (Space sp in playfield.Spaces) + { sp.OldItem = sp.Item; + if (sp.Item != null) + sp.Item.OldPosition = sp.Position; + } playfield.player?.TryMove(actDir); actDir = nextDir; nextDir = nextDir2; diff --git a/CSharpBible/Graphics/All_Graphics/Models/AllExampleModel.cs b/CSharpBible/Graphics/All_Graphics/Models/AllExampleModel.cs index f8165ef18..f2521dc81 100644 --- a/CSharpBible/Graphics/All_Graphics/Models/AllExampleModel.cs +++ b/CSharpBible/Graphics/All_Graphics/Models/AllExampleModel.cs @@ -94,7 +94,7 @@ public AllExampleModel() try { Debug.WriteLine($"{ex.Description} {ex.ExType}"); - var desc = new Dictionary(); + var desc = new Dictionary(); Type? t = ex.ExType.Assembly.GetTypes().First((t) => t.Name.EndsWith(nameof(Resources))); if (t != null) { @@ -102,7 +102,7 @@ public AllExampleModel() if (prop.PropertyType == typeof(string)) { Debug.WriteLine($" {prop.Name} {prop.PropertyType} "); - desc[prop.Name] = (string)prop.GetValue(null); + desc[prop.Name] = (string?)prop.GetValue(null); } ex.Additionals = desc; } diff --git a/CSharpBible/Graphics/All_Graphics/ViewModels/AllExamplesViewModel.cs b/CSharpBible/Graphics/All_Graphics/ViewModels/AllExamplesViewModel.cs index 0c6b0e692..92b0b08f4 100644 --- a/CSharpBible/Graphics/All_Graphics/ViewModels/AllExamplesViewModel.cs +++ b/CSharpBible/Graphics/All_Graphics/ViewModels/AllExamplesViewModel.cs @@ -38,7 +38,7 @@ public partial class AllExamplesViewModel : BaseViewModelCT private ObservableCollection _examples = new(); [ObservableProperty] - string _exFilter; + string? _exFilter; #endregion #region Methods @@ -57,7 +57,7 @@ public AllExamplesViewModel(ITemplateModel model) OnExFilterChanged(ExFilter); } - private void OnMPropertyChanged(object sender, PropertyChangedEventArgs e) + private void OnMPropertyChanged(object? sender, PropertyChangedEventArgs e) { OnPropertyChanged(e.PropertyName); } diff --git a/CSharpBible/Graphics/CanvasWPF/CanvasWPF.csproj b/CSharpBible/Graphics/CanvasWPF/CanvasWPF.csproj index c1b0498ce..a5dbb0be1 100644 --- a/CSharpBible/Graphics/CanvasWPF/CanvasWPF.csproj +++ b/CSharpBible/Graphics/CanvasWPF/CanvasWPF.csproj @@ -2,12 +2,18 @@ WinExe - net472;net48;net481;net6.0-windows;net7.0-windows;net8.0-windows + net472;net48;net481;net8.0-windows true AnyCPU;x64 + + $(TargetFrameworks);net9.0-windows + + + $(TargetFrameworks);net10.0-windows + CanvasWPF true diff --git a/CSharpBible/Graphics/CanvasWPF2_CTItemTemplateSelector/CanvasWPF2_CTItemTemplateSelector.csproj b/CSharpBible/Graphics/CanvasWPF2_CTItemTemplateSelector/CanvasWPF2_CTItemTemplateSelector.csproj index 82b50447f..8192f8718 100644 --- a/CSharpBible/Graphics/CanvasWPF2_CTItemTemplateSelector/CanvasWPF2_CTItemTemplateSelector.csproj +++ b/CSharpBible/Graphics/CanvasWPF2_CTItemTemplateSelector/CanvasWPF2_CTItemTemplateSelector.csproj @@ -2,12 +2,18 @@ WinExe - net472;net48;net481;net6.0-windows;net7.0-windows + net472;net48;net481;net8.0-windows true AnyCPU;x64 + + $(TargetFrameworks);net9.0-windows + + + $(TargetFrameworks);net10.0-windows + false false diff --git a/CSharpBible/Graphics/CanvasWPF2_CTItemTemplateSelector/ViewModels/MainWindowViewmodel.cs b/CSharpBible/Graphics/CanvasWPF2_CTItemTemplateSelector/ViewModels/MainWindowViewmodel.cs index adcc3215b..81966eb58 100644 --- a/CSharpBible/Graphics/CanvasWPF2_CTItemTemplateSelector/ViewModels/MainWindowViewmodel.cs +++ b/CSharpBible/Graphics/CanvasWPF2_CTItemTemplateSelector/ViewModels/MainWindowViewmodel.cs @@ -119,7 +119,7 @@ private void SelectShape(object? o) private void CreateRectangle() { lock (Shapes) - Shapes.Add(new ShapeData(_rnd.Next(0, 600), _rnd.Next(0, 400)) { Dx = _rnd.NextDouble() * 40 - 20, Dy = _rnd.NextDouble() * 40 - 20, SType = 0, MouseHover = new DelegateCommand(Shape_MouseHover) }); + Shapes.Add(new ShapeData(_rnd.Next(0, 600), _rnd.Next(0, 400)) { Dx = _rnd.NextDouble() * 40 - 20, Dy = _rnd.NextDouble() * 40 - 20, SType = 0, MouseHover = Shape_MouseHover }); } private void CreateCircle() @@ -143,7 +143,7 @@ private void CreateTorus() [RelayCommand] private void DeleteShape(object? o) => throw new NotImplementedException(); - private void Shape_MouseHover(object o) + private void Shape_MouseHover(object? o) { if (o is ShapeData obj) DataText = $"{GetNameOfType(obj.SType)} at {obj.point}"; diff --git a/CSharpBible/Graphics/CanvasWPF2_CTItemTemplateSelector/ViewModels/ObservablePoint.cs b/CSharpBible/Graphics/CanvasWPF2_CTItemTemplateSelector/ViewModels/ObservablePoint.cs index 349f70f6d..495be2724 100644 --- a/CSharpBible/Graphics/CanvasWPF2_CTItemTemplateSelector/ViewModels/ObservablePoint.cs +++ b/CSharpBible/Graphics/CanvasWPF2_CTItemTemplateSelector/ViewModels/ObservablePoint.cs @@ -72,12 +72,12 @@ public partial class ShapeData : NotificationObjectCT /// Gets or sets the mouse left button down. /// /// The mouse left button down. - public DelegateCommand MouseLeftButtonDown { get; set; } = default; + public DelegateCommand? MouseLeftButtonDown { get; set; } = default; /// /// Gets or sets the mouse hover. /// /// The mouse hover. - public DelegateCommand MouseHover { get; set; } = default; + public DelegateCommand? MouseHover { get; set; } = default; #endregion #region Methods @@ -97,7 +97,7 @@ public ShapeData(Point p):this(p.X, p.Y) { } /// The y. public ShapeData(double x, double y) { (X, Y) = (x, y); - MouseLeftButtonDown = new DelegateCommand((o) => { }); + MouseLeftButtonDown = new DelegateCommand((o) => { }); } const int iMargin = 20; diff --git a/CSharpBible/Graphics/CanvasWPF2_ItemTemplateSelector/CanvasWPF2_ItemTemplateSelector.csproj b/CSharpBible/Graphics/CanvasWPF2_ItemTemplateSelector/CanvasWPF2_ItemTemplateSelector.csproj index 50107732a..6555ad4b2 100644 --- a/CSharpBible/Graphics/CanvasWPF2_ItemTemplateSelector/CanvasWPF2_ItemTemplateSelector.csproj +++ b/CSharpBible/Graphics/CanvasWPF2_ItemTemplateSelector/CanvasWPF2_ItemTemplateSelector.csproj @@ -2,7 +2,7 @@ WinExe - net472;net48;net481;net6.0-windows;net7.0-windows;net8.0-windows + net472;net48;net481;net8.0-windows true AnyCPU;x64 diff --git a/CSharpBible/Graphics/CanvasWPF2_ItemTemplateSelector/ViewModels/IVisualObject.cs b/CSharpBible/Graphics/CanvasWPF2_ItemTemplateSelector/ViewModels/IVisualObject.cs index ca6c44c55..8b4f602ce 100644 --- a/CSharpBible/Graphics/CanvasWPF2_ItemTemplateSelector/ViewModels/IVisualObject.cs +++ b/CSharpBible/Graphics/CanvasWPF2_ItemTemplateSelector/ViewModels/IVisualObject.cs @@ -10,7 +10,7 @@ public interface IVisualObject double Dx { get; set; } double Dy { get; set; } int sType { get; set; } - DelegateCommand MouseHover { get; set; } + DelegateCommand? MouseHover { get; set; } Point point { get; set; } void Step(); diff --git a/CSharpBible/Graphics/CanvasWPF2_ItemTemplateSelector/ViewModels/ItemBehavior.cs b/CSharpBible/Graphics/CanvasWPF2_ItemTemplateSelector/ViewModels/ItemBehavior.cs index 5bf6fd2e3..9bc74f17f 100644 --- a/CSharpBible/Graphics/CanvasWPF2_ItemTemplateSelector/ViewModels/ItemBehavior.cs +++ b/CSharpBible/Graphics/CanvasWPF2_ItemTemplateSelector/ViewModels/ItemBehavior.cs @@ -38,7 +38,7 @@ protected override void OnAttached() var c = (AssociatedObject.DataContext as IVisualObject); if (c != null) c.point = elementPosition; - (AssociatedObject.DataContext as IVisualObject)?.MouseHover.Execute(AssociatedObject.DataContext); + (AssociatedObject.DataContext as IVisualObject)?.MouseHover?.Execute(AssociatedObject.DataContext); }; AssociatedObject.MouseLeftButtonUp += (s, e) => @@ -49,7 +49,7 @@ protected override void OnAttached() AssociatedObject.MouseEnter += (s, e) => { - (AssociatedObject.DataContext as IVisualObject)?.MouseHover.Execute(AssociatedObject.DataContext); + (AssociatedObject.DataContext as IVisualObject)?.MouseHover?.Execute(AssociatedObject.DataContext); }; } } diff --git a/CSharpBible/Graphics/CanvasWPF_CT/CanvasWPF_CT.csproj b/CSharpBible/Graphics/CanvasWPF_CT/CanvasWPF_CT.csproj index 3000f131f..89a39dd49 100644 --- a/CSharpBible/Graphics/CanvasWPF_CT/CanvasWPF_CT.csproj +++ b/CSharpBible/Graphics/CanvasWPF_CT/CanvasWPF_CT.csproj @@ -2,7 +2,7 @@ WinExe - net472;net48;net481;net6.0-windows;net7.0-windows;net8.0-windows + net472;net48;net481;net8.0-windows true AnyCPU;x64 diff --git a/CSharpBible/Graphics/Cifar10.WPF/Cifar10.WPF.csproj b/CSharpBible/Graphics/Cifar10.WPF/Cifar10.WPF.csproj index dcd7bafdb..8747971cd 100644 --- a/CSharpBible/Graphics/Cifar10.WPF/Cifar10.WPF.csproj +++ b/CSharpBible/Graphics/Cifar10.WPF/Cifar10.WPF.csproj @@ -14,7 +14,7 @@ - + diff --git a/CSharpBible/Graphics/Cifar10_2.WPF/Cifar10_2.WPF.csproj b/CSharpBible/Graphics/Cifar10_2.WPF/Cifar10_2.WPF.csproj index 1834c6662..0e134c023 100644 --- a/CSharpBible/Graphics/Cifar10_2.WPF/Cifar10_2.WPF.csproj +++ b/CSharpBible/Graphics/Cifar10_2.WPF/Cifar10_2.WPF.csproj @@ -16,7 +16,7 @@ - + diff --git a/CSharpBible/Graphics/Cifar10_2.WPF/Views/CifarFilteredView.xaml b/CSharpBible/Graphics/Cifar10_2.WPF/Views/CifarFilteredView.xaml index e3d324ff0..0bf2c7db8 100644 --- a/CSharpBible/Graphics/Cifar10_2.WPF/Views/CifarFilteredView.xaml +++ b/CSharpBible/Graphics/Cifar10_2.WPF/Views/CifarFilteredView.xaml @@ -31,74 +31,76 @@ - - - + - - + + - - - + + + + Width="128" + Height="128" + Source="{Binding DestImage}" + Stretch="Uniform" /> - - - - - - - - - - - - - + HorizontalScrollBarVisibility="Disabled" + VerticalScrollBarVisibility="Auto"> + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - + + B - + I - + U - - - - - - - - - + - + CustomWords.lex - + - + diff --git a/CSharpBible/MVVM_Tutorial/MVVM_36_ComToolKtSavesWork/Views/CommunityToolkit2View.xaml b/CSharpBible/MVVM_Tutorial/MVVM_36_ComToolKtSavesWork/Views/CommunityToolkit2View.xaml index 8aa2cb906..353ad12a0 100644 --- a/CSharpBible/MVVM_Tutorial/MVVM_36_ComToolKtSavesWork/Views/CommunityToolkit2View.xaml +++ b/CSharpBible/MVVM_Tutorial/MVVM_36_ComToolKtSavesWork/Views/CommunityToolkit2View.xaml @@ -1,42 +1,47 @@ - + - - + + - + - diff --git a/CSharpBible/MVVM_Tutorial/MVVM_36_ComToolKtSavesWork/Views/UserControls/LoginControl.xaml b/CSharpBible/MVVM_Tutorial/MVVM_36_ComToolKtSavesWork/Views/UserControls/LoginControl.xaml index 07c807d05..3204a4cc6 100644 --- a/CSharpBible/MVVM_Tutorial/MVVM_36_ComToolKtSavesWork/Views/UserControls/LoginControl.xaml +++ b/CSharpBible/MVVM_Tutorial/MVVM_36_ComToolKtSavesWork/Views/UserControls/LoginControl.xaml @@ -1,23 +1,28 @@ - + - + -