UNPKG

agentscape

Version:

Agentscape is a library for creating agent-based simulations. It provides a simple API for defining agents and their behavior, and for defining the environment in which the agents interact. Agentscape is designed to be flexible and extensible, allowing

79 lines 3.2 kB
import Vector2 from '../numbers/Vector2'; import Agent from './Agent'; export default class Particle extends Agent { constructor(opts) { super(opts); this.metabolism = 0; this.acceleration = new Vector2([0, 0]); this.velocity = new Vector2(opts.initialVelocity); this.mass = opts.mass || 1; } get kineticEnergy() { return 0.5 * this.mass * this.velocity.magnitude ** 2; } get momentum() { return this.velocity.scale(this.mass); } /** * Applies an acceleration to the particle proportionate to the net gravitational attraction of all other particles in the given set. */ resolveGravitation(world, particles) { this.acceleration = new Vector2([0, 0]); particles.forEach((other) => { this.resolveGravitationPair(world, other); }); } resolveCollisions(world, particles, options = { particle: true }) { if (world.boundaryCondition === 'finite') { this.resolveBoundaryCollision(world); } if (options.particle) { particles.forEach((neighbor) => { this.resolveParticleCollision(neighbor); }); } } resolveParticleCollision(other) { if (this.id === other.id) { return; } const nextPosition = this.position.add(this.velocity); const otherNextPosition = other.position.add(other.velocity); const distance = nextPosition.subtract(otherNextPosition).magnitude; if (distance < (this.radius / 2) + (other.radius / 2)) { const normal = this.position.subtract(other.position).normal; const relativeVelocity = this.velocity.subtract(other.velocity); const impulse = (2 * this.mass * other.mass) / (this.mass + other.mass) * relativeVelocity.dot(normal); this.velocity = this.velocity.subtract(normal.scale(impulse / this.mass)); other.velocity = other.velocity.add(normal.scale(impulse / other.mass)); } } resolveBoundaryCollision(world) { if (this.position.x - this.radius < 0) { this.position.x = this.radius; this.velocity.x *= -1; } else if (this.position.x + this.radius >= world.width) { this.position.x = world.width - this.radius; this.velocity.x *= -1; } if (this.position.y - this.radius < 0) { this.position.y = this.radius; this.velocity.y *= -1; } else if (this.position.y + this.radius >= world.height) { this.position.y = world.height - this.radius; this.velocity.y *= -1; } } resolveGravitationPair(world, other) { if (this.id === other.id) { return; } const dxy = this.position.subtract(other.position); const force = dxy.scale(-1e-4 * this.mass * other.mass / this.distanceTo(world, other) ** 2); this.acceleration = this.acceleration.add(force.scale(1 / this.mass)); other.acceleration = other.acceleration.subtract(force.scale(1 / other.mass).scale(-1)); } } //# sourceMappingURL=Particle.js.map