Projectile2D

Coding Critique is the place to post source code for peer review by other members of DevNetwork. Any kind of code can be posted. Code posted does not have to be limited to PHP. All members are invited to contribute constructive criticism with the goal of improving the code. Posted code should include some background information about it and what areas you specifically would like help with.

Popular code excerpts may be moved to "Code Snippets" by the moderators.

Moderator: General Moderators

Post Reply
User avatar
Jonah Bron
DevNet Master
Posts: 2764
Joined: Thu Mar 15, 2007 6:28 pm
Location: Redding, California

Projectile2D

Post by Jonah Bron »

Hello, world!

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 . ' }';
	}
}
And this is Projectile2D:

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;
	}
}
Pretty simple stuff. Here's an example use:

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>
That will draw a lovely little ASCII graph of the projectile's trajectory.

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?
Post Reply