Show Square.php syntax highlighted
<?php
/**
* @internal
* Quantum Game Library
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the text file LICENSE located in the root
* directory of this library.
* It is also available through the internet at this URL:
* http://doc.astrumfutura.com/license.html
*
* If you did not receive a copy of the license and are unable to
* obtain it through the internet, please send an email
* to license@astrumfutura.com so we can send you a copy.
*
* @package Map
* @subpackage Measure
* @category Quantum
* @copyright Copyright (c) 2007 The QGL Group (refer to COPYRIGHT file)
* @version $Id: Square.php 210 2007-02-03 02:55:49Z santosj $
* @license http://doc.astrumfutura.com/license.html New BSD License
*/
/** Quantum_Map_Measure_Abstract */
require_once('Quantum/Map/Measure/Abstract.php');
/**
* Provides methods for measuring certain unit based measures of a Coordinate
* Grid in following the Square Grid Map layout (typical 2D coordinate map).
*
* @package Map
* @subpackage Measure
* @category Quantum
* @author Pádraic Brady (http://blog.astrumfutura.com)
* @uses Quantum_Map_Measure_Abstract
*/
class Quantum_Map_Measure_Square extends Quantum_Map_Measure_Abstract
{
/**
* Constants all refer to the unit difference between the coordinates of
* the current cell to a cell in the given direction (allowing us to
* figure out their coordinates easily). Directions are given in degrees
* starting from the West (0) in a clockwise direction to South-West (315)
*/
/** West */
const DEG_0_X = -1;
const DEG_0_Y = 0;
/** Northwest */
const DEG_45_X = -1;
const DEG_45_Y = 1;
/** North */
const DEG_90_X = 0;
const DEG_90_Y = 1;
/** Northeast */
const DEG_135_X = 1;
const DEG_135_Y = 1;
/** East */
const DEG_180_X = 1;
const DEG_180_Y = 0;
/** Southeast */
const DEG_225_X = 1;
const DEG_225_Y = -1;
/** South */
const DEG_270_X = 0;
const DEG_270_Y = -1;
/** Southwest */
const DEG_315_X = -1;
const DEG_315_Y = -1;
/*
* Stores an instance of this class when instantiated.
*
* @access private
* @var Quantum_Map_Measure_Hex
*/
protected static $_instance = null;
/**
* Singleton static method for retrieving an instance of the DataAccess class.
*
* @return Quantum_Map_Measure_hex
* @access public
*/
static public function getInstance()
{
if(is_null(self::$_instance))
{
self::$_instance = new self();
}
return self::$_instance;
}
/**
* Returns the minimum number of cells an entity must pass through to travel
* on the map from a starting cell to a finish cell adhering to the map layout.
* This differs from getUnitDistance which returns the absolute metric distance
* (i.e. a measurement of distance "as the crow flies").
*
* @param $startNode Quantum_Coordinate
* @param $endNode Quantum_Coordinate
* @return integer
* @access public
*/
public function getMoveDistance(Quantum_Coordinate_Interface $startNode,
Quantum_Coordinate_Interface $endNode)
{
throw new Quantum_Map_Measure_Exception('Not implemented.');
}
/**
* Returns the absolute metric distance between the starting and end cells
* (i.e. a measurement of distance "as the crow flies"). This returns a float
* being an exact measure, and ignores any movement rules.
*
* @param $startNode Quantum_Coordinate
* @param $endNode Quantum_Coordinate
* @return float
* @access public
*/
public function getUnitDistance(Quantum_Coordinate_Interface $startNode,
Quantum_Coordinate_Interface $endNode)
{
/*
* Set distance to 0, the following is for clarity and some speed boost.
*/
$distance = 0;
$dX = $endNode[0] - $startNode[0];
$dY = $endNode[1] - $startNode[1];
$distance = sqrt(
pow($dX, 2) + pow($dY, 2)
);
return $distance;
}
/**
* Return an array of neighbouring cells with short form direction strings
* as keys. Order of return is clockwise from North-East (ne) to North-West
* (nw). Non supported directions should be checked for NULL values as not
* set. For Hex maps, for example, we use the "pointy-side up" orientation
* meaning any Entities cannot move directly North or South on a map, only
* in the other six compass directions.
*
* @param $node Quantum_Coordinate
* @return array
* @access public
*/
public function getPerimeterCells(Quantum_Coordinate_Interface $node)
{
$cells = array();
$cells['n'] = array(
'x'=>$node['x'] + self::DEG_90_X,
'y'=>$node['y'] + self::DEG_90_Y
);
$cells['ne'] = array(
'x'=>$node['x'] + self::DEG_135_X,
'y'=>$node['y'] + self::DEG_135_Y
);
$cells['e'] = array(
'x'=>$node['x'] + self::DEG_180_X,
'y'=>$node['y'] + self::DEG_180_Y
);
$cells['se'] = array(
'x'=>$node['x'] + self::DEG_225_X,
'y'=>$node['y'] + self::DEG_225_Y
);
$cells['s'] = array(
'x'=>$node['x'] + self::DEG_270_X,
'y'=>$node['y'] + self::DEG_270_Y
);
$cells['sw'] = array(
'x'=>$node['x'] + self::DEG_315_X,
'y'=>$node['y'] + self::DEG_315_Y
);
$cells['w'] = array(
'x'=>$node['x'] + self::DEG_0_X,
'y'=>$node['y'] + self::DEG_0_Y
);
$cells['nw'] = array(
'x'=>$node['x'] + self::DEG_45_X,
'y'=>$node['y'] + self::DEG_45_Y
);
return $cells;
}
/**
* Returns an array in form $array[row][column] holding each coordinate of a grid
* centred on the $node value with the required area. Area is simply a map height
* squared, e.g. Area:9 = Height:3 * Width:3.
*
* @param array $node Coordinate x,y array
* @param integer $area Area value for coordinate box including centre node
* @return array
*/
public function getAreaCells(Quantum_Coordinate_Interface $node, $area)
{
if(!is_int($area) || $area < 9 || !is_int(sqrt($area)))
{
throw new Quantum_Map_Measure_Exception('Invalid Map Area. Area should be an integer value not less than 9, with a whole number square root.');
}
$mapDimension = sqrt($area);
$returnArray = array();
$minusFactor = $mapDimension - (floor($mapDimension / 2) + 1);
for($rows=0;$rows<$mapDimension;++$rows)
{
$returnArray[] = array();
for($columns=0;$columns<$mapDimension;++$columns)
{
$x = $node['x'] + ($columns - $minusFactor);
$y = $node['y'] + ($rows - $minusFactor);
$returnArray[$rows][] = array(
'x'=>$x,
'y'=>$y
);
}
}
return $returnArray;
}
/**
* Returns the number of cells in any perimeter ring at any radius distance
* from a center cell. This is actually a very simple calculation since for
* Square based shapes (8 sided polygon), if you fit all Squares in a map, the
* number of cells in any perimeter ring (or "orbit") always equals 8 times
* the radius from the center cell. The same works for Hex cell layouts
* if you substitute 8 with 6 ;).
*
* @param $radius Radius distance from center cell
* @return integer
* @access public
*/
public function getPerimeterFromRadius($radius)
{
if(!isset($radius) || !is_int($radius) || $radius < 0)
{
throw new Quantum_Map_Measure_Exception('Radius must be an integer with a minimum value of 0.');
}
$perimeter = $radius * 8;
if($perimeter == 0) // handle case where radius is 0, i.e. one cell, so area of 1
{
return 1;
}
return $perimeter;
}
/**
* Calculated the area if any region on a Square map with the given radius (i.e
* the region is a rectangular plane with a central cell.
*
* Area factor is the "Sum of the Series" where the series is a progression
* reducing radius by 1 per iteration (e.g. Series of 6 is 6,5,4,3,2,1,0)
* to zero.
*
* The Sum of Radii is then multiplied by the Square perimeter count factor, 8.
* We add 1, to represent the center cell and include it.
*
* @param $startNode Quantum_Coordinate
* @param $endNode Quantum_Coordinate
* @return integer
* @access public
*/
public function getAreaFromRadius($radius)
{
if(!isset($radius) || !is_int($radius) || $radius < 0)
{
throw new Quantum_Map_Measure_Exception('Radius must be an integer with a minimum value of 0.');
}
$sum_of_radii = 0;
do
{
$sum_of_radii += $radius;
$radius--;
}
while($radius > 0);
// area of all rings outside center cell
$area = $sum_of_radii * 8;
// add center cell
$area += 1;
return $area;
}
}
See more files for this project here