На PHP простая ролевая игра (недострой) - проект обучения


Друг заставляет меня постить код сюда, потому что ему не нравятся мои длинные переменных $_SESSION, и я говорю ему, нет никакого способа его остановить не позже в коде, снова определяя их что ненужные накладные расходы. Я понимаю, мне не нужен класс для каждого монстра я планирую переделать, что позже.

Играбельную версию: https://vanjavk.me/rpggame/ (код изменился сейчас)

<?php
session_start();



if(!isset($_SESSION['hp'])) {
    $_SESSION['hp']=10;
}

if(!isset($_SESSION['randomenemy'])) {
    $_SESSION['randomenemy']=0;
}



if(!isset($_SESSION['gold'])) {
    $_SESSION['gold']=0;
}

if(!isset($_SESSION['xp'])) {
    $_SESSION['xp']=100;
}

if(!isset($_SESSION['xy'])) {
    $_SESSION['xy']=array(0,0);
}
function calculateLevel($xp)
{
    $level=0;
    $startxp=100;
    $increase=0.1;
    while ($xp>=$startxp+$level*$increase*$startxp)
    {
        $xp-=$startxp+$level*$increase*$startxp;
        $level++;
    }
    $hp=10*$level;

    return array($level,$xp,$hp);
}

$levelxp = calculateLevel($_SESSION['xp']);

if(isset($_POST['name'])) {
    $_SESSION['name']=$_POST['name'];
}
if(isset($_POST['heal'])) {
    $_SESSION['hp']=15+$levelxp[2];
}

class location {
    public $name;
    public $xy;
    public $description;
    public $enemies;
    public $img;
    public $info;

    public function __construct($name,$xy,$description,$enemies,$img,$info)
    {
        $this->name = $name;
        $this->xy = $xy;
        $this->description = $description;
        $this->enemies = $enemies;
        $this->img = $img;
        $this->info = $info;
    }

}

class enemyBear {
    public $name;
    public $hp;
    public $description;
    public $minDmg;
    public $maxDmg;
    public $critChance;
    public $missChance;
    public $img;

    public function __construct()
    {
        $this->name = "Bear";
        $this->hp = 20;
        $this->description = "A mighty bear.";
        $this->minDmg = 0;
        $this->maxDmg = 2;
        $this->critChance = 0.03;
        $this->missChance = 0.20;
        $this->img = "img/bear.jpg";
    }
}
class enemyBoar {
    public $name;
    public $hp;
    public $description;
    public $minDmg;
    public $maxDmg;
    public $critChance;
    public $missChance;
    public $img;

    public function __construct()
    {
        $this->name = "Bear";
        $this->hp = 12;
        $this->description = "A wild boar.";
        $this->minDmg = 0;
        $this->maxDmg = 2;
        $this->critChance = 0.1;
        $this->missChance = 0.25;
        $this->img = "img/bear.jpg";
    }
}
class enemyWolf {
    public $name;
    public $hp;
    public $description;
    public $minDmg;
    public $maxDmg;
    public $critChance;
    public $missChance;
    public $img;

    public function __construct()
    {
        $this->name = "Wolf";
        $this->hp = 8;
        $this->description = "A wolf with sharp teeth.";
        $this->minDmg = 0;
        $this->maxDmg = 3;
        $this->critChance = 0.25;
        $this->missChance = 0.15;
        $this->img = "img/wolf.jpg";
    }
}
class enemyReaper {
    public $name;
    public $hp;
    public $description;
    public $minDmg;
    public $maxDmg;
    public $critChance;
    public $missChance;
    public $img;

    public function __construct()
    {
        $this->name = "Harvest reaper";
        $this->hp = 55;
        $this->description = "Stay off my field you pest.";
        $this->minDmg = 3;
        $this->maxDmg = 7;
        $this->critChance = 0.15;
        $this->missChance = 0.15;
        $this->img = "img/reaper.jpg";
    }
}
class enemyVulture {    
    public $name;
    public $hp;
    public $description;
    public $minDmg;
    public $maxDmg;
    public $critChance;
    public $missChance;
    public $img;

    public function __construct()
    {
        $this->name = "Vulture fleshripper";
        $this->hp = 35;
        $this->description = "Mmmmm... Flesh of fallen angels.";
        $this->minDmg = 5;
        $this->maxDmg = 10;
        $this->critChance = 0.25;
        $this->missChance = 0.15;
        $this->img = "img/vulture.jpg";
    }
}
//array(0,0)
if(!isset($_SESSION['locations'])) {
$_SESSION['locations']=array("0,0"=>new location("Goldshire inn",array(0,0),"Relax and dance in our inn.",array(),"img/goldshire.jpg","Melika Isenstrider greets you!"),
    "1,0"=>new location("Elwynn Forest",array(1,0),"Monsters lurk here.",array(new enemyBoar(), new enemyWolf(), new enemyBoar(), new enemyWolf(), new enemyBear(), new enemyBoar(), new enemyWolf(), new enemyBoar(), new enemyWolf(), new enemyBear()),"img/elwynn.jpg","You hear a strange sound."),
    "-1,0"=>new location("Westfall",array(-1,0),"Farmers are fightning wild animals.",array(new enemyVulture(), new enemyReaper(), new enemyVulture(), new enemyReaper(), new enemyReaper(), new enemyVulture(), new enemyReaper(), new enemyVulture(), new enemyReaper()),"img/westfall.jpg","You hear a strange mechanical sound."),
    "-1,-1"=>new location("Sentinel hill",array(-1,-1),"Everyone is peacefully enjoying sunny weather.",array(),"img/sentinelhill.jpg","You hear a welcoming sound."));
}
function splitString1($string)
{
    $x=substr($string, 0, 10);
    while (strlen($x)!=10){
        $x.=".";
    }
    return $x;
};
function splitString2($string)
{
    $x=substr($string, 10, 10);
    while (strlen($x)!=10){
        $x.=".";
    }
    return $x;
};
function attackEnemy($maxDmg,$minDmg,$critChance,$missChance){
    $attackdmg=0;
    $msg="miss";
    if (mt_rand()/mt_getrandmax()>$missChance){
        $attackdmg=random_int($minDmg,$maxDmg);
        $msg="hit";
        if (mt_rand()/mt_getrandmax()<$critChance){
            $attackdmg*=1.5;
            $msg="crit";
        }
    }
    return array($attackdmg,$msg);
}
function attack($level){
    return round($level+rand(0,5)/10*$level,2);
}
function combat($attack)
{
    $attackdmg= attack($GLOBALS["levelxp"][0]);
    $_SESSION['locations'][$_SESSION['xy'][0].",".$_SESSION['xy'][1]]->enemies[$_SESSION['randomenemy']]->hp-=$attackdmg;
    $attackdmge=attackEnemy($_SESSION['locations'][$_SESSION['xy'][0].",".$_SESSION['xy'][1]]->enemies[$_SESSION['randomenemy']]->maxDmg,$_SESSION['locations'][$_SESSION['xy'][0].",".$_SESSION['xy'][1]]->enemies[$_SESSION['randomenemy']]->minDmg,$_SESSION['locations'][$_SESSION['xy'][0].",".$_SESSION['xy'][1]]->enemies[$_SESSION['randomenemy']]->critChance,$_SESSION['locations'][$_SESSION['xy'][0].",".$_SESSION['xy'][1]]->enemies[$_SESSION['randomenemy']]->missChance);
    $_SESSION['hp']-=$attackdmge[0];
    if ($attack)
    {
        $_SESSION['locations'][$_SESSION['xy'][0].",".$_SESSION['xy'][1]]->info.="<p style='color:#1aa51d;'>You hit " . $_SESSION['locations'][$_SESSION['xy'][0].",".$_SESSION['xy'][1]]->enemies[$_SESSION['randomenemy']]->name . " for " . $attackdmg . ". Current hp: ". $_SESSION['locations'][$_SESSION['xy'][0].",".$_SESSION['xy'][1]]->enemies[$_SESSION['randomenemy']]->hp ."</p>";
    }else{
       $_SESSION['locations'][$_SESSION['xy'][0].",".$_SESSION['xy'][1]]->info.="<p style='color:#bcab2d;'>You tried to flee, but failed.</p>";
    }

    if ($attackdmge[1]==="hit")
    {
        $_SESSION['locations'][$_SESSION['xy'][0].",".$_SESSION['xy'][1]]->info.="<p style='color:#f4424b;'>" . $_SESSION['locations'][$_SESSION['xy'][0].",".$_SESSION['xy'][1]]->enemies[$_SESSION['randomenemy']]->name . " hit you for " . $attackdmge[0] . ". Your hp: ". $_SESSION["hp"] ."</p>";

    }elseif ($attackdmge[1]==="miss") {
        $_SESSION['locations'][$_SESSION['xy'][0].",".$_SESSION['xy'][1]]->info.="<p style='color:#9e9e9e;'>" . $_SESSION['locations'][$_SESSION['xy'][0].",".$_SESSION['xy'][1]]->enemies[$_SESSION['randomenemy']]->name . " missed you. Your hp: ". $_SESSION["hp"] ."</p>";
    }elseif ($attackdmge[1]==="crit") {
        $_SESSION['locations'][$_SESSION['xy'][0].",".$_SESSION['xy'][1]]->info.="<p style='color:#af0c14;'>" . $_SESSION['locations'][$_SESSION['xy'][0].",".$_SESSION['xy'][1]]->enemies[$_SESSION['randomenemy']]->name . " critically hit you for " . $attackdmge[0] . ". Your hp: ". $_SESSION["hp"] ."</p>";
    }


    if ($_SESSION['hp']<=0)
    {
        echo "<script>window.alert('You died!');</script>";
        header("Location: http://vanjavk.me/rpggame/reset.php");
        die();
    }

    if ($_SESSION['locations'][$_SESSION['xy'][0].",".$_SESSION['xy'][1]]->enemies[$_SESSION['randomenemy']]->hp<=0)
    {
        $_SESSION['locations'][$_SESSION['xy'][0].",".$_SESSION['xy'][1]]->info.="<p style='color:#000000;'>" . $_SESSION['locations'][$_SESSION['xy'][0].",".$_SESSION['xy'][1]]->enemies[$_SESSION['randomenemy']]->name . " died. You earned 50 xp!</p>";
        array_shift($_SESSION['locations'][$_SESSION['xy'][0].",".$_SESSION['xy'][1]]->enemies);
        $_SESSION['xp']+=50;

    }

}
if(isset($_POST['attack'])) 
{
    combat(true);
}
function post($string){
    return "<a onclick='document.getElementById(".$string.").click();' href='#'>";
}
function leaveCombat(){
    if (sizeof($_SESSION['locations'][$_SESSION['xy'][0].",".$_SESSION['xy'][1]]->enemies)>0)
    {
      if (mt_rand()/mt_getrandmax()<0.35)
      {
        return false;
      } else {
        combat(false);
        return true;
      }
    }

}
if(isset($_POST['right'])) {
    if (isset($_SESSION['locations'][($_SESSION['xy'][0]+1).",".$_SESSION['xy'][1]]))
    {
        (function(){
        if (leaveCombat()){ return; }
        $_SESSION['xy'][0]+=1;
        })();
    }
}
if(isset($_POST['left'])) {
    if (isset($_SESSION['locations'][($_SESSION['xy'][0]-1).",".$_SESSION['xy'][1]]))
    {
        (function(){
        if (leaveCombat()){ return; }
        $_SESSION['xy'][0]-=1;
        })();
    }
}
if(isset($_POST['up'])) {
    if (isset($_SESSION['locations'][$_SESSION['xy'][0].",".($_SESSION['xy'][1]+1)]))
    {
        (function(){
        if (leaveCombat()){ return; }
        $_SESSION['xy'][1]+=1;
        })();
    }
}
if(isset($_POST['down'])) {
    if (isset($_SESSION['locations'][$_SESSION['xy'][0].",".($_SESSION['xy'][1]-1)]))
    {
        (function(){
        if (leaveCombat()){ return; }
        $_SESSION['xy'][1]-=1;
        })();
    }
}
//echo $_SESSION['xy'][0].",".$_SESSION['xy'][1];
//echo $_SESSION['locations'][$_SESSION['xy'][0].",".$_SESSION['xy'][1]]->description;
?>

<!DOCTYPE html>

<html>
    <head>
        <script
        src="https://code.jquery.com/jquery-3.3.1.min.js"
        integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8="
        crossorigin="anonymous"></script>
        <link rel="stylesheet" type="text/css" href="/css/default.css">
        <link rel="stylesheet" type="text/css" href="css/default.css">
        <meta charset="UTF-8">
        <title>vanjavk</title>
    </head>
    <body>
        <script>
            var left="left";
            var right="right";
            var up="up";
            var down="down";
            var W = [119,87];
            var A = [97,65];
            var S = [115,83];
            var D = [100,68];
            document.onkeydown = function(event){
            if(D.includes(event.which) || D.includes(event.keyCode))    //d
                document.getElementById(right).click();
            else if(S.includes(event.which) || S.includes(event.keyCode))   //s    //d
                document.getElementById(down).click();
            else if(A.includes(event.which) || A.includes(event.keyCode)) //a    //d
                document.getElementById(left).click();
            else if(W.includes(event.which) || W.includes(event.keyCode))     //d
                document.getElementById(up).click();
            }
        </script>
        <div class="container">
            <div class="topleft">
<?php
if(isset($_SESSION["name"])) {
    echo "Your name: " . $_SESSION['name'] . "<br>";
    echo "Hitpoints: " . $_SESSION['hp'] . "<br>";
    echo "Gold: " . $_SESSION['gold'] . "<br>";
    echo "XP: " . $levelxp[1] . "<br>";
    echo "Level: " . $levelxp[0] . "<br>";
    echo "Location: " . $_SESSION['xy'][0] . ", " . $_SESSION['xy'][1] . "<br>";
    echo "<a href='reset.php'>RESET ALL DATA</a><br>";
    if (isset($_SESSION['locations'][$_SESSION['xy'][0].",".$_SESSION['xy'][1]]->enemies[$_SESSION['randomenemy']]->hp)){
        if ($_SESSION['locations'][$_SESSION['xy'][0].",".$_SESSION['xy'][1]]->enemies[$_SESSION['randomenemy']]->hp>0)
        {
            echo "<br>Enemy name: ".$_SESSION['locations'][$_SESSION['xy'][0].",".$_SESSION['xy'][1]]->enemies[$_SESSION['randomenemy']]->name."<br>";
            echo "Enemy description: ".$_SESSION['locations'][$_SESSION['xy'][0].",".$_SESSION['xy'][1]]->enemies[$_SESSION['randomenemy']]->description."<br>";
            echo "Enemy hitpoints: ".$_SESSION['locations'][$_SESSION['xy'][0].",".$_SESSION['xy'][1]]->enemies[$_SESSION['randomenemy']]->hp."<br>";
            echo "Enemy max damage: ".$_SESSION['locations'][$_SESSION['xy'][0].",".$_SESSION['xy'][1]]->enemies[$_SESSION['randomenemy']]->maxDmg."<br>";
            echo "Enemy min damage: ".$_SESSION['locations'][$_SESSION['xy'][0].",".$_SESSION['xy'][1]]->enemies[$_SESSION['randomenemy']]->minDmg."<br>";
            echo "Enemy crit chance: ".$_SESSION['locations'][$_SESSION['xy'][0].",".$_SESSION['xy'][1]]->enemies[$_SESSION['randomenemy']]->critChance."<br>";
            echo "Enemy miss chance: ".$_SESSION['locations'][$_SESSION['xy'][0].",".$_SESSION['xy'][1]]->enemies[$_SESSION['randomenemy']]->missChance."<br>";
        }
    }
} else {
    echo "Hey! Tell us your name: <form method='post' action=''>
    <input type='text' name='name'>
    <input type='submit'>
    </form>" . PHP_EOL;

}
?>


            </div>
            <div class="top"><div id="info">
<?php




echo $_SESSION['locations'][$_SESSION['xy'][0].",".$_SESSION['xy'][1]]->info;
?>

            </div></div>
            <script>$("#info").scrollTop($("#info")[0].scrollHeight);</script>
            <div class="topright">
                <div class="topright1">
<?php
//echo $_SESSION['locations'][$_SESSION['xy'][0].",".$_SESSION['xy'][1]];
echo "<h1>".$_SESSION['locations'][$_SESSION['xy'][0].",".$_SESSION['xy'][1]]->name . "</h1><br>";
echo $_SESSION['locations'][$_SESSION['xy'][0].",".$_SESSION['xy'][1]]->description . "<br>";
echo "<img src='".$_SESSION['locations'][$_SESSION['xy'][0].",".$_SESSION['xy'][1]]->img."' style='max-width:100%;max-height:80%;'>" . "<br>";
?>
                </div>
                <div class="topright2">

<?php
//echo $_SESSION['locations'][$_SESSION['xy'][0].",".$_SESSION['xy'][1]];
echo "<h1>".$_SESSION['locations'][$_SESSION['xy'][0].",".$_SESSION['xy'][1]]->enemies[$_SESSION['randomenemy']]->name . "</h1><br>";
echo $_SESSION['locations'][$_SESSION['xy'][0].",".$_SESSION['xy'][1]]->enemies[$_SESSION['randomenemy']]->description . "<br>";
echo "<img src='".$_SESSION['locations'][$_SESSION['xy'][0].",".$_SESSION['xy'][1]]->enemies[$_SESSION['randomenemy']]->img."' style='max-width:100%;max-height:80%;'>" . "<br>";
?>
                </div>
            </div>
            <div class="botleft"><h1>botleft Page</h1></div>
            <div class="bot"><div class="bot1">
<?php
if (sizeof($_SESSION['locations'][$_SESSION['xy'][0].",".$_SESSION['xy'][1]]->enemies)>0){
    echo "<form method='post' action=''>
    <input name='attack' type='submit' value='attack'>
    </form>";
} else
{
    echo "<form method='post' action=''>
    <input name='heal' type='submit' value='heal'>
    </form>";  
}



?>
            </div><div class="bot2">



            </div>
            </div>
            <div class="botright">

<?php echo splitString1($_SESSION['locations'][($_SESSION['xy'][0]-1).",".($_SESSION['xy'][1]+1)]->name);?>|<?php echo post("up").splitString1($_SESSION['locations'][$_SESSION['xy'][0].",".($_SESSION['xy'][1]+1)]->name);?></a>|<?php echo splitString1($_SESSION['locations'][($_SESSION['xy'][0]+1).",".($_SESSION['xy'][1]+1)]->name);?><br>
<?php echo splitString2($_SESSION['locations'][($_SESSION['xy'][0]-1).",".($_SESSION['xy'][1]+1)]->name);?>|<?php echo post("up").splitString2($_SESSION['locations'][$_SESSION['xy'][0].",".($_SESSION['xy'][1]+1)]->name);?></a>|<?php echo splitString2($_SESSION['locations'][($_SESSION['xy'][0]+1).",".($_SESSION['xy'][1]+1)]->name);?><br>
--------------------------------<br>
<?php echo post("left").splitString1($_SESSION['locations'][($_SESSION['xy'][0]-1).",".$_SESSION['xy'][1]]->name);?></a>|<?php echo splitString1($_SESSION['locations'][$_SESSION['xy'][0].",".$_SESSION['xy'][1]]->name);?>|<?php echo post("right").splitString1($_SESSION['locations'][($_SESSION['xy'][0]+1).",".$_SESSION['xy'][1]]->name);?></a><br>
<?php echo post("left").splitString2($_SESSION['locations'][($_SESSION['xy'][0]-1).",".$_SESSION['xy'][1]]->name);?></a>|<?php echo splitString2($_SESSION['locations'][$_SESSION['xy'][0].",".$_SESSION['xy'][1]]->name);?>|<?php echo post("right").splitString2($_SESSION['locations'][($_SESSION['xy'][0]+1).",".$_SESSION['xy'][1]]->name);?></a><br>
--------------------------------<br>
<?php echo splitString1($_SESSION['locations'][($_SESSION['xy'][0]-1).",".($_SESSION['xy'][1]-1)]->name);?>|<?php echo post("down").splitString1($_SESSION['locations'][$_SESSION['xy'][0].",".($_SESSION['xy'][1]-1)]->name);?></a>|<?php echo splitString1($_SESSION['locations'][($_SESSION['xy'][0]+1).",".($_SESSION['xy'][1]-1)]->name);?><br>
<?php echo splitString2($_SESSION['locations'][($_SESSION['xy'][0]-1).",".($_SESSION['xy'][1]-1)]->name);?>|<?php echo post("down").splitString2($_SESSION['locations'][$_SESSION['xy'][0].",".($_SESSION['xy'][1]-1)]->name);?></a>|<?php echo splitString2($_SESSION['locations'][($_SESSION['xy'][0]+1).",".($_SESSION['xy'][1]-1)]->name);?><br>

            </div>
        </div>
        <div style="visibility: hidden">
        <form name="post" action="" method="post">
        <input id="left" name="left" type='submit'>
        <input id="right" name="right" type='submit'>
        <input id="up" name="up" type='submit'>
        <input id="down" name="down" type='submit'>
        </div>
        </form>
    </body>

</html>


206
4
задан 31 марта 2018 в 09:03 Источник Поделиться
Комментарии
1 ответ

Для небольших, демо-приложений, $_SESSION Это хорошо для сохранения данных сессии. Однако, двигаясь вперед, вы должны знать о недостатках $_SESSION и почему это не рекомендуется.


  • Сервисы виртуального хостинга разделяют один и тот же экземпляр сервера для нескольких сайтов. Вы риск утечки ваших данных сессии с другими сайтами на одном сервере, если он плохо настроен.

  • Если ваш хост имеет возможности балансировки нагрузки, это может прозрачно распределения трафика между различными узлами. Переменная сессии может "исчезнуть", потому что сеанс передачи данных в одном сервере не обязательно на другом сервере.

  • Сеансы делают код трудно тестировать. Он может вызвать два идентичных запросов HTTP действовать по-разному в зависимости от устаревших данных сессии.

В идеале, ваш PHP-код должен быть без гражданства. Это позволяет код для масштабирования по горизонтали в среде с балансировкой нагрузки и действовать по той же схеме дан один и тот же вход. Любая форма государства, как и данные сессии, должны быть отодвинуты в другом месте, подальше от веб-сервера. Например, в CodeIgniter шифрует данные сессии в куки, при каждом запросе эффективно проводит свои сессии. Drupal есть модуль сессии, которая хранит данные сессии в базе данных, связаны с пользователем (в случае подлинности) или уникальный идентификатор в cookie (если без проверки подлинности).

Что касается классов, похоже, у вас есть несколько "вражеских" классов, которые выглядят одинаково. Рассмотреть вопрос о внесении один Enemy класс, а экземпляр этого. Если есть несколько классов с уникальными свойствами, но все-таки есть что-то общее с Enemy, подкласс Enemy для этого конкретного класса.

У вас также есть служебные функции в глобальной области видимости. Рассмотрим собирая их в один класс. Вы, вероятно, можете иметь их в качестве методов экземпляр служебного класса, или статические методы это служебный класс. В любом случае, просто не имея материалов на глобальном уровне.

Также рассмотреть возможность переноса логики и рендеринга в отдельные классы. В обычной Java-терминов, это будет включать ваш "оказание классы" и "Сервис-класс".

Теперь, когда все в классе, вы могли бы хотеть проверить в PHP класс-загрузки функции. Это позволяет регистрировать загрузчик класса, который позволяет PHP, чтобы загрузить классы на лету, а также определить свой код в один класс в одном файле мода, очень похож на Java.

Наконец, управление потоком. Вместо того, чтобы ваш скрипт выполняется сверху вниз с все разваливали в глобальном пространстве, можно определить "Шелл" класс, который инстанцирует одиночек логики классов (на Java, они называются "бобы"), управляет потоком данных в вашем приложении. Что-то вдоль линий...

// Enemy.php - base class for all enemies
class Enemy {...}

// Utils.php - all utility functions in here
class Utils {...}

// CombatLogic.php - All calculations go in here
class CombatLogic {...}

// PageRenderer.php - Receives data, and renders HTML
class PageRenderer {...}

// Request.php - All logic that grabs from $_POST, $_GET, etc goes here
class Request {...}

// Session.php - Logic that grabs session data from wherever you store it
class Session {...}

// App.php - Flow control here
class App {

public __construct(){
$this->renderer = new PageRenderer();
$this->session = new Session();
...and so on.
}

public function main(){
// Grab all data from Request
// Recreate session data from Session, Enemy, etc.
// Calculate new game state using CombatLogic, Utils, etc.
// Render using PageRenderer
}
}

(new App()).main()

Конечно, в больших масштабах приложений и CMSes, они могут быть очень общая и свободная (интерфейса, внедрения зависимостей, вещи), но общая идея очень похож на этот.

1
ответ дан 3 апреля 2018 в 01:04 Источник Поделиться