114 lines
2.8 KiB
PHP
114 lines
2.8 KiB
PHP
|
<?php
|
||
|
|
||
|
abstract class Entity
|
||
|
{
|
||
|
/**
|
||
|
* Different visibility types for entities
|
||
|
*/
|
||
|
const VSB_INVISIBLE = 0;
|
||
|
const VSB_VISIBLE = 1;
|
||
|
const VSB_SEETHROUGH = 2;
|
||
|
|
||
|
protected $place;
|
||
|
protected $seenCells = array();
|
||
|
|
||
|
|
||
|
public function __toString()
|
||
|
{
|
||
|
return static::CHAR;
|
||
|
}
|
||
|
|
||
|
static public function getChar()
|
||
|
{
|
||
|
return static::CHAR;
|
||
|
}
|
||
|
|
||
|
public function getVisibility()
|
||
|
{
|
||
|
return static::VISIBILITY;
|
||
|
}
|
||
|
|
||
|
public function setPlace(Place $place)
|
||
|
{
|
||
|
// Remove from old place if exists
|
||
|
if ($this->place !== null)
|
||
|
$this->place->getLevel()->removeEntity($this->place->getCoord());
|
||
|
|
||
|
$this->place = $place;
|
||
|
|
||
|
if ($this->place !== null)
|
||
|
$this->place->getLevel()->insertEntity($this->place->getCoord(), $this);
|
||
|
}
|
||
|
|
||
|
public function getPlace()
|
||
|
{
|
||
|
return $this->place;
|
||
|
}
|
||
|
|
||
|
public function drawPath(Entity $target, $callback)
|
||
|
{
|
||
|
$targetX = $target->getPlace()->getCoord()->x;
|
||
|
$targetY = $target->getPlace()->getCoord()->y;
|
||
|
$startX = $this->getPlace()->getCoord()->x;
|
||
|
$startY = $this->getPlace()->getCoord()->y;
|
||
|
|
||
|
if ($startX == $targetX && $startY == $targetY)
|
||
|
return;
|
||
|
|
||
|
$diffX = $targetX - $startX;
|
||
|
$diffY = $targetY - $startY;
|
||
|
|
||
|
$step = max(abs($diffX), abs($diffY));
|
||
|
$stepX = $diffX / $step;
|
||
|
$stepY = $diffY / $step;
|
||
|
if ($stepX != 0)
|
||
|
$steps = floor($diffX / $stepX);
|
||
|
else
|
||
|
$steps = floor($diffY / $stepY);
|
||
|
|
||
|
$x = $startX;
|
||
|
$y = $startY;
|
||
|
$i = 0;
|
||
|
do
|
||
|
{
|
||
|
$x += $stepX;
|
||
|
$y += $stepY;
|
||
|
++$i;
|
||
|
if (!$callback(new Coord(floor($x), floor($y))))
|
||
|
return;
|
||
|
|
||
|
} while ((floor($x) != $targetX || floor($y) != $targetY)
|
||
|
&& $i < $steps);
|
||
|
}
|
||
|
|
||
|
public function canSee(Entity $target)
|
||
|
{
|
||
|
// Check if already marked as seen
|
||
|
if (isset($this->seenCells[$target->getPlace()->getCoord()->x][$target->getPlace()->getCoord()->y]))
|
||
|
return true;
|
||
|
|
||
|
// Check distance
|
||
|
if ($this->getSight() < $this->getPlace()->getCoord()->getDistance($target->getPlace()->getCoord()))
|
||
|
return false;
|
||
|
|
||
|
// Check each cell on the way for opaque objects
|
||
|
$level = $this->getPlace()->getLevel();
|
||
|
$return = true;
|
||
|
$seenCells =& $this->seenCells;
|
||
|
$this->drawPath($target, function(Coord $coord) use (&$return, $level, $target,
|
||
|
&$seenCells)
|
||
|
{
|
||
|
$obj = $level->whatsAt($coord);
|
||
|
if ($obj !== null && $obj != $target && $obj->getVisibility() == Entity::VSB_VISIBLE)
|
||
|
{
|
||
|
$return = false;
|
||
|
return false;
|
||
|
}
|
||
|
$seenCells[$coord->x][$coord->y] = true;
|
||
|
return true;
|
||
|
});
|
||
|
|
||
|
return $return;
|
||
|
}
|
||
|
}
|