220 likes | 342 Views
This guide details the implementation of a particle system based on the laws of motion, including position, velocity, acceleration, and force calculations. It showcases code examples for updating particle positions and velocities with Newton's Laws, along with methods for firing various types of projectiles in a game environment. The integration of damping effects and multiple particle instances is also covered. Ideal for game developers looking to enhance their knowledge of physics-driven particle simulations.
E N D
Particle Systems Asst. Prof. Rujchai Ung-arunyawee COE, KKU
Laws of Motion • Position • Velocity • Acceleration • Mass • Force • Newton’s Laws
Velocity • Differential • Integral • Code Position += Velocity*time;
Acceleration • Differential • Integral • Code Position += Velocity*time + acceleration*time*time* 0.5; OR Position += Velocity*time;
Force Equation • Code acceleration = inversemass*force;
Integrator for Particle Update public void Integrate(float duration) { // Update linear position position.X += velocity.X * duration; position.Y += velocity.Y * duration; position.Z += velocity.Z * duration; // Update linear velocity Vector3 resultingAcc = acceleration; resultingAcc.X += forceAccum.X * inverseMass; resultingAcc.Y += forceAccum.Y * inverseMass; resultingAcc.Z += forceAccum.Z * inverseMass; velocity.X += resultingAcc.X * duration; velocity.Y += resultingAcc.Y * duration; velocity.Z += resultingAcc.Z * duration; // Impose drag. float scale = (float)Math.Pow(damping, duration); velocity = Vector3.Multiply(velocity, scale); }
Game Update() protected override void Update(GameTime gameTime) { // Allows the game to exit if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed) this.Exit(); // TODO: Add your update logic here KeyboardState kb = Keyboard.GetState(); MouseState mouse = Mouse.GetState(); if (mouse.LeftButton == ButtonState.Pressed) fire(gameTime); float duration = gameTime.ElapsedGameTime.Milliseconds / (1000.0f); ammos.Integrate(duration); base.Update(gameTime); }
Fire() Method private void fire(GameTime gametime) { // Artillery ammos.Mass = 200.0f; // 200.0kg ammos.Velocity = new Vector3(0.0f, 30.0f, 40.0f);// 50m/s ammos.Acceleration = new Vector3(0.0f, -20.0f, 0.0f); ammos.Damping = 0.99f; ammos.Position = new Vector3(0.0f, 1.5f, 0.0f); ammos.clearAccumulator(); }
Draw the particle foreach (ModelMesh mesh in myModel.Meshes) { // Draw the current mesh foreach (BasicEffect eff in mesh.Effects) { eff.World = Matrix.CreateScale(0.03f); eff.World *= Matrix.CreateTranslation(ammos.Position); eff.View = effect.View; eff.Projection = effect.Projection; eff.EnableDefaultLighting(); } mesh.Draw(); }
Camera Settings // Set the Viewing Matrix effect.View = Matrix.CreateLookAt( new Vector3(-25.0f, 8.0f,-5.0f),new Vector3(0.0f, 5.0f, 22.0f), Vector3.Up); // Set the Projection Matrix effect.Projection = Matrix.CreatePerspectiveFieldOfView( MathHelper.ToRadians(60.0f), aspectRatio, 1.0f, 500.0f);
Other Particle Types // Laser //ammos.Mass = 0.1f; // 0.1kg - almost no weight //ammos.Velocity = new Vector3(0.0f, 0.0f, 100.0f);// 100m/s //ammos.Acceleration = new Vector3(0.0f, 0.0f, 0.0f); //No gravity //ammos.Damping = 0.99f; // Pistol //ammos.Mass = 2.0f; // 2.0kg //ammos.Velocity = new Vector3(0.0f, 0.0f, 35.0f);// 35m/s //ammos.Acceleration = new Vector3(0.0f, -1.0f, 0.0f); //ammos.Damping = 0.99f; // Fireball //ammos.Mass = 1.0f; // 1.0kg //ammos.Velocity = new Vector3(0.0f, 0.0f, 10.0f);// 10m/s //ammos.Acceleration = new Vector3(0.0f, 0.6f, 0.0f);// Floats up //ammos.Damping = 0.9f;
Particle Array • Declared as a field of the Game class const int ammoMax = 10; Particle[] ammos; • Created in Initialize() ammos = new Particle[ammoMax];
Timer in XNA MouseState mouse = Mouse.GetState(); m_gameTime = gameTime; if ((mouse.LeftButton == ButtonState.Pressed)&& (m_gameTime.TotalGameTime.TotalMilliseconds - lastTime > 200)) { // Do your mouse state logic here lastTime = m_gameTime.TotalGameTime.TotalMilliseconds; fire(gametime); }
Updating the Particles float duration = gameTime.ElapsedGameTime.Milliseconds / (1000.0f); for (int i = 0; i < ammoMax; i++) { if (ammos[i] != null) { if (ammos[i].Position.Y < 0) ammos[i] = null; else ammos[i].Integrate(duration); } }
Firing the Particles private void fire(GameTime gametime) { for (int i = 0; i < ammoMax; i++) { if (ammos[i] == null) { ammos[i] = new Particle(); // Artillery ammos[i].Mass = 200.0f; // 200.0kg ammos[i].Velocity = new Vector3(0.0f, 30.0f, 40.0f); ammos[i].Acceleration = new Vector3(0.0f, -20.0f, 0.0f); ammos[i].Damping = 0.99f; ammos[i].Position = new Vector3(0.0f, 1.5f, 0.0f); ammos[i].clearAccumulator(); break; } }
Drawing the Particles (1/2) protected override void Draw(GameTime gameTime) { ... ... ... draw_lines(device); for(int i =0 ; i < ammoMax; i++) if(ammos[i] != null) draw_ammo(i); base.Draw(gameTime); }
Drawing the Particles (2/2) private void draw_ammo(int i) { foreach (ModelMesh mesh in myModel.Meshes) { // Draw the current mesh foreach (BasicEffect eff in mesh.Effects) { eff.World = Matrix.CreateScale(0.03f); eff.World *= Matrix.CreateTranslation(ammos[i].Position); eff.View = effect.View; eff.Projection = effect.Projection; eff.EnableDefaultLighting(); } mesh.Draw(); } }