Just for fun, I whipped together a couple of little classes to simulate a projectile's path in a 2D universe. All it does now is take an initial velocity, a gravity, and a resistance constant. Here's Point2D:
Code: Select all
<?php
namespace D;
/**
* Point2D
*
* Holds a position on a 2-dimensional plane
*
* @author Jonah Dahlquist <jonah[at]nucleussystems[dot]com>
*/
class Point2D
{
/**
* The x dimension position
*
* @var double $x
*/
public $x = 0;
/**
* The y dimension position
*
* @var double $y
*/
public $y = 0;
/**
* Create a new Point2D
*
* @param double $x X dimension (optional, default 0)
* @param double $y Y dimension (optional, default 0)
*/
public function __construct($x = 0, $y = 0)
{
$this->x = $x;
$this->y = $y;
}
/**
* Puts this Point object into a human-readable format
*
* @return string
*/
public function __toString()
{
return '{ x: ' . $this->x . ', y: ' . $this->y . ' }';
}
}
Code: Select all
<?php
namespace D;
/**
* Projectile2D
*
* Simulates a projectile launched from the origin (0, 0) with a given initial
* velocity, resistance, and universal accelerative force (e.g. gravity).
*
* @author Jonah Dahlquist <jonah[at]nucleussystems[dot]com>
*/
class Projectile2D
{
/**
* Keeps the inital velocity passed through constructor
*
* @var Point $initialVelocity
*/
protected $initialVelocity = null;
/**
* Holds the simulations current velocity
*
* @var Point $velocity
*/
protected $velocity = null;
/**
* Holds the projectile's current x & y coordinates
*
* @var Point $position
*/
protected $position = null;
/**
* Contains the universal force in x & y direction. For example,
* Jb_Point(0, -1) would accelerate the projectile downward at one foot per
* second per second.
*
* @var Point $gravity
*/
protected $gravity = null;
/**
* Contains the resistance constant. This constant is multiplied by the
* speed during simulation per-frame to calculate new speed.
*
* @var double $resistance
*/
protected $resistance = null;
/**
* Creates a new Projectile2D.
*
* @param Point $initalVelocity Initial velocity of projectile
* @param Point $gravity Universal force
* @param double $resistance Resistance (optional, default none)
*/
public function __construct(Point2D $initialVelocity, Point2D $gravity, $resistance = 1)
{
$this->initialVelocity = $initialVelocity;
$this->reset();
$this->gravity = $gravity;
$this->resistance = doubleval($resistance);
}
/**
* Runs the simulation a given number of frames
*
* @param int $frames
* @return void
*/
public function run($frames)
{
while ($frames > 0) {
$frames--;
$this->affectVelocityWithGravity();
$this->affectVelocityWithResistance();
$this->affectPositionWithVelocity();
}
}
/**
* Resets the simulation to the origin and initial velocity
*
* @return void
*/
public function reset()
{
$this->position = new Point2D();
$this->velocity = clone $this->initialVelocity;
}
/**
* Gets the projectile's current velocity
*
* @return Point
*/
public function getVelocity()
{
return clone $this->velocity;
}
/**
* Gets the projectile's current position
*
* @return Point
*/
public function getPosition()
{
return clone $this->position;
}
/**
* Modifies the velocity based on the universal force
*
* @return void
*/
protected function affectVelocityWithGravity()
{
$this->velocity->x += $this->gravity->x;
$this->velocity->y += $this->gravity->y;
}
/**
* Modifies the velocity based on the resistance constant
*
* @return void
*/
protected function affectVelocityWithResistance()
{
$this->velocity->x *= $this->resistance;
$this->velocity->y *= $this->resistance;
}
/**
* Modifies the position based on the velocity
*
* @return void
*/
protected function affectPositionWithVelocity()
{
$this->position->x += $this->velocity->x;
$this->position->y += $this->velocity->y;
}
}
Code: Select all
<pre>
<?php
require 'D/Projectile2D.php';
require 'D/Point2D.php';
namespace D;
$gun = new Projectile2D(new Point2D(0.5, 1.2), new Point2D(0, -0.03), 0.98);
$positions = array();
for ($i = 0; $i < 200; $i++) {
$positions[] = $gun->getPosition();
$gun->run(1);
}
for ($i = 20; $i >= -20; $i--) {
for ($j = -75; $j < 75; $j++) {
$found = false;
if ($i == 0) {
echo '_';
continue;
}
foreach ($positions as $position) {
if (round($position->x) == $j && round($position->y) == $i) {
$found = true;
break;
}
}
echo $found ? '@' : ' ';
}
echo PHP_EOL;
}
?>
</pre>Seems like this could be useful for graphing of some kind, but that's the only application I can think of. Do you know of any uses for this, or things that could be added to make it more useful?