some-dungeon-game/class_entity.php

114 lines
2.8 KiB
PHP
Raw Normal View History

2021-03-18 19:58:26 +00:00
<?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;
}
}