### Initialize and Apply Custom Shaders in Foster Source: https://context7.com/fosterframework/foster/llms.txt This example demonstrates loading driver-specific shader bytecode, creating vertex and fragment shader instances, and assigning them to a material for rendering. It also shows how to update uniform buffers dynamically during the update loop. ```csharp using Foster.Framework; public class ShaderExample : App { private Shader vertexShader; private Shader fragmentShader; private Material customMaterial; private Batcher batcher; private Texture texture; public ShaderExample() : base("Shader Demo", 800, 600) { } protected override void Startup() { batcher = new Batcher(GraphicsDevice); texture = new Texture(GraphicsDevice, new Image("sprite.png")); byte[] vertexCode = GraphicsDevice.Driver switch { GraphicsDriver.Vulkan => File.ReadAllBytes("shaders/custom.vertex.spv"), GraphicsDriver.D3D12 => File.ReadAllBytes("shaders/custom.vertex.dxil"), GraphicsDriver.Metal => File.ReadAllBytes("shaders/custom.vertex.msl"), _ => throw new Exception("Unsupported driver") }; byte[] fragmentCode = GraphicsDevice.Driver switch { GraphicsDriver.Vulkan => File.ReadAllBytes("shaders/custom.fragment.spv"), GraphicsDriver.D3D12 => File.ReadAllBytes("shaders/custom.fragment.dxil"), GraphicsDriver.Metal => File.ReadAllBytes("shaders/custom.fragment.msl"), _ => throw new Exception("Unsupported driver") }; vertexShader = new Shader(GraphicsDevice, stage: ShaderStage.Vertex, code: vertexCode, samplerCount: 0, uniformBufferCount: 1, entryPoint: "main"); fragmentShader = new Shader(GraphicsDevice, stage: ShaderStage.Fragment, code: fragmentCode, samplerCount: 1, uniformBufferCount: 1, entryPoint: "main"); customMaterial = new Material(); customMaterial.Vertex.Shader = vertexShader; customMaterial.Fragment.Shader = fragmentShader; customMaterial.Fragment.SetUniformBuffer([0f], slot: 0); } protected override void Update() { float time = (float)Time.Elapsed.TotalSeconds; customMaterial.Fragment.SetUniformBuffer([time], slot: 0); } protected override void Render() { Window.Clear(Color.Black); batcher.Clear(); batcher.PushMaterial(customMaterial); batcher.Image(texture, new System.Numerics.Vector2(100, 100), Color.White); batcher.PopMaterial(); batcher.Render(Window); } protected override void Shutdown() { vertexShader.Dispose(); fragmentShader.Dispose(); texture.Dispose(); batcher.Dispose(); } } ``` -------------------------------- ### Render to Texture with Foster Framework Source: https://context7.com/fosterframework/foster/llms.txt Demonstrates creating and using a render target in Foster Framework. It shows how to initialize a target, render graphics to it using a Batcher, and then display the target's texture on the main window, including scaling and nearest-neighbor filtering for a pixel-art effect. The example also includes cleanup for disposed resources. ```csharp using Foster.Framework; using System.Numerics; public class TargetExample : App { private Target renderTarget; private Batcher batcher; private Texture sprite; public TargetExample() : base("Render Target Demo", 800, 600) { } protected override void Startup() { batcher = new Batcher(GraphicsDevice); sprite = new Texture(GraphicsDevice, new Image("sprite.png")); // Create a render target (defaults to single Color attachment) renderTarget = new Target(GraphicsDevice, 320, 180); // Create with specific format // renderTarget = new Target(GraphicsDevice, 320, 180, // [TextureFormat.Color], TextureFlags.None); // Create with multiple attachments (for MRT) // renderTarget = new Target(GraphicsDevice, 320, 180, [ // (TextureFormat.Color, TextureFlags.None, SampleCount.One), // (TextureFormat.Color, TextureFlags.None, SampleCount.One) // ]); } protected override void Render() { // Render scene to the target first GraphicsDevice.Clear(renderTarget, Color.CornflowerBlue, 0, ClearMask.All); batcher.Clear(); batcher.Image(sprite, new Vector2(50, 50), Color.White); batcher.Circle(new Vector2(160, 90), 30, 32, Color.Red); batcher.Render(renderTarget); // Now render the target to the window (scaled up) Window.Clear(Color.Black); batcher.Clear(); // Target implicitly converts to its first texture attachment Texture targetTexture = renderTarget; // Draw scaled up for pixel-art effect batcher.PushSampler(new TextureSampler(TextureFilter.Nearest, TextureWrap.Clamp)); batcher.Image(targetTexture, position: Vector2.Zero, origin: Vector2.Zero, scale: new Vector2(2.5f, 2.5f), // Scale up rotation: 0, color: Color.White); batcher.PopSampler(); batcher.Render(Window); } protected override void Update() { } protected override void Startup() { } protected override void Shutdown() { renderTarget.Dispose(); sprite.Dispose(); batcher.Dispose(); } } ``` -------------------------------- ### Rendering 2D Graphics with Batcher Source: https://context7.com/fosterframework/foster/llms.txt This example demonstrates how to initialize a Batcher and use it to render various shapes, textures, and transformations. It covers advanced features like matrix stacks, blend modes, and scissor clipping. ```csharp using Foster.Framework; using System.Numerics; public class BatcherExample : App { private Batcher batcher; private Texture texture; public BatcherExample() : base("Batcher Demo", 800, 600) { } protected override void Startup() { batcher = new Batcher(GraphicsDevice); texture = new Texture(GraphicsDevice, new Image("sprite.png")); } protected override void Render() { Window.Clear(Color.Black); batcher.Clear(); batcher.Rect(10, 10, 100, 50, Color.Red); batcher.RectLine(new Rect(120, 10, 100, 50), 2f, Color.Green); batcher.Circle(new Vector2(300, 35), 25, 32, Color.Blue); batcher.CircleLine(new Vector2(380, 35), 25, 2f, 32, Color.Yellow); batcher.Line(new Vector2(420, 10), new Vector2(500, 60), 2f, Color.White); batcher.Triangle(new Vector2(550, 60), new Vector2(520, 10), new Vector2(580, 10), Color.Magenta); batcher.RectRounded(10, 80, 100, 50, 10f, Color.Orange); batcher.RectRoundedLine(new Rect(120, 80, 100, 50), 10f, 2f, Color.Cyan); batcher.Image(texture, new Vector2(10, 150), Color.White); batcher.Image(texture, position: new Vector2(200, 200), origin: new Vector2(texture.Width / 2f, texture.Height / 2f), scale: new Vector2(2f, 2f), rotation: Time.Elapsed.Seconds * MathF.PI, color: Color.White); batcher.PushMatrix(new Vector2(400, 200)); batcher.Rect(0, 0, 50, 50, Color.Red); batcher.PushMatrix(Vector2.Zero, new Vector2(1.5f, 1.5f), MathF.PI / 4); batcher.Rect(60, 0, 50, 50, Color.Green); batcher.PopMatrix(); batcher.PopMatrix(); batcher.PushBlend(BlendMode.Add); batcher.Circle(new Vector2(500, 300), 50, 32, new Color(255, 0, 0, 128)); batcher.Circle(new Vector2(530, 300), 50, 32, new Color(0, 255, 0, 128)); batcher.PopBlend(); batcher.PushScissor(new RectInt(10, 300, 100, 100)); batcher.Rect(0, 290, 200, 50, Color.White); batcher.PopScissor(); batcher.PushMode(Batcher.Modes.Wash); batcher.Image(texture, new Vector2(10, 420), Color.Red); batcher.PopMode(); batcher.Render(Window); } protected override void Shutdown() { texture.Dispose(); batcher.Dispose(); } } ``` -------------------------------- ### Virtual Input Example in C# Source: https://context7.com/fosterframework/foster/llms.txt Demonstrates the usage of VirtualInput classes for handling player input in a game. It shows how to set up virtual actions, axes, and sticks, bind them to physical inputs like keys and buttons, and use their states for game logic such as jumping and movement. Includes input buffering, repeat delays, and deadzone configurations. ```csharp using Foster.Framework; using System.Numerics; public class VirtualInputExample : App { private Batcher batcher; private VirtualAction jumpAction; private VirtualAxis horizontalAxis; private VirtualStick moveStick; private Vector2 playerPos = new(400, 300); public VirtualInputExample() : base("Virtual Input Demo", 800, 600) { } protected override void Startup() { batcher = new Batcher(GraphicsDevice); // Create a virtual action (button) with input buffer jumpAction = new VirtualAction(Input, "Jump", buffer: 0.1f) { RepeatDelay = 0.4f, // Time before repeat starts RepeatInterval = 0.1f // Time between repeats }; // Bind multiple inputs to the jump action jumpAction.Entries.Add(new() { Key = Keys.Space }); jumpAction.Entries.Add(new() { Key = Keys.W }); jumpAction.Entries.Add(new() { Key = Keys.Up }); jumpAction.Entries.Add(new() { Button = Buttons.A }); // Create a virtual axis (-1 to 1) horizontalAxis = new VirtualAxis(Input, "Horizontal"); horizontalAxis.Entries.Add(new() { Negative = Keys.A, Positive = Keys.D }); horizontalAxis.Entries.Add(new() { Negative = Keys.Left, Positive = Keys.Right }); horizontalAxis.Entries.Add(new() { Axis = Axes.LeftX, Deadzone = 0.2f }); // Create a virtual stick (2D input) moveStick = new VirtualStick(Input, "Move"); moveStick.Entries.Add(new() { Up = Keys.W, Down = Keys.S, Left = Keys.A, Right = Keys.D }); moveStick.Entries.Add(new() { Up = Keys.Up, Down = Keys.Down, Left = Keys.Left, Right = Keys.Right }); moveStick.Entries.Add(new() { HorizontalAxis = Axes.LeftX, VerticalAxis = Axes.LeftY, Deadzone = 0.2f }); } protected override void Update() { // Check virtual action states if (jumpAction.Pressed) { Log.Info("Jump pressed!"); // Input buffering means Pressed can be true for a short window } if (jumpAction.Repeated) { Log.Info("Jump repeated (held)"); } // Consume the press (prevents re-triggering in other systems) if (jumpAction.ConsumePress()) { // Handle the jump } // Use axis for horizontal movement float horizontal = horizontalAxis.Value; // -1 to 1 playerPos.X += horizontal * 200f * Time.Delta; // Use stick for 2D movement Vector2 movement = moveStick.Value; // Normalized Vector2 if (movement.Length() > 0.1f) { playerPos += movement * 200f * Time.Delta; } // Virtual inputs track timing if (jumpAction.Down) { var heldTime = Time.Elapsed - jumpAction.Timestamp; // Charge attack based on hold time, etc. } } protected override void Render() { Window.Clear(Color.DarkGray); batcher.Clear(); batcher.Circle(playerPos, 25, 32, Color.Cyan); batcher.Render(Window); } protected override void Shutdown() { jumpAction.Dispose(); horizontalAxis.Dispose(); moveStick.Dispose(); batcher.Dispose(); } } ``` -------------------------------- ### Create and Manage GPU Textures in C# Source: https://context7.com/fosterframework/foster/llms.txt Demonstrates the creation of GPU textures from various sources including image files, raw pixel data, and empty initializations. It also shows how to update texture data, read data back, clone textures, and perform blitting operations for copying texture regions. This example utilizes the Foster Framework's Texture and Batcher classes. ```csharp using Foster.Framework; public class TextureExample : App { private Texture textureFromImage; private Texture textureFromPixels; private Texture textureEmpty; private Batcher batcher; public TextureExample() : base("Texture Demo", 800, 600) { } protected override void Startup() { batcher = new Batcher(GraphicsDevice); // Create texture from image file var image = new Image("character.png"); textureFromImage = new Texture(GraphicsDevice, image); // Create texture directly from file path // textureFromImage = new Texture(GraphicsDevice, new Image("character.png")); // Create texture from pixel data var pixels = new Color[64 * 64]; for (int y = 0; y < 64; y++) for (int x = 0; x < 64; x++) { pixels[x + y * 64] = ((x + y) % 2 == 0) ? Color.White : Color.Black; } textureFromPixels = new Texture(GraphicsDevice, 64, 64, pixels); // Create empty texture and set data later textureEmpty = new Texture(GraphicsDevice, 32, 32, TextureFormat.Color); var redPixels = new Color[32 * 32]; Array.Fill(redPixels, Color.Red); textureEmpty.SetData(redPixels); // Set partial data (update a region) var bluePixels = new Color[16 * 16]; Array.Fill(bluePixels, Color.Blue); textureEmpty.SetData(bluePixels, new RectInt(8, 8, 16, 16)); // Read texture data back var readBack = new Color[32 * 32]; textureEmpty.GetData(readBack); // Clone a texture var cloned = textureFromImage.Clone(); // Blit (copy) between textures textureFromImage.Blit( sourceRect: new RectInt(0, 0, 32, 32), destination: textureEmpty, destinationRect: new RectInt(0, 0, 32, 32), filter: TextureFilter.Nearest ); } protected override void Render() { Window.Clear(Color.DarkGray); batcher.Clear(); batcher.Image(textureFromImage, new System.Numerics.Vector2(10, 10), Color.White); batcher.Image(textureFromPixels, new System.Numerics.Vector2(200, 10), Color.White); batcher.Image(textureEmpty, new System.Numerics.Vector2(300, 10), Color.White); batcher.Render(Window); } protected override void Update() { } protected override void Shutdown() { textureFromImage.Dispose(); textureFromPixels.Dispose(); textureEmpty.Dispose(); batcher.Dispose(); } } ``` -------------------------------- ### Batcher - 2D Sprite Batching Source: https://context7.com/fosterframework/foster/llms.txt This example demonstrates the core functionalities of the Batcher class for 2D rendering in Foster.Framework. It covers drawing various shapes, images, applying transformations, and utilizing blend modes and scissor clipping. ```APIDOC ## Batcher - 2D Sprite Batching ### Description The Batcher is the primary class for 2D rendering. It batches draw calls efficiently and supports shapes, textures, transforms, blend modes, and more. ### Usage Example This C# code snippet illustrates how to initialize and use the `Batcher` class within a Foster.Framework application. ```csharp using Foster.Framework; using System.Numerics; public class BatcherExample : App { private Batcher batcher; private Texture texture; public BatcherExample() : base("Batcher Demo", 800, 600) { } protected override void Startup() { batcher = new Batcher(GraphicsDevice); texture = new Texture(GraphicsDevice, new Image("sprite.png")); } protected override void Render() { Window.Clear(Color.Black); batcher.Clear(); // Draw shapes batcher.Rect(10, 10, 100, 50, Color.Red); batcher.RectLine(new Rect(120, 10, 100, 50), 2f, Color.Green); batcher.Circle(new Vector2(300, 35), 25, 32, Color.Blue); batcher.CircleLine(new Vector2(380, 35), 25, 2f, 32, Color.Yellow); batcher.Line(new Vector2(420, 10), new Vector2(500, 60), 2f, Color.White); batcher.Triangle(new Vector2(550, 60), new Vector2(520, 10), new Vector2(580, 10), Color.Magenta); // Rounded rectangles batcher.RectRounded(10, 80, 100, 50, 10f, Color.Orange); batcher.RectRoundedLine(new Rect(120, 80, 100, 50), 10f, 2f, Color.Cyan); // Draw textures/images batcher.Image(texture, new Vector2(10, 150), Color.White); // Draw with transform (position, origin, scale, rotation) batcher.Image(texture, position: new Vector2(200, 200), origin: new Vector2(texture.Width / 2f, texture.Height / 2f), scale: new Vector2(2f, 2f), rotation: Time.Elapsed.Seconds * MathF.PI, // Rotate over time color: Color.White); // Use matrix transformations batcher.PushMatrix(new Vector2(400, 200)); // Translate batcher.Rect(0, 0, 50, 50, Color.Red); batcher.PushMatrix(Vector2.Zero, new Vector2(1.5f, 1.5f), MathF.PI / 4); // Scale and rotate batcher.Rect(60, 0, 50, 50, Color.Green); batcher.PopMatrix(); batcher.PopMatrix(); // Blend modes batcher.PushBlend(BlendMode.Add); batcher.Circle(new Vector2(500, 300), 50, 32, new Color(255, 0, 0, 128)); batcher.Circle(new Vector2(530, 300), 50, 32, new Color(0, 255, 0, 128)); batcher.PopBlend(); // Scissor clipping batcher.PushScissor(new RectInt(10, 300, 100, 100)); batcher.Rect(0, 290, 200, 50, Color.White); // Only visible portion is drawn batcher.PopScissor(); // Draw modes (Normal, Wash, Fill) batcher.PushMode(Batcher.Modes.Wash); // Use texture alpha with solid color batcher.Image(texture, new Vector2(10, 420), Color.Red); batcher.PopMode(); batcher.Render(Window); } protected override void Update() { } protected override void Shutdown() { texture.Dispose(); batcher.Dispose(); } } ``` ### Key Features * **Shape Drawing**: Supports rectangles, lines, circles, and triangles with customizable colors and line thickness. * **Texture Rendering**: Efficiently draws textures and images with support for transformations (position, origin, scale, rotation). * **Matrix Transformations**: Allows for complex transformations using `PushMatrix` and `PopMatrix`. * **Blend Modes**: Enables additive blending and other modes for advanced visual effects. * **Scissor Clipping**: Restricts rendering to a specified rectangular area. * **Draw Modes**: Supports different drawing modes like `Wash` for applying color with texture alpha. ### Resource Management Ensure that `Batcher` and `Texture` resources are properly disposed of when they are no longer needed, typically in the `Shutdown` method. ``` -------------------------------- ### RGBA Color Utilities in C# Source: https://context7.com/fosterframework/foster/llms.txt Demonstrates the creation, manipulation, and conversion of RGBA colors using the Foster.Framework.Color struct. Includes examples of constructors, predefined colors, component access, vector conversions, HSV operations, and hex string parsing. ```csharp using Foster.Framework; using System.Numerics; public class ColorExample { public void DemonstrateColors() { // Create colors var white = new Color(255, 255, 255, 255); var red = new Color(1.0f, 0f, 0f, 1.0f); // Float constructor (0-1) var fromInt = new Color(0xFF00FF); // RGB hex (no alpha) var fromUint = new Color(0xFF00FFFF); // RGBA hex var fromVector = new Color(new Vector4(1, 0.5f, 0.25f, 1)); // Predefined colors (CSS3 standard) Color c = Color.CornflowerBlue; c = Color.Transparent; c = Color.Red; c = Color.Green; c = Color.Blue; c = Color.White; c = Color.Black; c = Color.Gray; // Access components byte r = c.R, g = c.G, b = c.B, a = c.A; // Get as packed integer uint rgba = c.RGBA; uint abgr = c.ABGR; // Convert to vectors Vector4 vec4 = c.ToVector4(); Vector3 vec3 = c.ToVector3(); // Implicit conversions Vector4 asVec = Color.Red; Color fromVec = new Vector4(1, 0, 0, 1); // Lerp between colors Color mixed = Color.Lerp(Color.Red, Color.Blue, 0.5f); // Purple // Premultiply alpha (for correct blending) var semiTransparent = new Color(255, 0, 0, 128); Color premultiplied = semiTransparent.Premultiply(); // HSV conversion var (h, s, v) = Color.Red.ToHSV(); Color fromHsv = Color.FromHSV(0.5f, 1f, 1f); // Cyan (hue 0.5 = 180 degrees) // Hex string conversion string hexRgb = Color.Red.ToHexStringRGB(); // "FF0000" string hexRgba = Color.Red.ToHexStringRGBA(); // "FF0000FF" // Parse from hex string Color parsed = Color.FromHexStringRGB("#FF00FF"); Color parsedRgba = Color.FromHexStringRGBA("FF00FF80"); // Custom component order string customHex = Color.Red.ToHexString("ARGB"); // "FFFF0000" Color customParsed = Color.FromHexString("ARGB", "80FF0000"); // Multiply by scalar Color dimmed = Color.White * 0.5f; // Half brightness // Grayscale helper Color gray = Color.Grayscale(128, 255); // RGB all 128, full alpha } } ``` -------------------------------- ### C# Window Management in Foster Framework Source: https://context7.com/fosterframework/foster/llms.txt Demonstrates how to initialize an application window with specific configurations, access and modify window properties like title, size, and fullscreen status, and subscribe to various window events such as resizing, focus changes, and close requests. It also shows how to control VSync and mouse capture modes. ```csharp using Foster.Framework; public class WindowExample : App { private Batcher batcher; public WindowExample() : base(new AppConfig( ApplicationName: "Window Demo", WindowTitle: "My Game Window", Width: 1280, Height: 720, Fullscreen: false, Resizable: true )) { } protected override void Startup() { batcher = new Batcher(GraphicsDevice); // Window properties string title = Window.Title; Window.Title = "New Title"; int width = Window.Width; int height = Window.Height; Point2 size = Window.Size; bool focused = Window.Focused; bool visible = Window.Visible; bool minimized = Window.Minimized; bool maximized = Window.Maximized; bool fullscreen = Window.Fullscreen; // Modify window state Window.Fullscreen = true; // Toggle fullscreen Window.Fullscreen = false; // Subscribe to window events Window.OnResized += () => { Log.Info($"Window resized to {Window.Width}x{Window.Height}"); }; Window.OnFocusGained += () => Log.Info("Window focused"); Window.OnFocusLost += () => Log.Info("Window lost focus"); Window.OnCloseRequested += () => { // Can prevent close or show confirmation Log.Info("Close requested"); // Don't call Exit() to prevent closing Exit(); }; // VSync control Window.VSync = true; // Mouse capture mode for FPS-style controls // Window.RelativeMouseMode = true; } protected override void Render() { // Clear window with color Window.Clear(Color.CornflowerBlue); // Or clear with more control via GraphicsDevice GraphicsDevice.Clear(Window, Color.Black, depth: 0, mask: ClearMask.Color); batcher.Clear(); // ... draw content batcher.Render(Window); } protected override void Update() { if (Input.Keyboard.Pressed(Keys.F11)) Window.Fullscreen = !Window.Fullscreen; } protected override void Shutdown() { batcher.Dispose(); } } ``` -------------------------------- ### Implement Game Lifecycle with App Class Source: https://context7.com/fosterframework/foster/llms.txt Demonstrates how to create a game by inheriting from the App class. It covers essential lifecycle methods including Startup, Update, Render, and Shutdown, as well as basic resource management and input handling. ```csharp using Foster.Framework; using System.Numerics; public class MyGame : App { private Batcher batcher; private Texture playerTexture; public MyGame() : base("My Game", 1280, 720) { } protected override void Startup() { batcher = new Batcher(GraphicsDevice); playerTexture = new Texture(GraphicsDevice, new Image("player.png")); } protected override void Update() { if (Input.Keyboard.Pressed(Keys.Escape)) Exit(); } protected override void Render() { Window.Clear(Color.CornflowerBlue); batcher.Clear(); batcher.Image(playerTexture, new Vector2(100, 100), Color.White); batcher.Render(Window); } protected override void Shutdown() { playerTexture.Dispose(); batcher.Dispose(); } public static void Main() { using var game = new MyGame(); game.Run(); } } ``` -------------------------------- ### Initialize and Render Text with SpriteFont Source: https://context7.com/fosterframework/foster/llms.txt Demonstrates how to initialize SpriteFont objects from TTF files, handle custom codepoints, and render text using various justification and wrapping options. It also shows how to measure text dimensions and use Batcher extension methods. ```csharp using Foster.Framework; using System.Numerics; public class SpriteFontExample : App { private Batcher batcher; private SpriteFont font; private SpriteFont largeFont; public SpriteFontExample() : base("Font Demo", 800, 600) { } protected override void Startup() { batcher = new Batcher(GraphicsDevice); font = new SpriteFont(GraphicsDevice, "assets/font.ttf", size: 24); int[] extendedChars = [.. SpriteFont.Ascii, 0x00C0, 0x00C1]; largeFont = new SpriteFont(GraphicsDevice, "assets/font.ttf", size: 48, codepoints: extendedChars); } protected override void Render() { Window.Clear(Color.DarkSlateGray); batcher.Clear(); font.Draw(batcher, "Hello, Foster!", new Vector2(50, 50), Color.White); font.DrawWrapped(batcher, "Wrapped text example.", new Vector2(50, 220), Vector2.Zero, 300f, Color.White); batcher.Text(font, "Extension method!", new Vector2(50, 350), Color.Green); batcher.Render(Window); } protected override void Shutdown() { font.Dispose(); largeFont.Dispose(); batcher.Dispose(); } } ``` -------------------------------- ### Manipulate Images with Foster Framework Source: https://context7.com/fosterframework/foster/llms.txt Demonstrates how to load, create, modify, and save images using the Foster Framework. Covers pixel access, copying between images, alpha premultiplication, and texture creation. ```csharp using Foster.Framework; public class ImageExample : App { private Texture resultTexture; private Batcher batcher; public ImageExample() : base("Image Demo", 800, 600) { } protected override void Startup() { batcher = new Batcher(GraphicsDevice); var image = new Image("character.png"); var blank = new Image(128, 128); var filled = new Image(64, 64, Color.Red); var pixels = new Color[32 * 32]; for (int i = 0; i < pixels.Length; i++) pixels[i] = Color.FromHSV(i / (float)pixels.Length, 1, 1); var fromPixels = new Image(32, 32, pixels); var span = image.Data; Color pixel = image[10, 10]; image[10, 10] = Color.White; pixel = image[100]; image.SetPixel(5, 5, Color.Blue); Color read = image.GetPixel(5, 5); var dest = new Image(256, 256); dest.CopyPixels(image, sourceRect: new RectInt(0, 0, 64, 64), destination: new Point2(10, 10)); dest.CopyPixels(filled, destination: new Point2(100, 100), blend: (src, dst) => Color.Lerp(dst, src, src.A / 255f)); image.Premultiply(); image.WritePng("output.png"); image.WriteQoi("output.qoi"); using var stream = new System.IO.MemoryStream(); image.WritePng(stream); byte[] pngBytes = image.WritePng(); resultTexture = new Texture(GraphicsDevice, dest); image.Dispose(); blank.Dispose(); filled.Dispose(); fromPixels.Dispose(); dest.Dispose(); } protected override void Render() { Window.Clear(Color.DarkGray); batcher.Clear(); batcher.Image(resultTexture, new System.Numerics.Vector2(10, 10), Color.White); batcher.Render(Window); } protected override void Update() { } protected override void Shutdown() { resultTexture.Dispose(); batcher.Dispose(); } } ``` -------------------------------- ### Handle Keyboard, Mouse, and Controller Input in C# Source: https://context7.com/fosterframework/foster/llms.txt This C# code demonstrates how to use the Foster Input system to detect and respond to keyboard presses, mouse movements and clicks, and controller inputs. It covers checking key states (pressed, released, down), mouse button states, analog stick values, trigger inputs, and subscribing to text input and controller connection events. It also shows how to manipulate the clipboard and rumble a controller. ```csharp using Foster.Framework; using System.Numerics; public class InputExample : App { private Batcher batcher; private Vector2 playerPos = new(400, 300); private const float Speed = 200f; public InputExample() : base("Input Demo", 800, 600) { } protected override void Startup() { batcher = new Batcher(GraphicsDevice); // Subscribe to text input events Input.OnTextEvent += (text, window) => { Log.Info($"Text input: {text.ToString()}"); }; // Subscribe to controller events Input.OnControllerConnected += (id) => Log.Info($"Controller {id} connected"); Input.OnControllerDisconnected += (id) => Log.Info($"Controller {id} disconnected"); } protected override void Update() { // Keyboard input if (Input.Keyboard.Down(Keys.Escape)) Exit(); // Check key states if (Input.Keyboard.Pressed(Keys.Space)) // Just pressed this frame Log.Info("Space pressed!"); if (Input.Keyboard.Released(Keys.Space)) // Just released this frame Log.Info("Space released!"); if (Input.Keyboard.Down(Keys.Space)) // Currently held Log.Info("Space held..."); // Movement with WASD Vector2 move = Vector2.Zero; if (Input.Keyboard.Down(Keys.W) || Input.Keyboard.Down(Keys.Up)) move.Y -= 1; if (Input.Keyboard.Down(Keys.S) || Input.Keyboard.Down(Keys.Down)) move.Y += 1; if (Input.Keyboard.Down(Keys.A) || Input.Keyboard.Down(Keys.Left)) move.X -= 1; if (Input.Keyboard.Down(Keys.D) || Input.Keyboard.Down(Keys.Right)) move.X += 1; if (move != Vector2.Zero) { move = Vector2.Normalize(move); playerPos += move * Speed * Time.Delta; } // Mouse input Vector2 mousePos = Input.Mouse.Position; Vector2 mouseDelta = Input.Mouse.Delta; Vector2 wheelDelta = Input.Mouse.Wheel; if (Input.Mouse.Pressed(MouseButtons.Left)) Log.Info($"Left click at {mousePos}"); if (Input.Mouse.Down(MouseButtons.Right)) Log.Info("Right mouse held"); if (Input.Mouse.Released(MouseButtons.Middle)) Log.Info("Middle mouse released"); // Controller input (if connected) var controller = Input.Controllers[0]; if (controller.Connected) { // Check button states if (controller.Pressed(Buttons.A)) Log.Info("A button pressed"); if (controller.Down(Buttons.B)) Log.Info("B button held"); // Read analog sticks (-1 to 1) Vector2 leftStick = new( controller.Axis(Axes.LeftX), controller.Axis(Axes.LeftY) ); Vector2 rightStick = new( controller.Axis(Axes.RightX), controller.Axis(Axes.RightY) ); // Apply deadzone and move if (leftStick.Length() > 0.2f) playerPos += leftStick * Speed * Time.Delta; // Triggers (0 to 1) float leftTrigger = controller.Axis(Axes.TriggerLeft); float rightTrigger = controller.Axis(Axes.TriggerRight); // Rumble the controller if (controller.Pressed(Buttons.X)) Input.Rumble(controller.ID, intensity: 0.5f, duration: 0.2f); } // Clipboard if (Input.Keyboard.Ctrl && Input.Keyboard.Pressed(Keys.C)) Input.SetClipboardString("Hello from Foster!"); if (Input.Keyboard.Ctrl && Input.Keyboard.Pressed(Keys.V)) Log.Info($"Clipboard: {Input.GetClipboardString()}"); } protected override void Render() { Window.Clear(Color.DarkGray); batcher.Clear(); // Draw player batcher.Circle(playerPos, 20, 32, Color.Green); // Draw mouse cursor indicator batcher.CircleLine(Input.Mouse.Position, 10, 2, 16, Color.White); batcher.Render(Window); } protected override void Shutdown() { batcher.Dispose(); } } ``` -------------------------------- ### Configure Game Loop Timing with UpdateMode Source: https://context7.com/fosterframework/foster/llms.txt Shows how to configure the game loop timing using UpdateMode. It explains the differences between fixed timestep for deterministic logic and unlocked frame rates for maximum performance. ```csharp using Foster.Framework; public class TimingExample : App { public TimingExample() : base("Timing Demo", 800, 600) { // Set fixed 60 FPS update loop UpdateMode = UpdateMode.FixedStep(60); } protected override void Update() { // Time.Delta provides the time elapsed since the last update float movement = 100f * Time.Delta; } protected override void Startup() { } protected override void Shutdown() { } protected override void Render() { } } ``` -------------------------------- ### Utilize 2D Geometric Primitives Source: https://context7.com/fosterframework/foster/llms.txt Shows how to instantiate and use auxiliary 2D types such as Point2, Line, Circle, Triangle, and Quad. These types provide essential spatial functionality like distance calculation, point containment, and overlap detection. ```csharp var point = new Point2(10, 20); var line = new Line(new Vector2(0, 0), new Vector2(100, 100)); var circle = new Circle(new Vector2(100, 100), 50); var triangle = new Triangle(new Vector2(0, 0), new Vector2(100, 0), new Vector2(50, 100)); var quad = new Quad(new Vector2(0, 0), new Vector2(100, 0), new Vector2(100, 100), new Vector2(0, 100)); ``` -------------------------------- ### App - Application Lifecycle Source: https://context7.com/fosterframework/foster/llms.txt The App class is the central point for managing the lifecycle of a Foster application. It handles window creation, input processing, graphics device initialization, and the main game loop. Developers inherit from App and implement abstract methods like Startup, Update, Render, and Shutdown to define their game's behavior. ```APIDOC ## App - Application Lifecycle ### Description The App class is the main entry point for Foster applications. Inherit from it and implement the abstract methods to create your game. It manages the window, input, graphics device, and main update loop. ### Method Inheritance and method implementation ### Endpoint N/A (Class-based) ### Parameters N/A (Class-based) ### Request Example ```csharp using Foster.Framework; using System.Numerics; public class MyGame : App { private Batcher batcher; private Texture playerTexture; public MyGame() : base("My Game", 1280, 720) { } // Alternative constructor with full configuration // public MyGame() : base(new AppConfig( // ApplicationName: "My Game", // WindowTitle: "My Awesome Game", // Width: 1280, // Height: 720, // Fullscreen: false, // Resizable: true, // UpdateMode: UpdateMode.FixedStep(60), // PreferredGraphicsDriver: GraphicsDriver.None, // Auto-select // Flags: AppFlags.None // )) { } protected override void Startup() { // Called once when the app starts batcher = new Batcher(GraphicsDevice); playerTexture = new Texture(GraphicsDevice, new Image("player.png")); } protected override void Update() { // Called every frame (or fixed timestep) // Access timing via Time property float delta = Time.Delta; // Time since last update in seconds TimeSpan elapsed = Time.Elapsed; // Total elapsed time // Check for exit if (Input.Keyboard.Pressed(Keys.Escape)) Exit(); } protected override void Render() { // Clear the window and draw Window.Clear(Color.CornflowerBlue); batcher.Clear(); batcher.Image(playerTexture, new Vector2(100, 100), Color.White); batcher.Render(Window); } protected override void Shutdown() { // Clean up resources playerTexture.Dispose(); batcher.Dispose(); } public static void Main() { using var game = new MyGame(); game.Run(); } } ``` ### Response N/A (Class-based) ``` -------------------------------- ### Manipulate 2D Rectangles in Foster Source: https://context7.com/fosterframework/foster/llms.txt Demonstrates the creation, transformation, and collision detection capabilities of the Rect class. It covers static constructors, edge calculations, intersection logic, and operator overloading for spatial positioning. ```csharp var rect = new Rect(10, 20, 100, 50); var centered = Rect.Centered(new Vector2(400, 300), 100, 50); bool overlaps = rect.Overlaps(new Rect(50, 40, 100, 100)); Rect translated = rect.Translate(10, 20); Quad transformed = rect.Transform(Matrix3x2.CreateRotation(MathF.PI / 4)); ``` -------------------------------- ### VirtualAction API Source: https://context7.com/fosterframework/foster/llms.txt Defines a button-like input that can be triggered by multiple keys or buttons, supporting input buffering and repeat logic. ```APIDOC ## VirtualAction ### Description A VirtualAction represents a binary input (pressed/released) that can be bound to multiple physical sources. It includes support for input buffering, repeat delays, and state consumption. ### Properties - **Pressed** (bool) - Returns true if the action was triggered this frame. - **Down** (bool) - Returns true if the action is currently held down. - **Repeated** (bool) - Returns true if the action is held and the repeat interval has passed. - **Timestamp** (double) - The time at which the action was last triggered. ### Methods - **ConsumePress()** (bool) - Returns true if pressed and marks the press as consumed, preventing other systems from reacting to the same input. - **Dispose()** (void) - Cleans up resources associated with the action. ### Example ```csharp jumpAction = new VirtualAction(Input, "Jump", buffer: 0.1f); jumpAction.Entries.Add(new() { Key = Keys.Space }); if (jumpAction.ConsumePress()) { /* Handle Jump */ } ``` ``` -------------------------------- ### VirtualAxis and VirtualStick API Source: https://context7.com/fosterframework/foster/llms.txt Defines continuous input bindings for mapping analog sticks or keyboard pairs to scalar or vector values. ```APIDOC ## VirtualAxis / VirtualStick ### Description VirtualAxis maps inputs to a float (-1 to 1), while VirtualStick maps inputs to a 2D Vector2. Both support deadzone configuration to filter out minor hardware noise. ### VirtualAxis Properties - **Value** (float) - The current normalized value of the axis. ### VirtualStick Properties - **Value** (Vector2) - The current normalized 2D vector of the stick. ### Configuration - **Deadzone** (float) - The threshold below which input is ignored. - **Entries** (List) - A collection of bindings (Keys, Buttons, or hardware Axes) that contribute to the final value. ### Example ```csharp horizontalAxis = new VirtualAxis(Input, "Horizontal"); horizontalAxis.Entries.Add(new() { Negative = Keys.A, Positive = Keys.D }); float val = horizontalAxis.Value; ``` ``` -------------------------------- ### UpdateMode - Frame Timing Configuration Source: https://context7.com/fosterframework/foster/llms.txt UpdateMode allows developers to configure the game loop's frame timing. It supports fixed timesteps for consistent gameplay or an unlocked mode for maximum performance. This configuration affects the `Time.Delta` value used in the `Update` method. ```APIDOC ## UpdateMode - Frame Timing Configuration ### Description UpdateMode controls how the game loop timing works. Use fixed timestep for deterministic gameplay or unlocked for maximum frame rate. ### Method Configuration via `UpdateMode` property ### Endpoint N/A (Class-based configuration) ### Parameters N/A (Class-based configuration) ### Request Example ```csharp using Foster.Framework; public class TimingExample : App { public TimingExample() : base("Timing Demo", 800, 600) { // Fixed 60 FPS with frame waiting enabled (default) UpdateMode = UpdateMode.FixedStep(60); // Fixed 120 FPS // UpdateMode = UpdateMode.FixedStep(120); // Unlocked frame rate (update as fast as possible) // UpdateMode = UpdateMode.Unlocked; // Fixed step without waiting (runs as fast as possible but fixed delta) // UpdateMode = UpdateMode.FixedStep(60, waitEnabled: false); // Fixed step with custom max accumulator time (prevents spiral of death) // UpdateMode = UpdateMode.FixedStep(60, maxElapsedTime: TimeSpan.FromSeconds(0.25)); } protected override void Update() { // Time.Delta is consistent in fixed mode (1/60 = 0.0166... seconds) // In unlocked mode, Time.Delta varies based on actual frame time float movement = 100f * Time.Delta; // 100 units per second } protected override void Startup() { } protected override void Shutdown() { } protected override void Render() { } } ``` ### Response N/A (Class-based configuration) ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.