Added Base Project

This commit is contained in:
Müller Wayan
2025-02-23 14:29:32 +01:00
parent cda7948be9
commit a6130d4ff0
364 changed files with 12117 additions and 0 deletions
@@ -0,0 +1,22 @@
{
"type": "object",
"properties": {
"AppSettings": {
"type": "object",
"properties": {
"ScreenResolution": {
"type": "object",
"properties": {
"x": { "type": "integer" },
"y": { "type": "integer" }
},
"required": [ "x", "y" ]
},
"Fullscreen": { "type": "boolean" },
"Log" : {"type": "boolean"}
},
"Required": [ "ScreenResolution", "Fullscreen", "Log" ]
}
},
"Required" : ["AppSettings"]
}
+144
View File
@@ -0,0 +1,144 @@
using Firebird2D.Logger;
using Microsoft.Extensions.Configuration;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json.Schema;
using SFML.Window;
using System.Text;
namespace Firebird2D.Configuration
{
public class GameConfig
{
public VideoMode VideoMode { get { return _videoMode; } set { _videoMode = value; updateConfig(); } }
public bool FullScreen { get { return _fullScreen; } set { _fullScreen = value; updateConfig(); } }
public bool LogActive { get { return _logActive; } set { _logActive = value; GameLogger.logActive = value; updateConfig(); } }
private static readonly string ConfigSchema = "Configuration/ConfigurationSchema/ConfigSchema.json";
private static readonly string ConfigPath = "Configuration/GameConfig.json";
private IConfigurationBuilder _configurationBuilder;
private IConfigurationSection _configurationSection;
private VideoMode _videoMode;
private bool _fullScreen;
private bool _logActive;
public GameConfig() {
CheckFile();
LoadConfig();
}
private void updateConfig()
{
if (_configurationBuilder != null)
{
_configurationSection["ScreenResolution:x"] = _videoMode.Width.ToString();
_configurationSection["ScreenResolution:y"] = _videoMode.Height.ToString();
_configurationSection["Fullscreen"] = _fullScreen.ToString();
_configurationSection["Log"] = _logActive.ToString();
}
}
private void LoadConfig()
{
_configurationBuilder = new ConfigurationBuilder().AddJsonFile(ConfigPath, false, true);
_configurationSection = _configurationBuilder.Build().GetSection("AppSettings");
_videoMode = new VideoMode();
if (_configurationSection != null)
{
try
{
_videoMode.Width = uint.Parse(_configurationSection["ScreenResolution:x"]);
_videoMode.Height = uint.Parse(_configurationSection["ScreenResolution:y"]);
_fullScreen = bool.Parse(_configurationSection["Fullscreen"]);
_logActive = bool.Parse(_configurationSection["Log"]);
GameLogger.logActive = _logActive;
}
catch(Exception ex)
{
GameLogger.Log("GameConfig", LogType.Error, ex.Message);
File.Delete(ConfigPath);
MakeConfigFile();
LoadConfig();
}
}
else
{
GameLogger.Log("GameConfig", LogType.Error, "The Config File Was Corrupted");
File.Delete(ConfigPath);
MakeConfigFile();
LoadConfig();
}
}
private void CheckFile()
{
if (File.Exists(ConfigPath))
{
string schemaJson = File.ReadAllText(ConfigSchema);
JSchema schema = JSchema.Parse(schemaJson);
string ConfigData = File.ReadAllText(ConfigPath);
JObject json = JObject.Parse(ConfigData);
IList<string> validationErrors = [];
if (schema != null)
{
if (!json.IsValid(schema,out validationErrors)){
File.Delete(ConfigPath);
MakeConfigFile();
GameLogger.Log("GameConfig", LogType.Error, "The Config File Was Corrupted");
foreach (string error in validationErrors)
{
GameLogger.Log("GameConfig", LogType.Error, error);
}
}
}
}
else
{
MakeConfigFile();
}
}
private void MakeConfigFile()
{
VideoMode desktopMode = VideoMode.DesktopMode;
using (FileStream stream = File.Create(ConfigPath))
{
AddText(stream, "{" +
" \"AppSettings\":{" +
" \"ScreenResolution\": {" +
string.Format(" \"x\": {0},", desktopMode.Width) +
string.Format(" \"y\": {0}", desktopMode.Height) +
" }," +
" \"Fullscreen\": false," +
" \"Log\": true," +
" }" +
"}"
);
stream.Close();
}
}
private static void AddText(FileStream fs, string value)
{
byte[] info = new UTF8Encoding(true).GetBytes(value);
fs.Write(info, 0, info.Length);
}
}
}
+266
View File
@@ -0,0 +1,266 @@
using SFML.System;
using SFML.Window;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Firebird2D.Core
{
internal struct JoystickMapping
{
public uint joysticnumber;
public uint buttonnumber;
}
public static class InputMapper
{
private static Dictionary<Keyboard.Key, KeyboardHandler> KeyboardMapping = new Dictionary<Keyboard.Key, KeyboardHandler>();
private static Dictionary<JoystickMapping, JoystickButtonHandler> JoystickButtonMapping = new Dictionary<JoystickMapping, JoystickButtonHandler>();
private static Dictionary<Mouse.Button, MouseHandler> MouseButtonMapping = new Dictionary<Mouse.Button, MouseHandler>();
private static List<(Keyboard.Key, Keyboard.Key)> Keyremaps = new List<(Keyboard.Key, Keyboard.Key)>();
private static List<(Mouse.Button, Mouse.Button)> MouseButtonremaps = new List<(Mouse.Button, Mouse.Button)>();
private static List<(uint, uint, uint)> JoystickButtonremaps = new List<(uint, uint, uint)>();
public delegate void KeyboardHandler(Keyboard.Key key);
public delegate void MouseHandler(Mouse.Button button);
public delegate void JoystickButtonHandler(uint JoystickId, uint ButtonNumber);
public delegate void JoystickAxisHandler(uint JoystickId, float x, float y, float z, float r, float u, float v);
public delegate void JoystickHatHandler(uint JoystickId, float PovX, float PovY);
public delegate void MouseCursorPositionhandler(Vector2i mousePosition);
public static event JoystickAxisHandler? JoystickAxisEvent;
public static event JoystickHatHandler? JoystickHatEvent;
public static event MouseCursorPositionhandler? MouseCursorPositionEvent;
public static void Map(KeyboardHandler Method, Keyboard.Key key)
{
KeyboardMapping.Add(key, Method);
}
public static void Map(MouseHandler Method, Mouse.Button button)
{
MouseButtonMapping.Add(button, Method);
}
public static void Map(JoystickButtonHandler Method, uint joysticknumber, uint buttonnumber)
{
JoystickMapping mapping = new JoystickMapping { joysticnumber = joysticknumber, buttonnumber = buttonnumber };
JoystickButtonMapping.Add(mapping, Method);
}
public static void Remap(Keyboard.Key key1, Keyboard.Key key2)
{
if (KeyboardMapping.ContainsKey(key2)) throw new ArgumentException("Key2 already exists");
if (!KeyboardMapping.ContainsKey(key1)) throw new ArgumentException("Key1 not existing");
var keyboardHandler = KeyboardMapping[key1];
KeyboardMapping.Remove(key1);
KeyboardMapping.Add(key2, keyboardHandler);
if (!Keyremaps.Contains((key1, key2)))
Keyremaps.Add((key1, key2));
}
public static void Remap(Mouse.Button button1, Mouse.Button button2)
{
if (MouseButtonMapping.ContainsKey(button2)) throw new ArgumentException("Button2 already exists");
if (!MouseButtonMapping.ContainsKey(button1)) throw new ArgumentException("Button1 not existing");
var mouseHandler = MouseButtonMapping[button1];
MouseButtonMapping.Remove(button1);
MouseButtonMapping.Add(button2, mouseHandler);
if (!MouseButtonremaps.Contains((button1, button2)))
MouseButtonremaps.Add((button1, button2));
}
public static void Remap(uint joysticknumber, uint buttonnumber1, uint buttonnumber2)
{
JoystickMapping mappOld = new JoystickMapping { joysticnumber = joysticknumber, buttonnumber = buttonnumber1 };
JoystickMapping mappNew = new JoystickMapping { joysticnumber = joysticknumber, buttonnumber = buttonnumber2 };
if (JoystickButtonMapping.ContainsKey(mappNew)) throw new ArgumentException("Button2 already exists");
if (!JoystickButtonMapping.ContainsKey(mappOld)) throw new ArgumentException("Button1 not existing");
var joystickHandler = JoystickButtonMapping[mappOld];
JoystickButtonMapping.Remove(mappOld);
JoystickButtonMapping.Add(mappNew, joystickHandler);
if (!JoystickButtonremaps.Contains((joysticknumber, buttonnumber1, buttonnumber2)))
JoystickButtonremaps.Add((joysticknumber, buttonnumber1, buttonnumber2));
}
public static void ClearRemappingLog()
{
JoystickButtonremaps.Clear();
MouseButtonremaps.Clear();
Keyremaps.Clear();
}
public static async Task UpdateOrSafeRemapsAsync(string filepath)
{
if (string.IsNullOrEmpty(filepath)) throw new ArgumentException(nameof(filepath));
if (File.Exists(filepath))
{
await UpdateRemapsAsync(filepath);
}
else
{
string directoryName = Path.GetDirectoryName(filepath);
if (directoryName != null) Directory.CreateDirectory(directoryName);
await SafeRemapsAsync(new FileStream(filepath, FileMode.Create));
}
}
private static async Task SafeRemapsAsync(FileStream fileStream)
{
using (StreamWriter writer = new StreamWriter(fileStream))
{
writer.WriteLine("<KeyMappings>");
foreach (var keyRemap in Keyremaps)
{
writer.WriteLine($"{keyRemap.Item1};{keyRemap.Item2}");
}
writer.WriteLine("</KeyMappings>");
writer.WriteLine("<MouseMappings>");
foreach (var mouseRemap in MouseButtonremaps)
{
writer.WriteLine($"{mouseRemap.Item1};{mouseRemap.Item2}");
}
writer.WriteLine("</MouseMappings>");
writer.WriteLine("<JoystickMappings>");
foreach (var joyRemap in JoystickButtonremaps)
{
writer.WriteLine($"{joyRemap.Item1};{joyRemap.Item2};{joyRemap.Item3}");
}
writer.WriteLine("</JoystickMappings>");
writer.Flush();
}
await fileStream.FlushAsync();
fileStream.Close();
}
private static async Task UpdateRemapsAsync(string filepath)
{
string Filecontent = null;
using (StreamReader reader = new StreamReader(filepath))
{
Filecontent = await reader.ReadToEndAsync();
}
string[] keyRemaps = ExtractMappings(Filecontent, "<KeyMappings>", "</KeyMappings>");
string[] mouseButtonRemaps = ExtractMappings(Filecontent, "<MouseMappings>", "</MouseMappings>");
string[] joyButtonRemaps = ExtractMappings(Filecontent, "<JoystickMappings>", "</JoystickMappings>");
Keyremaps.InsertRange(0, keyRemaps.Select(k => ParseKeyMapping(k)).ToArray());
MouseButtonremaps.InsertRange(0, mouseButtonRemaps.Select(m => ParseMouseMapping(m)).ToArray());
JoystickButtonremaps.InsertRange(0, joyButtonRemaps.Select(j => ParseJoystickMapping(j)).ToArray());
using (var fileStream = new FileStream(filepath, FileMode.Create))
{
await SafeRemapsAsync(fileStream);
}
}
private static string[] ExtractMappings(string content, string startTag, string endTag)
{
int start = content.IndexOf(startTag) + startTag.Length;
int end = content.IndexOf(endTag);
if (start < 0 || end < 0)
return new string[0]; // Falls das Tag nicht gefunden wurde
string mappings = content.Substring(start, end - start);
return mappings.Split(new[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries);
}
private static (Keyboard.Key, Keyboard.Key) ParseKeyMapping(string keyMapping)
{
var keys = keyMapping.Split(";");
return (Enum.Parse<Keyboard.Key>(keys[0]), Enum.Parse<Keyboard.Key>(keys[1]));
}
private static (Mouse.Button, Mouse.Button) ParseMouseMapping(string mouseMapping)
{
var buttons = mouseMapping.Split(";");
return (Enum.Parse<Mouse.Button>(buttons[0]), Enum.Parse<Mouse.Button>(buttons[1]));
}
private static (uint, uint, uint) ParseJoystickMapping(string joystickMapping)
{
var joyButtons = joystickMapping.Split(";");
return (uint.Parse(joyButtons[0]), uint.Parse(joyButtons[1]), uint.Parse(joyButtons[2]));
}
public static void revertLastKeyRemap()
{
if (Keyremaps.Any())
{
var lastKeyRemap = Keyremaps.Last();
Keyremaps.Remove(lastKeyRemap);
KeyboardMapping[lastKeyRemap.Item2] = KeyboardMapping[lastKeyRemap.Item1];
}
}
public static void revertLastMouseButtonRemap()
{
if (MouseButtonremaps.Any())
{
var lastMouseButtonRemap = MouseButtonremaps.Last();
MouseButtonremaps.Remove(lastMouseButtonRemap);
MouseButtonMapping[lastMouseButtonRemap.Item2] = MouseButtonMapping[lastMouseButtonRemap.Item1];
}
}
public static void revertLastJoystickButtonRemap()
{
if (JoystickButtonremaps.Any())
{
var lastJoystickButtonRemap = JoystickButtonremaps.Last();
JoystickButtonremaps.Remove(lastJoystickButtonRemap);
var mappOld = new JoystickMapping { joysticnumber = lastJoystickButtonRemap.Item1, buttonnumber = lastJoystickButtonRemap.Item2 };
var mappNew = new JoystickMapping { joysticnumber = lastJoystickButtonRemap.Item1, buttonnumber = lastJoystickButtonRemap.Item3 };
JoystickButtonMapping[mappNew] = JoystickButtonMapping[mappOld];
JoystickButtonMapping.Remove(mappOld);
}
}
public static void HandleKeyboardInput(Keyboard.Key key)
{
if (KeyboardMapping.ContainsKey(key))
{
KeyboardMapping[key](key); // Event auslösen
}
}
public static void HandleMouseInput(Mouse.Button button)
{
if (MouseButtonMapping.ContainsKey(button))
{
MouseButtonMapping[button](button);
}
}
public static void HandleJoystickButtonInput(uint joystickId, uint buttonNumber)
{
var joymap = new JoystickMapping { buttonnumber = buttonNumber, joysticnumber = joystickId };
if (JoystickButtonMapping.ContainsKey(joymap))
{
JoystickButtonMapping[joymap](joystickId, buttonNumber);
}
}
public static void HandleMouseMovement(Vector2i mouseposition)
{
MouseCursorPositionEvent?.Invoke(mouseposition);
}
public static void HandleJoytickMove(uint JoystickId, float x, float y, float z, float r, float u, float v, float PovX, float PovY)
{
JoystickAxisEvent?.Invoke(JoystickId, x, y, z, r, u, v);
JoystickHatEvent?.Invoke(JoystickId, PovX, PovY);
}
}
}
+104
View File
@@ -0,0 +1,104 @@
using Firebird2D.SceneSystem;
using SFML.Graphics;
using SFML.System;
using SFML.Window;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Threading.Tasks;
namespace Firebird2D.Core
{
public class MainWindow
{
private RenderWindow renderWindow;
private Clock clock = new Clock();
private List<uint> joyStickMovement = new List<uint>();
public Vector2u mainWindowSize { get; private set; }
internal I_Scene? ActiveSecene { set; get; }
public MainWindow(VideoMode resolution, string GameName, Styles style = Styles.Default)
{
renderWindow = new RenderWindow(resolution, GameName, style);
renderWindow.Closed += (sender, e) => renderWindow.Close();
renderWindow.Resized += RenderWindow_Resized;
mainWindowSize = renderWindow.Size;
renderWindow.KeyPressed += RenderWindow_KeyPressed;
renderWindow.JoystickButtonPressed += RenderWindow_JoystickButtonPressed;
renderWindow.MouseButtonPressed += RenderWindow_MouseButtonPressed;
renderWindow.MouseMoved += RenderWindow_MouseMoved;
renderWindow.JoystickMoved += RenderWindow_JoystickMoved;
}
private void RenderWindow_JoystickMoved(object? sender, JoystickMoveEventArgs e)
{
if(!joyStickMovement.Contains(e.JoystickId)) joyStickMovement.Add(e.JoystickId);
}
private void RenderWindow_MouseMoved(object? sender, MouseMoveEventArgs e)
{
Vector2i mousposition = new Vector2i(e.X, e.Y);
InputMapper.HandleMouseMovement(mousposition);
}
private void RenderWindow_MouseButtonPressed(object? sender, MouseButtonEventArgs e)
{
InputMapper.HandleMouseInput(e.Button);
}
private void RenderWindow_JoystickButtonPressed(object? sender, JoystickButtonEventArgs e)
{
InputMapper.HandleJoystickButtonInput(e.JoystickId, e.Button);
}
private void RenderWindow_KeyPressed(object? sender, KeyEventArgs e)
{
InputMapper.HandleKeyboardInput(e.Code);
}
private void RenderWindow_Resized(object? sender, SizeEventArgs e)
{
//throw new NotImplementedException();
}
public void Gameloop()
{
while (renderWindow.IsOpen)
{
int delteMiliseconds = clock.Restart().AsMilliseconds();
renderWindow.DispatchEvents();
renderWindow.Clear();
if (ActiveSecene != null)
{
foreach (uint joystickId in joyStickMovement)
InputMapper.HandleJoytickMove(joystickId
,Joystick.GetAxisPosition(joystickId,Joystick.Axis.X)
, Joystick.GetAxisPosition(joystickId, Joystick.Axis.Y)
, Joystick.GetAxisPosition(joystickId, Joystick.Axis.Z)
, Joystick.GetAxisPosition(joystickId, Joystick.Axis.R)
, Joystick.GetAxisPosition(joystickId, Joystick.Axis.U)
, Joystick.GetAxisPosition(joystickId, Joystick.Axis.V)
, Joystick.GetAxisPosition(joystickId, Joystick.Axis.PovX)
, Joystick.GetAxisPosition(joystickId, Joystick.Axis.PovY));
ActiveSecene.TickScene(delteMiliseconds);
ActiveSecene.RenderScene(renderWindow);
}
renderWindow.Display();
}
}
}
}
+133
View File
@@ -0,0 +1,133 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Firebird2D.Datatypes
{
public class AVL_Tree<T> : BinarySearchTree<T>
{
public AVL_Tree(IComparer<T> comparer) : base(comparer) { }
internal AVL_Tree(BinaryNode<T> node, IComparer<T> comparer) : base (node, comparer) {}
public new void InsertItem(T item)
{
InsertItem(item, ref root);
}
private void InsertItem(T item, ref BinaryNode<T>? node)
{
if(node == null)
{
node = new BinaryNode<T>(item);
}
else if (Comparer.Compare(item,node.content) < 0)
{
InsertItem(item, ref node.left);
}
else if (Comparer.Compare(item, node.content) > 0)
{
InsertItem(item, ref node.right);
}
else
{
InsertItem(item, ref node.left);
}
balanceTree(ref node);
}
public new void RemoveItem(T item)
{
}
private void RemoveItem(T item, ref BinaryNode<T>? node)
{
if (node != null)
{
if(Comparer.Compare(item, node.content) < 0)
{
RemoveItem(item, ref node.left);
}
else if (Comparer.Compare(item, node.content) > 0)
{
RemoveItem(item, ref node.right);
}
else if (Comparer.Compare(item, node.content) == 0)
{
if (node.left == null)
{
node = node.right;
}
else if (node.right == null)
{
node = node.left;
}
else
{
T newRoot = leastItem(node.right);
node.content = newRoot;
RemoveItem(newRoot, ref node.right);
}
}
}
else
{
return;
}
balanceTree(ref node);
}
private void balanceTree(ref BinaryNode<T> node)
{
if (node != null)
{
node.balanceFactor = height(node.left) - height(node.right);
if(node.balanceFactor <= -2)
{
rotateLeft(ref node);
}
if(node.balanceFactor >= 2)
{
rotateRight(ref node);
}
}
}
private void rotateLeft(ref BinaryNode<T> node)
{
if ( node.left.balanceFactor > 0)
{
rotateRight(ref node);
}
BinaryNode<T> oldRoot = node;
BinaryNode<T> newRoot = node.right;
oldRoot.right = newRoot.left;
newRoot.left = oldRoot;
node = newRoot;
}
private void rotateRight(ref BinaryNode<T> node)
{
if (node.left.balanceFactor < 0)
{
rotateLeft(ref node.left);
}
BinaryNode<T> oldRoot = node;
BinaryNode <T> newRoot = node.left;
oldRoot.left = newRoot.right;
newRoot.right = oldRoot;
node = newRoot;
}
}
}
+24
View File
@@ -0,0 +1,24 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Firebird2D.Datatypes
{
internal class BinaryNode<T>
{
public T content;
public int balanceFactor;
public BinaryNode<T>? left;
public BinaryNode<T>? right;
public BinaryNode(T item)
{
content = item;
left = null;
right = null;
}
}
}
+139
View File
@@ -0,0 +1,139 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Firebird2D.Datatypes
{
public class BinarySearchTree<T> : BinaryTree<T>
{
public int Height { get { return height(root); } }
protected readonly IComparer<T> Comparer;
public BinarySearchTree(IComparer<T> comparer)
{
root = null;
Comparer = comparer;
}
internal BinarySearchTree(BinaryNode<T> node, IComparer<T> comparer)
{
root = node;
Comparer = comparer;
}
public void InsertItem(T item)
{
InsertItem(item, ref root);
}
private void InsertItem(T item, ref BinaryNode<T>? node)
{
if (node == null)
{
node = new BinaryNode<T>(item);
}
else if(Comparer.Compare(item, node.content) < 0)
{
InsertItem(item, ref node.left);
}
else if(Comparer.Compare(item, node.content) > 0)
{
InsertItem(item, ref node.right);
}
}
internal int height(BinaryNode<T>? tree)
{
if(tree == null)
{
return 0;
}
else
{
return 1 + Math.Max(height(tree.left), height(tree.right));
}
}
public bool Contains(T item)
{
return Contains(item, root);
}
private bool Contains(T item, BinaryNode<T>? node)
{
if(node != null)
{
if(item.Equals(node.content))
return true;
if(Comparer.Compare(item, node.content) < 0)
{
return Contains(item, node.left);
}
else
{
return Contains(item, node.right);
}
}
else
{
return false;
}
}
public void RemoveItem(T item)
{
RemoveItem(item, ref root);
}
private void RemoveItem(T item, ref BinaryNode<T>? node)
{
if (node == null)
{
return;
}
else if (Comparer.Compare(item, node.content) < 0)
{
RemoveItem(item, ref node.left);
}
else if (Comparer.Compare(item, node.content) > 0)
{
RemoveItem(item, ref node.right);
}
if (item.Equals(node.content))
{
if(node.left == null)
{
node = node.right;
}
else if (node.right == null)
{
node = node.left;
}
else
{
T newRoot = leastItem(node.right);
node.content = newRoot;
RemoveItem(newRoot, ref node.right );
}
}
}
internal T leastItem(BinaryNode<T> node)
{
if(node.left == null)
{
return node.content;
}
else
{
return leastItem(node.left);
}
}
}
}
+137
View File
@@ -0,0 +1,137 @@
using System;
using System.Collections.Generic;
using System.Diagnostics.Metrics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Firebird2D.Datatypes
{
public abstract class BinaryTree<T>
{
internal BinaryNode<T> root = null;
public int Count { get {
int counter = 0;
count(root, ref counter);
return counter;
} }
public T[]? InOrder()
{
if (root == null)
return Array.Empty<T>();
List<T> result = new();
Stack<BinaryNode<T>> stack = new();
BinaryNode<T>? current = root;
while (current != null || stack.Count > 0)
{
// Gehe nach links, so weit wie möglich
while (current != null)
{
stack.Push(current);
current = current.left;
}
// Knoten aus dem Stack holen
current = stack.Pop();
result.Add(current.content);
// Gehe nach rechts
current = current.right;
}
return result.ToArray();
}
public T[]? PreOrder()
{
if (root == null)
return Array.Empty<T>();
List<T> result = new();
Stack<BinaryNode<T>> stack = new();
stack.Push(root);
while (stack.Count > 0)
{
// Knoten aus dem Stack holen
var current = stack.Pop();
result.Add(current.content);
// Zuerst den rechten Knoten hinzufügen (wird später bearbeitet)
if (current.right != null)
stack.Push(current.right);
// Dann den linken Knoten hinzufügen
if (current.left != null)
stack.Push(current.left);
}
return result.ToArray();
}
public T[]? PostOrder()
{
if (root == null)
return Array.Empty<T>();
List<T> result = new();
Stack<BinaryNode<T>> stack1 = new();
Stack<BinaryNode<T>> stack2 = new();
stack1.Push(root);
while (stack1.Count > 0)
{
// Knoten aus dem ersten Stack holen
var current = stack1.Pop();
stack2.Push(current);
// Linken und rechten Knoten in den ersten Stack schieben
if (current.left != null)
stack1.Push(current.left);
if (current.right != null)
stack1.Push(current.right);
}
// Ergebnis aus dem zweiten Stack lesen (umgekehrte Reihenfolge)
while (stack2.Count > 0)
{
result.Add(stack2.Pop().content);
}
return result.ToArray();
}
public void Copy(BinaryTree<T> tree2)
{
Copy(ref root, tree2.root);
}
private void Copy(ref BinaryNode<T>? tree, BinaryNode<T>? tree2)
{
if(tree == null && tree2 != null)
{
tree = new BinaryNode<T>(tree2.content);
}
if(tree != null && tree2 != null)
{
tree.content = tree2.content;
Copy(ref tree.left, tree2.left);
Copy(ref tree.right, tree2.right);
}
}
private void count(BinaryNode<T>? tree, ref int counter)
{
if (root != null)
{
counter++;
count(tree.left, ref counter);
count(tree.right, ref counter);
}
}
}
}
+14
View File
@@ -0,0 +1,14 @@
using SFML.Graphics;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Firebird2D.Datatypes
{
public interface ISpatial
{
public FloatRect Bounds { get; }
}
}
+257
View File
@@ -0,0 +1,257 @@
using Firebird2D.Requirement;
using SFML.Graphics;
using System.Diagnostics.CodeAnalysis;
using Firebird2D.SFMLExtensions;
using System.Drawing;
using SFML.System;
using System.Collections;
namespace Firebird2D.Datatypes
{
public class Quadtree<T> where T : ISpatial
{
private readonly List<T> _elements = [];
private readonly int _bucketCapacity;
private readonly int _maxDepth;
private Quadtree<T>? _topLeft, _topRight, _bottomLeft, _bottomRight;
public FloatRect Bounds { get; }
public int Level { get; init; }
[MemberNotNullWhen(false, nameof(_topLeft), nameof(_topRight), nameof(_bottomLeft), nameof(_bottomRight))]
public bool IsLeaf
=> _topLeft == null || _topRight == null || _bottomLeft == null || _bottomRight == null;
public bool AllowOutOfBounds { get; set; }
public Quadtree(FloatRect bounds, int bucketCapacity, int maxDepth)
{
Bounds = bounds;
_bucketCapacity = bucketCapacity;
_maxDepth = maxDepth;
}
public Quadtree(FloatRect bounds): this(bounds,32,5) { }
public void Insert(T element)
{
Require.NotNull(element, nameof(element));
if (!(Bounds.Contains(element.Bounds) || AllowOutOfBounds))
throw new ArgumentException(string.Format("{0} is out of Quadtreebounds", nameof(element)), nameof(element));
if (_elements.Count >= _bucketCapacity)
Split();
Quadtree<T>? containingChild = GetContainingChild(element.Bounds);
if (containingChild != null)
{
containingChild.Insert(element);
}
else
{
_elements.Add(element);
}
}
public bool Remove(T element)
{
Require.NotNull(element, nameof(element));
Quadtree<T>? containingChild = GetContainingChild(element.Bounds);
bool removed = containingChild?.Remove(element) ?? _elements.Remove(element);
if (removed && CountElements() <= _bucketCapacity)
Merge();
return removed;
}
public int CountElements()
{
int count = _elements.Count;
if(!IsLeaf)
{
count += _topLeft.CountElements();
count += _topRight.CountElements();
count += _bottomLeft.CountElements();
count += _bottomRight.CountElements();
}
return count;
}
public IEnumerable<T> GetElements()
{
List<T> children = new();
Queue<Quadtree<T>> nodes = new Queue<Quadtree<T>>();
nodes.Enqueue(this);
while (nodes.Count > 0)
{
Quadtree<T> node = nodes.Dequeue();
if (!node.IsLeaf)
{
nodes.Enqueue(node._topLeft);
nodes.Enqueue(node._topRight);
nodes.Enqueue(node._bottomLeft);
nodes.Enqueue(node._bottomRight);
}
children.AddRange(node._elements);
}
return children;
}
private void Split()
{
if (!IsLeaf)
return;
if (Level + 1 > _maxDepth)
return;
_topLeft = CreateChild(Bounds.Location());
_topRight = CreateChild(new Vector2f(Bounds.Center().X, Bounds.Location().Y));
_bottomLeft = CreateChild(new Vector2f(Bounds.Location().X, Bounds.Center().Y));
_bottomRight = CreateChild(Bounds.Center());
List<T> elements = _elements.ToList();
foreach (T element in elements)
{
Quadtree<T>? containingChild = GetContainingChild(element.Bounds);
if (containingChild != null)
{
_elements.Remove(element);
containingChild.Insert(element);
}
}
}
private Quadtree<T> CreateChild(Vector2f location)
=> new(new FloatRect(location, Bounds.Size / 2), _bucketCapacity, _maxDepth) { Level = Level + 1 };
private void Merge()
{
if (IsLeaf)
return;
_elements.AddRange(_topLeft._elements);
_elements.AddRange(_topRight._elements);
_elements.AddRange(_bottomLeft._elements);
_elements.AddRange(_bottomRight._elements);
_topLeft = _topRight = _bottomLeft = _bottomRight = null;
}
private Quadtree<T>? GetContainingChild(FloatRect bounds)
{
if (IsLeaf)
return null;
if(_topLeft.Bounds.Contains(bounds))
return _topLeft;
if (_topRight.Bounds.Contains(bounds))
return _topRight;
if (_bottomLeft.Bounds.Contains(bounds))
return _bottomLeft;
if (_bottomRight.Bounds.Contains(bounds))
return _bottomRight;
return null;
}
public IEnumerable<T> FindCollisions(T element)
{
Require.NotNull(element, nameof(element));
var nodes = new Queue<Quadtree<T>>();
var collisions = new List<T>();
nodes.Enqueue(this);
while (nodes.Count > 0)
{
var node = nodes.Dequeue();
if (!element.Bounds.Intersects(node.Bounds))
continue;
collisions.AddRange(node._elements.Where(e => e.Bounds.Intersects(element.Bounds)));
if (!node.IsLeaf)
{
if (element.Bounds.Intersects(node._topLeft.Bounds))
nodes.Enqueue(node._topLeft);
if (element.Bounds.Intersects(node._topRight.Bounds))
nodes.Enqueue(node._topRight);
if (element.Bounds.Intersects(node._bottomLeft.Bounds))
nodes.Enqueue(node._bottomLeft);
if (element.Bounds.Intersects(node._bottomRight.Bounds))
nodes.Enqueue(node._bottomRight);
}
}
return collisions;
}
public IEnumerable<T> FindInRegion(FloatRect region)
{
var results = new List<T>();
var stack = new Stack<Quadtree<T>>();
stack.Push(this);
while (stack.Count > 0)
{
var node = stack.Pop();
if (!node.Bounds.Intersects(region))
continue;
results.AddRange(node._elements.Where(e => region.Intersects(e.Bounds)));
if (!node.IsLeaf)
{
stack.Push(node._topLeft);
stack.Push(node._topRight);
stack.Push(node._bottomLeft);
stack.Push(node._bottomRight);
}
}
return results;
}
public AVL_Tree<T> FindInRegionAVL(FloatRect region, IComparer<T> comparer)
{
List<T> values = (List<T>)FindInRegion(region);
AVL_Tree<T> returnTree = new(comparer);
foreach (T elment in values)
{
returnTree.InsertItem(elment);
}
return returnTree;
}
}
}
+29
View File
@@ -0,0 +1,29 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Configuration" Version="9.0.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="9.0.0" />
<PackageReference Include="Newtonsoft.Json.Schema" Version="4.0.1" />
<PackageReference Include="SFML.Net" Version="2.6.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Firebird2D.Logger\Firebird2D.Logger.csproj" />
<ProjectReference Include="..\Firebird2D.Requirement\Firebird2D.Requirement.csproj" />
<ProjectReference Include="..\Firebird2D.SFMLExtensions\Firebird2D.SFMLExtensions.csproj" />
</ItemGroup>
<ItemGroup>
<None Update="Configuration\ConfigurationSchema\ConfigSchema.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>
</Project>
+40
View File
@@ -0,0 +1,40 @@
using SFML.Graphics;
using SFML.Window;
using SFML.System;
using Microsoft.Extensions.Configuration;
using System.Text;
using Firebird2D.Core;
using Firebird2D.Configuration;
using Firebird2D.Logger;
using Firebird2D.SceneSystem;
namespace Firebird2D
{
public static class GameSystem
{
public static MainWindow? mainWindow {get; private set;}
public static GameConfig gameConfig = new GameConfig();
static void Main(string[] args)
{
GameLogger.Initalize();
if (VideoMode.DesktopMode.Width < gameConfig.VideoMode.Width || VideoMode.DesktopMode.Height < gameConfig.VideoMode.Height)
{
gameConfig.VideoMode = VideoMode.DesktopMode;
}
Styles style = gameConfig.FullScreen ? Styles.Fullscreen : Styles.Default;
mainWindow = new MainWindow(gameConfig.VideoMode, "testgame", style);
SceneManager.LoadScenes(mainWindow);
mainWindow.Gameloop();
}
}
}
@@ -0,0 +1,102 @@
using SFML.Graphics;
using SFML.System;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Firebird2D.SceneSystem.Actors
{
public enum ResizeMode
{
Resize,
DontResize,
CutImage
}
public enum AnchorPoint
{
topLeft,
topMiddle,
topRight,
bottomLeft,
bottomMiddle,
bottomRight,
LeftMiddle,
RightMiddle,
Center
}
public enum AnchorMode
{
stayInValue,
stayInRatio,
stayInPlace
}
public struct Anchors
{
public bool top;
public bool left;
public bool right;
public bool bottom;
AnchorPoint anchorPoint;
AnchorMode anchorMode;
public Anchors() : this(true, true, false, false, AnchorPoint.Center, AnchorMode.stayInValue) { }
public Anchors(bool top, bool left, bool right, bool bottom) : this(top, left, right, bottom, AnchorPoint.Center, AnchorMode.stayInValue) { }
public Anchors(bool top, bool left, bool right, bool bottom, AnchorPoint anchorPoint) : this(top, left, right, bottom, anchorPoint, AnchorMode.stayInValue) { }
public Anchors(bool top, bool left, bool right, bool bottom, AnchorPoint anchorPoint, AnchorMode anchorMode)
{
this.top = top;
this.left = left;
this.right = right;
this.bottom = bottom;
this.anchorPoint = anchorPoint;
this.anchorMode = anchorMode;
}
}
public interface IRenderable
{
public void Render(RenderWindow window);
}
public interface IUpdatable
{
void Tick(int timeDifference);
}
public interface IResizable : IRenderable
{
void Resize(int width, int height);
void OnWindowResize(int width, int height);
}
public interface I_BaseActor : IRenderable, IUpdatable, IComparable
{
public string Name { get; }
public ResizeMode resizeMode { get; set; }
public Anchors Anchors { get; set; }
public Vector2f Position { get; set; }
public Vector2f Size { get; set; }
public float Rotation { get; set; }
public int Z_Index { get; set; }
}
}
@@ -0,0 +1,13 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Firebird2D.SceneSystem.Actors
{
public interface I_Clickable : I_BaseActor
{
public event EventHandler Click;
}
}
@@ -0,0 +1,12 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Firebird2D.SceneSystem.Actors
{
public interface I_HitboxActor
{
}
}
@@ -0,0 +1,13 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Firebird2D.SceneSystem.Actors
{
public interface I_InteractableActor : I_BaseActor
{
public bool Interact(I_PlayerActor player);
}
}
@@ -0,0 +1,13 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Firebird2D.SceneSystem.Actors
{
public interface I_PlayerActor : I_BaseActor
{
}
}
+33
View File
@@ -0,0 +1,33 @@
using Firebird2D.SceneSystem.Actors;
using SFML.Graphics;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Firebird2D.SceneSystem
{
public interface I_Scene
{
public string Name { get; }
public I_PlayerActor Player { get; }
public List<I_InteractableActor> Interactable { get; }
public List<I_HitboxActor> Hitbox { get; }
public List<I_Clickable> Clickables{ get; }
public I_Scene BuildScene();
public void DestroyScene();
public void TickScene(int TimeDifference);
public void RenderScene(RenderWindow window);
public void addActor(I_BaseActor Actor);
}
}
+32
View File
@@ -0,0 +1,32 @@
using Firebird2D.SceneSystem.Actors;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Firebird2D.SceneSystem
{
public abstract class SceneGroup
{
public string? GroupName { get; protected set; }
public List<I_Scene>? Scenes { get; protected set; }
public abstract I_Scene SceneChangeAnimation { get; protected set; }
public abstract void InitializeGroup();
public abstract I_Scene getStartingScene();
public I_Scene? Get_Scene(Type type)
{
if (type != typeof(I_Scene) || Scenes == null) return null;
return Scenes.FirstOrDefault(instance => instance.GetType() == type);
}
}
}
+94
View File
@@ -0,0 +1,94 @@
using Firebird2D.Core;
using Firebird2D.SceneSystem.Actors;
using SFML.Graphics;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
namespace Firebird2D.SceneSystem
{
public static class SceneManager
{
//static List<I_Scene> scenes = new List<I_Scene>();
static string scenesPath = "scenes.dll";
static Assembly sceneDll = null;
static MainWindow mainWindow = null;
static SceneGroup ActiveSceneGroup = null;
public static void LoadScenes(MainWindow renderWindow)
{
if (mainWindow == null) return; // todo wenn render window null
mainWindow = renderWindow;
sceneDll = Assembly.Load(scenesPath);
if (sceneDll == null) return; //Todo wenn scenes nicht geladen werden fehler
Type? scenesConfig = sceneDll.GetType("Scenes.Config");
if (scenesConfig == null) return; //Todo wenn die scenes config nicht gefunden wird
FieldInfo? startSceneGroup = scenesConfig.GetField("startingGroup", BindingFlags.Public | BindingFlags.Static);
if (startSceneGroup == null) return;// Todo wenn die scenes config nicht gefunden wird
SceneGroup? startingGroup = startSceneGroup.GetValue(null) as SceneGroup;
if (startingGroup == null) return;//Todo wenn die scenes config nicht gefunden wird
LoadSceneGroup(startingGroup, null);
}
private static async void LoadSceneGroup(SceneGroup sceneGroup, List<I_BaseActor>? carryOverActors)
{
if (sceneGroup == null) return; //todoo wenn scene group null
ActiveSceneGroup = sceneGroup;
changeScene(sceneGroup.SceneChangeAnimation, carryOverActors);
// Asynchrone Initialisierung der Szene im Hintergrund
await Task.Run(() => sceneGroup.InitializeGroup());
}
public static void changeScene(Type type, List<I_BaseActor> carryOverActors)
{
if (type != typeof(I_Scene)) return;
I_Scene? scene = ActiveSceneGroup.Get_Scene(type);
changeScene(scene,carryOverActors);
}
private static void changeScene(I_Scene? scene, List<I_BaseActor>? carryOverActors)
{
if (scene == null) return; //todo reaction
if (mainWindow.ActiveSecene != null)
mainWindow.ActiveSecene.DestroyScene();
if (carryOverActors != null)
foreach (I_BaseActor actor in carryOverActors)
{
scene.addActor(actor);
}
mainWindow.ActiveSecene = scene.BuildScene();
}
public static void changeGroup(SceneGroup nextSceneGroup, List<I_BaseActor> carryOverActors)
{
LoadSceneGroup(nextSceneGroup, carryOverActors);
}
}
}
@@ -0,0 +1,22 @@
{
"type": "object",
"properties": {
"AppSettings": {
"type": "object",
"properties": {
"ScreenResolution": {
"type": "object",
"properties": {
"x": { "type": "integer" },
"y": { "type": "integer" }
},
"required": [ "x", "y" ]
},
"Fullscreen": { "type": "boolean" },
"Log" : {"type": "boolean"}
},
"Required": [ "ScreenResolution", "Fullscreen", "Log" ]
}
},
"Required" : ["AppSettings"]
}
@@ -0,0 +1 @@
{ "AppSettings":{ "ScreenResolution": { "x": 3840, "y": 2160 }, "Fullscreen": false, "Log": true, }}
File diff suppressed because it is too large Load Diff
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,12 @@
{
"runtimeOptions": {
"tfm": "net8.0",
"framework": {
"name": "Microsoft.NETCore.App",
"version": "8.0.0"
},
"configProperties": {
"System.Runtime.Serialization.EnableUnsafeBinaryFormatterSerialization": false
}
}
}
+1
View File
@@ -0,0 +1 @@
===================08,12,24===================
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1 @@
{ "AppSettings":{ "ScreenResolution": { "X": 3840, "Y": 2160 }, "Fullscreen": false }}

Some files were not shown because too many files have changed in this diff Show More