main
Raw Download raw file
  1package harmonica
  2
  3// This file defines simple physics projectile motion.
  4//
  5// Example usage:
  6//
  7//    // Run once to initialize.
  8//    projectile := NewProjectile(
  9//        FPS(60),
 10//        Point{6.0, 100.0, 0.0},
 11//        Vector{2.0, 0.0, 0.0},
 12//        Vector{2.0, -9.81, 0.0},
 13//    )
 14//
 15//    // Update on every frame.
 16//    someUpdateLoop(func() {
 17//        pos := projectile.Update()
 18//    })
 19//
 20// For background on projectile motion see:
 21// https://en.wikipedia.org/wiki/Projectile_motion
 22
 23// Projectile is the representation of a projectile that has a position on
 24// a plane, an acceleration, and velocity.
 25type Projectile struct {
 26	pos       Point
 27	vel       Vector
 28	acc       Vector
 29	deltaTime float64
 30}
 31
 32// Point represents a point containing the X, Y, Z coordinates of the point on
 33// a plane.
 34type Point struct {
 35	X, Y, Z float64
 36}
 37
 38// Vector represents a vector carrying a magnitude and a direction. We
 39// represent the vector as a point from the origin (0, 0) where the magnitude
 40// is the euclidean distance from the origin and the direction is the direction
 41// to the point from the origin.
 42type Vector struct {
 43	X, Y, Z float64
 44}
 45
 46// Gravity is a utility vector that represents gravity in 2D and 3D contexts,
 47// assuming that your coordinate plane looks like in 2D or 3D:
 48//
 49//   y             y ±z
 50//   │             │ /
 51//   │             │/
 52//   └───── ±x     └───── ±x
 53//
 54// (i.e. origin is located in the bottom-left corner)
 55var Gravity = Vector{0, -9.81, 0}
 56
 57// TerminalGravity is a utility vector that represents gravity where the
 58// coordinate plane's origin is on the top-right corner
 59var TerminalGravity = Vector{0, 9.81, 0}
 60
 61// NewProjectile creates a new projectile. It accepts a frame rate and initial
 62// values for position, velocity, and acceleration. It returns a new
 63// projectile.
 64func NewProjectile(deltaTime float64, initialPosition Point, initialVelocity, initalAcceleration Vector) *Projectile {
 65	return &Projectile{
 66		pos:       initialPosition,
 67		vel:       initialVelocity,
 68		acc:       initalAcceleration,
 69		deltaTime: deltaTime,
 70	}
 71}
 72
 73// Update updates the position and velocity values for the given projectile.
 74// Call this after calling NewProjectile to update values.
 75func (p *Projectile) Update() Point {
 76	p.pos.X += (p.vel.X * p.deltaTime)
 77	p.pos.Y += (p.vel.Y * p.deltaTime)
 78	p.pos.Z += (p.vel.Z * p.deltaTime)
 79
 80	p.vel.X += (p.acc.X * p.deltaTime)
 81	p.vel.Y += (p.acc.Y * p.deltaTime)
 82	p.vel.Z += (p.acc.Z * p.deltaTime)
 83
 84	return p.pos
 85}
 86
 87// Position returns the position of the projectile.
 88func (p *Projectile) Position() Point {
 89	return p.pos
 90}
 91
 92// Velocity returns the velocity of the projectile.
 93func (p *Projectile) Velocity() Vector {
 94	return p.vel
 95}
 96
 97// Acceleration returns the acceleration of the projectile.
 98func (p *Projectile) Acceleration() Vector {
 99	return p.acc
100}