Closed StuartJAtkinson closed 1 month ago
To address the user's request for adding UI controls to adjust the particle number and restart the simulation, we need to modify the MainWindow.cs
file to include these controls and their corresponding event handlers. Additionally, we need to ensure that the ParticleSimulator
class can handle the particle count updates and restart the simulation accordingly. The Program.cs
file will remain largely unchanged as its primary responsibility is to initialize and run the main window.
Modify MainWindow.cs
:
TextBox
for entering the number of particles.Button
to restart the simulation with the new number of particles.Button
click event to read the number of particles from the TextBox
and restart the simulation.Create ParticleSimulator.cs
:
ParticleSimulator
class to handle the particle simulation.Update Program.cs
:
MainWindow
is created and run.MainWindow.cs
using System;
using System.Diagnostics;
using System.Windows.Forms;
using System.Drawing;
using OpenTK;
using OpenTK.Input;
using OpenTK.Graphics;
using OpenTK.Graphics.OpenGL4;
using Newtonian_Particle_Simulator.Render;
namespace Newtonian_Particle_Simulator
{
class MainWindow : GameWindow
{
private TextBox particleNumberTextBox;
private Button restartButton;
private ParticleSimulator particleSimulator;
private readonly Camera camera = new Camera(new Vector3(0, 0, 15), new Vector3(0, 1, 0));
private Matrix4 projection;
private int frames = 0, FPS;
private readonly Stopwatch fpsTimer = Stopwatch.StartNew();
public MainWindow()
: base(832, 832, new GraphicsMode(0, 0, 0, 0), "Newtonian-Particle-Simulator")
{
InitializeControls();
}
private void InitializeControls()
{
// Initialize TextBox
particleNumberTextBox = new TextBox
{
Location = new Point(10, 10),
Width = 100
};
// Initialize Button
restartButton = new Button
{
Text = "Restart",
Location = new Point(120, 10)
};
restartButton.Click += RestartButton_Click;
// Add controls to the form
var form = (Form)Control.FromHandle(WindowInfo.Handle);
form.Controls.Add(particleNumberTextBox);
form.Controls.Add(restartButton);
}
private void RestartButton_Click(object sender, EventArgs e)
{
if (int.TryParse(particleNumberTextBox.Text, out int numParticles) && numParticles > 0)
{
particleSimulator.UpdateParticleCount(numParticles);
}
else
{
MessageBox.Show("Please enter a valid number of particles.");
}
}
protected override void OnRenderFrame(FrameEventArgs e)
{
particleSimulator.Run((float)e.Time);
SwapBuffers();
frames++;
base.OnRenderFrame(e);
}
protected override void OnUpdateFrame(FrameEventArgs e)
{
if (fpsTimer.ElapsedMilliseconds >= 1000)
{
FPS = frames;
Title = $"Newtonian-Particle-Simulator FPS: {FPS}";
frames = 0;
fpsTimer.Restart();
}
if (Focused)
{
KeyboardManager.Update();
MouseManager.Update();
if (KeyboardManager.IsKeyTouched(Key.V))
VSync = VSync == VSyncMode.Off ? VSyncMode.On : VSyncMode.Off;
if (KeyboardManager.IsKeyTouched(Key.E))
{
CursorVisible = !CursorVisible;
CursorGrabbed = !CursorGrabbed;
if (!CursorVisible)
{
MouseManager.Update();
camera.Velocity = Vector3.Zero;
}
}
if (KeyboardManager.IsKeyTouched(Key.F11))
WindowState = WindowState == WindowState.Normal ? WindowState.Fullscreen : WindowState.Normal;
particleSimulator.ProcessInputs(this, camera.Position, camera.View, projection);
if (!CursorVisible)
camera.ProcessInputs((float)e.Time);
}
if (KeyboardManager.IsKeyDown(Key.Escape))
Close();
base.OnUpdateFrame(e);
}
protected override void OnLoad(EventArgs e)
{
Console.WriteLine($"OpenGL: {Helper.APIVersion}");
Console.WriteLine($"GLSL: {GL.GetString(StringName.ShadingLanguageVersion)}");
Console.WriteLine($"GPU: {GL.GetString(StringName.Renderer)}");
if (!Helper.IsCoreExtensionAvailable("GL_ARB_direct_state_access", 4.5))
throw new NotSupportedException("Your system does not support GL_ARB_direct_state_access");
if (!Helper.IsCoreExtensionAvailable("GL_ARB_buffer_storage", 4.4))
throw new NotSupportedException("Your system does not support GL_ARB_buffer_storage");
GL.PointSize(1.1f);
GL.Enable(EnableCap.Blend);
GL.BlendEquation(BlendEquationMode.FuncAdd);
GL.BlendFunc(BlendingFactor.SrcAlpha, BlendingFactor.OneMinusSrcAlpha);
VSync = VSyncMode.Off;
int numParticles;
do
Console.Write($"Number of particles: "); // 8388480
while ((!int.TryParse(Console.ReadLine(), out numParticles)) || numParticles < 0);
particleSimulator = new ParticleSimulator(numParticles);
GC.Collect();
base.OnLoad(e);
}
protected override void OnResize(EventArgs e)
{
if (Width != 0 && Height != 0)
{
GL.Viewport(0, 0, Width, Height);
projection = Matrix4.CreatePerspectiveFieldOfView(MathHelper.DegreesToRadians(103.0f), (float)Width / Height, 0.1f, 1000f);
}
base.OnResize(e);
}
protected override void OnFocusedChanged(EventArgs e)
{
if (Focused)
MouseManager.Update();
}
}
}
ParticleSimulator.cs
using System;
using System.Collections.Generic;
namespace Newtonian_Particle_Simulator
{
public class ParticleSimulator
{
private int particleCount;
private List<Particle> particles;
public int ParticleCount
{
get { return particleCount; }
set
{
if (value != particleCount)
{
particleCount = value;
RestartSimulation();
}
}
}
public ParticleSimulator(int initialParticleCount)
{
particleCount = initialParticleCount;
particles = new List<Particle>();
StartSimulation();
}
public void StartSimulation()
{
particles.Clear();
for (int i = 0; i < particleCount; i++)
{
particles.Add(new Particle());
}
Console.WriteLine($"Simulation started with {particleCount} particles.");
}
public void RestartSimulation()
{
StartSimulation();
Console.WriteLine("Simulation restarted.");
}
public void UpdateParticleCount(int newCount)
{
ParticleCount = newCount;
}
public void Run(float deltaTime)
{
// Simulation logic here
}
public void ProcessInputs(MainWindow window, Vector3 cameraPosition, Matrix4 view, Matrix4 projection)
{
// Input processing logic here
}
}
public class Particle
{
public Vector3 Position { get; set; }
}
}
Program.cs
namespace Newtonian_Particle_Simulator
{
class Program
{
static void Main()
{
MainWindow gameWindow = new MainWindow();
gameWindow.Run(OpenTK.DisplayDevice.Default.RefreshRate);
}
}
}
This implementation provides the necessary UI controls to adjust the particle number and restart the simulation. The ParticleSimulator
class manages the particle simulation, and the MainWindow
class handles the UI interactions.
Click here to create a Pull Request with the proposed solution
Files used for this task:
What This project has controls for the control of the particle system. I want it to be in the application window as well as the particle number as an adjustable number that when entered restarts the simulation
Why I want to have them displayed so it can be controlled with button clicks rather than keyboard. Either suggest a C# control overlay that exists or make one for the project and make that where the particle # is entered rather than in the terminal