Code Search for Developers
 
 
  

Square.php from Astrum Futura at Krugle


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

Astrum Futura

Multiplayer space strategy game written in PHP5 with the Zend Framework. User interface uses Javascript/AJAX for dynamic interaction. Players compete across a hexagonal map of 10,000 sectors, planets, stars and other locations through trade and combat.

Project homepage: http://sourceforge.net/projects/astrumfutura
Programming language(s): PHP,XML
License: other

  Abstract.php
  Exception.php
  Hex.php
  Square.php