maps2 #2
@ -1,3 +1,3 @@
|
||||
# 2D Map
|
||||
|
||||
Простейший пример генерации карты для игр.
|
||||
Простейший пример генерации карты для игр. Добавил пародию на ООП и пофиксил большинство ошибок.
|
104
map.php
@ -1,104 +0,0 @@
|
||||
<?
|
||||
error_reporting(E_ALL);
|
||||
session_start();
|
||||
|
||||
if (!isset($_GET["name"])) $_GET["name"] ="map";
|
||||
//Читаем карту
|
||||
$handle = fopen(htmlspecialchars($_GET["name"]).".csv", "r");
|
||||
while (($data = fgetcsv($handle, 1000, ";")) !== FALSE){
|
||||
$map[]=$data;
|
||||
}
|
||||
fclose($handle);
|
||||
//Карта в двухмерном массиве $map
|
||||
|
||||
//информация о квадрате
|
||||
$infodot["g"]["status"] = "allow";
|
||||
$infodot["m"]["status"] = "allow";
|
||||
|
||||
if ($_POST['action']=='down' AND $infodot[$map[$_SESSION["y"]+1][$_SESSION["x"]]]["status"]=='allow'){
|
||||
$_SESSION["y"]++;
|
||||
}
|
||||
if ($_POST['action']=='up' AND $infodot[$map[$_SESSION["y"]-1][$_SESSION["x"]]]["status"]=='allow'){
|
||||
$_SESSION["y"]--;
|
||||
}
|
||||
if ($_POST['action']=='left' AND $infodot[$map[$_SESSION["y"]][$_SESSION["x"]-1]]["status"]=='allow'){
|
||||
$_SESSION["x"]--;
|
||||
}
|
||||
if ($_POST['action']=='right' AND $infodot[$map[$_SESSION["y"]][$_SESSION["x"]+1]]["status"]=='allow'){
|
||||
$_SESSION["x"]++;
|
||||
}
|
||||
|
||||
//если первый заход на карту
|
||||
if (!isset($_SESSION["y"]) OR !isset($_SESSION["x"])){
|
||||
$_SESSION["y"]=5;
|
||||
$_SESSION["x"]=5;
|
||||
}
|
||||
if ($_GET["name"]=="map2") {
|
||||
$_SESSION["y"]=4;
|
||||
$_SESSION["x"]=2;
|
||||
|
||||
}
|
||||
|
||||
//Строим квадрат 5Х5 вокруг игрока
|
||||
$y = $_SESSION["y"]-2;
|
||||
$y_end = $_SESSION["y"]+2;
|
||||
$x = $_SESSION["x"]-2;
|
||||
$x_end = $_SESSION["x"]+2;
|
||||
$q = $x;
|
||||
print "<table cellpadding='0' cellspacing='0'>";
|
||||
while ($y <= $y_end){
|
||||
print "<tr>";
|
||||
$x = $q;
|
||||
while ($x <= $x_end){
|
||||
if (@$map[$y][$x] == ""){ // ползут ошибки!
|
||||
$map[$y][$x] = "end";
|
||||
}
|
||||
if ($y == $_SESSION["y"] AND $x == $_SESSION["x"]){
|
||||
print "<td background = mapimg/".$map[$y][$x].".png>";
|
||||
print "<img src=mapimg/point.gif>";
|
||||
print "</td>";
|
||||
}
|
||||
else{
|
||||
print "<td>";
|
||||
print "<img src=mapimg/".$map[$y][$x].".png>";
|
||||
print "</td>";
|
||||
}
|
||||
$x++;
|
||||
}
|
||||
print "</tr>";
|
||||
$y++;
|
||||
}
|
||||
print "</table>";
|
||||
//квадрат построен
|
||||
?>
|
||||
<form method="POST">
|
||||
<button type="submit" name="action" value="up"><img src=mapimg/m-n.png border=0></button><br>
|
||||
<button type="submit" name="action" value="left"><img src=mapimg/m-w.png border=0></button>
|
||||
<button type="submit" name="action" value="right"><img src=mapimg/m-e.png border=0></button><br>
|
||||
<button type="submit" name="action" value="down"><img src=mapimg/m-s.png border=0></button>
|
||||
</form>
|
||||
<a href=map.php?action=up><img src=mapimg/m-n.png border=0></a><br>
|
||||
<a href=map.php?action=left><img src=mapimg/m-w.png border=0></a>
|
||||
<a href=map.php?action=right><img src=mapimg/m-e.png border=0></a><br>
|
||||
<a href=map.php?action=down><img src=mapimg/m-s.png border=0></a><p>
|
||||
|
||||
<?
|
||||
/*
|
||||
//Описываем свойство отдельной клетки с координатами 2,2
|
||||
if ($_SESSION["y"] == 2 AND $_SESSION["x"] == 2){
|
||||
print "<b>В этой клетке c координатами 2,2 находится магазин";
|
||||
}
|
||||
else{
|
||||
print "В этой клетке нет активных элементов";
|
||||
}
|
||||
*/
|
||||
|
||||
//Описываем свойство целого класса клеток
|
||||
if ($map[$_SESSION["y"]][$_SESSION["x"]] == "m"){ print "<b>В этой клетке класса <i>m</i> находится магазин"; }
|
||||
|
||||
//Бежим на вторую карту с первой.
|
||||
if ($_SESSION["y"] == 2 AND $_SESSION["x"] == 0){
|
||||
print "<a href=map.php?name=map2>Сменить локацию.</a>";
|
||||
}
|
||||
|
||||
?>
|
BIN
mapimg/m-e.png
Before Width: | Height: | Size: 1.5 KiB |
BIN
mapimg/m-n.png
Before Width: | Height: | Size: 1.4 KiB |
BIN
mapimg/m-s.png
Before Width: | Height: | Size: 1.5 KiB |
BIN
mapimg/m-w.png
Before Width: | Height: | Size: 1.5 KiB |
74
public/index.php
Normal file
@ -0,0 +1,74 @@
|
||||
<?php
|
||||
session_start();
|
||||
error_reporting(E_ALL);
|
||||
|
||||
# Date: 20.02.2022 (16:17)
|
||||
use Insallah\Map\Map;
|
||||
use Insallah\Map\MapData;
|
||||
use Insallah\Player\Player;
|
||||
|
||||
/** Автозагрузка классов с учётом неймспейсов. */
|
||||
spl_autoload_register(function ($className) {
|
||||
$fileName = dirname(__DIR__) . '/src/' . str_replace('\\', '/', $className . '.php');
|
||||
if (file_exists($fileName)) {
|
||||
require_once $fileName;
|
||||
}
|
||||
});
|
||||
|
||||
$_POST['action'] ??= null;
|
||||
$_SESSION['x'] ??= null;
|
||||
$_SESSION['y'] ??= null;
|
||||
$_SESSION['force'] ??= null; // Для насильной смены локации.
|
||||
$_SESSION['mapname'] ??= 'map';
|
||||
|
||||
/** Пример смены локации.
|
||||
* Да, можно сделать функцию.
|
||||
* И это будет более правильно.
|
||||
* Это просто принцип для демонстрации.
|
||||
*/
|
||||
if ($_SESSION['x'] === 0 && $_SESSION['y'] === 2 && $_SESSION['mapname'] === 'map') {
|
||||
$_SESSION['mapname'] = 'map2';
|
||||
$_SESSION['force'] = true;
|
||||
header('Location: ' . $_SERVER['REQUEST_URI']);
|
||||
exit;
|
||||
}
|
||||
if ($_SESSION['x'] === 4 && $_SESSION['y'] === 2 && $_SESSION['mapname'] === 'map2') {
|
||||
$_SESSION['mapname'] = 'map';
|
||||
$_SESSION['force'] = true;
|
||||
header('Location: ' . $_SERVER['REQUEST_URI']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$map = new Map(new MapData($_SESSION['mapname']), $_SESSION['force']);
|
||||
unset($_SESSION['force']);
|
||||
|
||||
if ($_POST['action'] === 'up') {
|
||||
$map->goUp();
|
||||
}
|
||||
if ($_POST['action'] === 'down') {
|
||||
$map->goDown();
|
||||
}
|
||||
if ($_POST['action'] === 'left') {
|
||||
$map->goLeft();
|
||||
}
|
||||
if ($_POST['action'] === 'right') {
|
||||
$map->goRight();
|
||||
}
|
||||
if ($_POST['action'] === 'clear') {
|
||||
Player::clear();
|
||||
}
|
||||
|
||||
/** Для отладки. */
|
||||
?>
|
||||
<div style="width: 600px; border: lightcoral dashed 2px; background-color: antiquewhite; padding: 2px;">
|
||||
<strong>P:[<?= Player::getPos()[0] ?>,<?= Player::getPos()[1] ?>] MAP:[<?= $_SESSION['mapname'] ?>]</strong><br>
|
||||
Смена локаций на MAP:[0,2] и MAP2:[4,2]. Да, там надо повторно клацнуть чтобы всё сменилось, но опять же, это
|
||||
принцип на коленке, а не готовое решение. Если хранить всё хоть в какой-то базе, а не в сессиях от половины этих
|
||||
костылей можно отказаться.
|
||||
</div>
|
||||
<?php
|
||||
echo $map->drawVisible();
|
||||
require_once '../resources/views/map-controls.html';
|
||||
|
||||
echo 'Карта целиком:<br><br>';
|
||||
MapData::drawFullMap();
|
Before Width: | Height: | Size: 168 B After Width: | Height: | Size: 168 B |
Before Width: | Height: | Size: 1.0 KiB After Width: | Height: | Size: 1.0 KiB |
Before Width: | Height: | Size: 7.1 KiB After Width: | Height: | Size: 7.1 KiB |
Before Width: | Height: | Size: 825 B After Width: | Height: | Size: 825 B |
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 6.1 KiB After Width: | Height: | Size: 6.1 KiB |
43
resources/views/map-controls.html
Normal file
@ -0,0 +1,43 @@
|
||||
<style>
|
||||
table {
|
||||
border-spacing: 0;
|
||||
}
|
||||
|
||||
td {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.game-board {
|
||||
display: grid;
|
||||
grid-template-rows: 50px 50px 50px;
|
||||
grid-template-columns: 50px 50px 50px;
|
||||
}
|
||||
|
||||
.box {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
</style>
|
||||
<form method="post" id="movement"></form>
|
||||
<div class='game-board'>
|
||||
<div class='box'></div>
|
||||
<div class="box">
|
||||
<button type='submit' name='action' value='up' form="movement">🔼</button>
|
||||
</div>
|
||||
<div class='box'></div>
|
||||
<div class='box'>
|
||||
<button type='submit' name='action' value='left' form='movement'>◀</button>
|
||||
</div>
|
||||
<div class='box'>X</div>
|
||||
<div class='box'>
|
||||
<button type='submit' name='action' value='right' form='movement'>▶</button>
|
||||
</div>
|
||||
<div class='box'></div>
|
||||
<div class='box'>
|
||||
<button type='submit' name='action' value='down' form='movement'>🔽</button>
|
||||
</div>
|
||||
<div class='box'></div>
|
||||
</div>
|
||||
|
||||
<button type='submit' name='action' value='clear' form='movement'>Сброс</button>
|
103
showmap.php
@ -1,103 +0,0 @@
|
||||
<?
|
||||
session_start();
|
||||
|
||||
if (!isset($_GET["name"])) $_GET["name"] ="map";
|
||||
|
||||
//Читаем карту
|
||||
$handle = fopen(htmlspecialchars($_GET["name"]).".csv", "r");
|
||||
while (($data = fgetcsv($handle, 1000, ";")) !== FALSE){
|
||||
$map[]=$data;
|
||||
}
|
||||
fclose($handle);
|
||||
//Карта в двухмерном массиве $map
|
||||
|
||||
//информация о квадрате
|
||||
/*
|
||||
$infodot["g"]["status"] = "allow";
|
||||
$infodot["m"]["status"] = "allow";
|
||||
|
||||
if ($_GET['action']=='down' AND $infodot[$map[$_SESSION["y"]+1][$_SESSION["x"]]]["status"]=='allow'){
|
||||
$_SESSION["y"]++;
|
||||
}
|
||||
if ($_GET['action']=='up' AND $infodot[$map[$_SESSION["y"]-1][$_SESSION["x"]]]["status"]=='allow'){
|
||||
$_SESSION["y"]--;
|
||||
}
|
||||
If ($_GET['action']=='left' AND $infodot[$map[$_SESSION["y"]][$_SESSION["x"]-1]]["status"]=='allow'){
|
||||
$_SESSION["x"]--;
|
||||
}
|
||||
if ($_GET['action']=='right' AND $infodot[$map[$_SESSION["y"]][$_SESSION["x"]+1]]["status"]=='allow'){
|
||||
$_SESSION["x"]++;
|
||||
}
|
||||
*/
|
||||
//если первый заход на карту
|
||||
if (!isset($_SESSION["y"]) OR !isset($_SESSION["x"])){
|
||||
$_SESSION["y"]=5;
|
||||
$_SESSION["x"]=5;
|
||||
}
|
||||
|
||||
//Строим квадрат 5Х5 вокруг игрока
|
||||
#$y = $_SESSION["y"]-10;
|
||||
#$y_end = $_SESSION["y"]+10;
|
||||
#$x = $_SESSION["x"]-20;
|
||||
#$x_end = $_SESSION["x"]+20;
|
||||
#$q = $x;
|
||||
|
||||
$y = -1;
|
||||
$y_end = 20;
|
||||
$x = -1;
|
||||
$x_end = 40;
|
||||
$q = $x;
|
||||
|
||||
|
||||
print "<table cellpadding='0' cellspacing='0'>";
|
||||
while ($y <= $y_end){
|
||||
print "<tr>";
|
||||
$x = $q;
|
||||
while ($x <= $x_end){
|
||||
if (@$map[$y][$x] == ""){ // ползут ошибки!
|
||||
$map[$y][$x] = "end";
|
||||
}
|
||||
if ($y == $_SESSION["y"] AND $x == $_SESSION["x"]){
|
||||
print "<td background = mapimg/".$map[$y][$x].".png>";
|
||||
print "<img src=mapimg/point.gif>";
|
||||
print "</td>";
|
||||
}
|
||||
else{
|
||||
print "<td background = mapimg/g.png>";
|
||||
print "<img src=mapimg/".$map[$y][$x].".png>";
|
||||
print "</td>";
|
||||
}
|
||||
$x++;
|
||||
}
|
||||
print "</tr>";
|
||||
$y++;
|
||||
}
|
||||
print "</table>";
|
||||
//квадрат построен
|
||||
/*
|
||||
?>
|
||||
|
||||
<a href=map.php?action=up><img src=mapimg/m-n.png border=0></a><br>
|
||||
<a href=map.php?action=left><img src=mapimg/m-w.png border=0></a>
|
||||
<a href=map.php?action=right><img src=mapimg/m-e.png border=0></a><br>
|
||||
<a href=map.php?action=down><img src=mapimg/m-s.png border=0></a><p>
|
||||
|
||||
<?
|
||||
*/
|
||||
/*
|
||||
//Описываем свойство отдельной клетки с координатами 2,2
|
||||
if ($_SESSION["y"] == 2 AND $_SESSION["x"] == 2){
|
||||
print "<b>В этой клетке c координатами 2,2 находится магазин";
|
||||
}
|
||||
else{
|
||||
print "В этой клетке нет активных элементов";
|
||||
}
|
||||
*/
|
||||
|
||||
//Описываем свойство целого класса клеток
|
||||
/*
|
||||
if ($map[$_SESSION["y"]][$_SESSION["x"]] == "m"){
|
||||
print "<b>В этой клетке класса <i>m</i> находится магазин";
|
||||
}
|
||||
*/
|
||||
?>
|
100
src/Insallah/Map/Map.php
Normal file
@ -0,0 +1,100 @@
|
||||
<?php
|
||||
# Date: 20.02.2022 (16:42)
|
||||
namespace Insallah\Map;
|
||||
|
||||
use Insallah\Player\Player;
|
||||
|
||||
class Map
|
||||
{
|
||||
private array $map;
|
||||
/** Это должно прилетать вместе с картой, но мне лень. */
|
||||
private const ALLOWED_PATH_MARKS = [
|
||||
'g' => ['status' => 1],
|
||||
'm' => ['status' => 1, 'message' => 'Тут может быть ваша реклама!'],
|
||||
];
|
||||
|
||||
public function __construct(MapData $mapData, $force = null)
|
||||
{
|
||||
$this->map = $mapData->getMap();
|
||||
Player::start([$mapData->getStartx(), $mapData->getStarty()], $force);
|
||||
}
|
||||
|
||||
private function canMoveTo($x, $y): bool
|
||||
{
|
||||
return
|
||||
$x >= 0 && $y >= 0 &&
|
||||
!empty($this->map[$y][$x]) &&
|
||||
!empty(self::ALLOWED_PATH_MARKS[$this->map[$y][$x]]) &&
|
||||
self::ALLOWED_PATH_MARKS[$this->map[$y][$x]]['status'] === 1;
|
||||
}
|
||||
|
||||
private function mapImage(int $x, int $y): string
|
||||
{
|
||||
if ($x < 0 || $y < 0 || empty($this->map[$y][$x])) {
|
||||
return '../resources/img/end.png';
|
||||
}
|
||||
return '../resources/img/' . $this->map[$y][$x] . '.png';
|
||||
}
|
||||
|
||||
public function goUp()
|
||||
{
|
||||
if ($this->canMoveTo(Player::getPos()[0], Player::getPos()[1] - 1)) {
|
||||
Player::modYPos(-1);
|
||||
}
|
||||
}
|
||||
|
||||
public function goDown()
|
||||
{
|
||||
if ($this->canMoveTo(Player::getPos()[0], Player::getPos()[1] + 1)) {
|
||||
Player::modYPos(+1);
|
||||
}
|
||||
}
|
||||
|
||||
public function goLeft()
|
||||
{
|
||||
if ($this->canMoveTo(Player::getPos()[0] - 1, Player::getPos()[1])) {
|
||||
Player::modXPos(-1);
|
||||
}
|
||||
}
|
||||
|
||||
public function goRight()
|
||||
{
|
||||
if ($this->canMoveTo(Player::getPos()[0] + 1, Player::getPos()[1])) {
|
||||
Player::modXPos(+1);
|
||||
}
|
||||
}
|
||||
|
||||
public function drawVisible(int $radius = 2): string
|
||||
{
|
||||
$x_last = Player::getPos()[0] + $radius;
|
||||
$y = Player::getPos()[1] - $radius;
|
||||
$y_last = Player::getPos()[1] + $radius;
|
||||
|
||||
$message = !empty(self::ALLOWED_PATH_MARKS[$this->map[Player::getPos()[1]][Player::getPos()[0]]]['message']) ?
|
||||
self::ALLOWED_PATH_MARKS[$this->map[Player::getPos()[1]][Player::getPos()[0]]]['message'] : '';
|
||||
|
||||
$str = '<table>';
|
||||
$str .= '<caption>Некий остров</caption>';
|
||||
$str .= "<tr><th colspan='" . ($radius * 2 + 1) . "'>$message</th></tr>";
|
||||
while ($y <= $y_last) {
|
||||
$str .= '<tr>';
|
||||
$x = Player::getPos()[0] - $radius;
|
||||
while ($x <= $x_last) {
|
||||
$mapImage = $this->mapImage($x, $y);
|
||||
if ($x === Player::getPos()[0] && $y === Player::getPos()[1]) {
|
||||
$str .= "<td style='background-image: url($mapImage)'>";
|
||||
$str .= '<img src="../resources/img/point.gif" alt="player">';
|
||||
} else {
|
||||
$str .= '<td>';
|
||||
$str .= "<img src='$mapImage' alt='mapsqare' title='$mapImage'>";
|
||||
}
|
||||
$str .= '</td>';
|
||||
$x++;
|
||||
}
|
||||
$str .= '</td>';
|
||||
$y++;
|
||||
}
|
||||
$str .= '</table>';
|
||||
return $str;
|
||||
}
|
||||
}
|
72
src/Insallah/Map/MapData.php
Normal file
@ -0,0 +1,72 @@
|
||||
<?php
|
||||
# Date: 20.02.2022 (16:21)
|
||||
namespace Insallah\Map;
|
||||
|
||||
class MapData
|
||||
{
|
||||
private array $map;
|
||||
private int $startx;
|
||||
private int $starty;
|
||||
private const DEF_XY = [
|
||||
'map' => ['x' => 5, 'y' => 5],
|
||||
'map2' => ['x' => 2, 'y' => 4],
|
||||
];
|
||||
private static string $filename;
|
||||
|
||||
public function __construct(?string $mapName)
|
||||
{
|
||||
if (empty($mapName)) {
|
||||
$mapName = 'map';
|
||||
}
|
||||
self::$filename = dirname(getcwd()) . '/resources/maps/' . htmlspecialchars($mapName) . '.csv';
|
||||
$handle = fopen(self::$filename, 'r');
|
||||
while (($data = fgetcsv($handle, 1000, ';')) !== false) {
|
||||
$this->map[] = $data;
|
||||
}
|
||||
fclose($handle);
|
||||
$this->startx = self::DEF_XY[$mapName]['x'];
|
||||
$this->starty = self::DEF_XY[$mapName]['y'];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getMap(): array
|
||||
{
|
||||
return $this->map;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function getStartx(): int
|
||||
{
|
||||
return $this->startx;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function getStarty(): int
|
||||
{
|
||||
return $this->starty;
|
||||
}
|
||||
|
||||
public static function drawFullMap()
|
||||
{
|
||||
$file = fopen(self::$filename, 'r');
|
||||
echo '<table>';
|
||||
while (($data = fgetcsv($file, null, ';')) !== false) {
|
||||
echo '<tr>';
|
||||
foreach ($data as $i) {
|
||||
if (empty($i)) {
|
||||
$i = 'end';
|
||||
}
|
||||
echo "<td><img src='../resources/img/$i.png' width='25px' height='25px' alt='map'></td>";
|
||||
}
|
||||
echo "</tr>\n";
|
||||
}
|
||||
echo '</table>';
|
||||
fclose($file);
|
||||
}
|
||||
}
|
45
src/Insallah/Player/Player.php
Normal file
@ -0,0 +1,45 @@
|
||||
<?php
|
||||
# Date: 20.02.2022 (17:47)
|
||||
namespace Insallah\Player;
|
||||
|
||||
class Player
|
||||
{
|
||||
public static function start(array $xy, $force = null)
|
||||
{
|
||||
if (!isset($_SESSION['x']) || !isset($_SESSION['y']) || !is_null($force)) {
|
||||
$_SESSION['x'] = $xy[0];
|
||||
$_SESSION['y'] = $xy[1];
|
||||
}
|
||||
}
|
||||
|
||||
public static function getPos(): array
|
||||
{
|
||||
return [$_SESSION['x'], $_SESSION['y']];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $x_pos
|
||||
*/
|
||||
public static function modXPos(int $x_pos): void
|
||||
{
|
||||
if ($_SESSION['x'] + $x_pos >= 0) {
|
||||
$_SESSION['x'] += $x_pos;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $y_pos
|
||||
*/
|
||||
public static function modYPos(int $y_pos): void
|
||||
{
|
||||
if ($_SESSION['y'] + $y_pos >= 0) {
|
||||
$_SESSION['y'] += $y_pos;
|
||||
}
|
||||
}
|
||||
|
||||
public static function clear()
|
||||
{
|
||||
session_destroy();
|
||||
header('Location: ' . $_SERVER['REQUEST_URI']);
|
||||
}
|
||||
}
|