【PHP】RPGゲームを作る その1(フィールド移動)

実行画面 PHP
RPGゲーム

PHPでPRGゲームを作ります。サンプルソースを載せつつついけるところまでやってみようと思います。

環境

 OS ubuntu22.04 
 Webサーバ apache2.4.52(自身のIP 192.168.19.128、公開フォルダ /var/www/html)
 PHP 8.1.2-1ubuntu2.14

フィールド画面を作る

マップを作成し、マップ上を主人公が移動するところまで作成します。
とりあえず今回はゲームのイメージをつかみたいので、マップデータもテキストデータを読み込む形にしています。
ソースは次の内容を作成しました。

<!DOCTYPE html>
<html>
<head>
<style>
table,tr,th,td{
	border-collapse:collapse;
	border-spacing:0;
	margin:0;
	padding:0;
	border:none
	line-height: 0;
	display: flex;
}

</style>
</head>
<body>
<script type="text/javascript">
<!--
function press_up_button(){
	document.getElementById("do").value="up";
	document.gameform.submit();
}
function press_down_button(){
	document.getElementById("do").value="down";
	document.gameform.submit();
}
function press_left_button(){
	document.getElementById("do").value="left";
	document.gameform.submit();
}
function press_right_button(){
	document.getElementById("do").value="right";
	document.gameform.submit();
}
function press_menu_button(){
	document.getElementById("do").value="menu";
	document.gameform.submit();
}
// --></script>
<?php
$data = "000000000022200000000000000000000000000000000000000000000000
000000000000000000222220000000000000000000000000000000000000
000000000000000000222000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000
000000000000066666666666666666611166666666666666600000000000
000000000666655566666666666655511155555555555555556600000000
000000006655555555666666655555511555555555555555555660000000
000000066555555556665555555555115555555555555555555660000000
000000066555555556665555555551155555555555555555555660000000
000000066555555556555555555511555555555555555566666600000000
000000000066555111111555555115555555555555115600000000000000
000000000011111555551111111111111155555555505600000000000000
000000000665555555551111111111111155555555555566666000000000
000000000665555555555511111111155555555555555555566000000000
000000000665555555555551111111115555555555555555555660000000
000000000665555555555555551111155555555555775555555660000000
000000000665555555555555551111115555551115555555556600000000
000000000665555555555555555111115555115551111111111100000000
000000000665551111111555555555551111555555555555556600000000
000000000665555511155555555555551111555555555555555660000000
000000000665555555555555555555555111155555555555556666000000
000000006655555555555555555551155555555555555555560000000000
000000006655555555555555555555555555555555555566600000000000
000000000066555555555555555555555555555555556600000000000000
000000000000066555555555555555555555555555660000000000000000
000000000000006665555555555555555556666666000000000000000000
000000000000000006655555555666666660000000000000000000000000
000000000000000665555556666000000555566000000000000000000000
002220000000066555555660000000005555660000000000000000000000
022200000000066666666660000000006666666600000000000000000000
000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000";

if ($_SERVER['REQUEST_METHOD'] === 'POST' 
	&& isset($_POST['do']) 
	&& isset($_POST['user_x']) 
	&& isset($_POST['user_y']) 
	&& isset($_POST['user'])) {

    $do = $_POST['do'];
    $user = $_POST['user'];
    $userx=$_POST['user_x'];
    $usery=$_POST['user_y'];
	//整合性チェック
	//移動先の確認
    if($do === 'up'){$usery--;}
    if($do === 'down'){$usery++;}
    if($do === 'left'){$userx--;}
    if($do === 'right'){$userx++;}
} else {
	//初期場所
	$userx=30;
	$usery=12;
}

$rows = explode("\n", $data); // 行ごとに分割
$y = 0;
$map_wide=4;
echo '<table>';
foreach ($rows as $row) {
    $y=$y+1;
    if($y >= $usery-$map_wide && $y <= $usery + $map_wide){
    echo '<tr>';

    for ($x = 0; $x < strlen($row); $x++) {
        if($x >= $userx-$map_wide && $x <= $userx + $map_wide){
            echo '<td>';
            if($y == $usery && $x == $userx){
                echo '<img src="./img/me.jpg" width="20.px">';
            }else {
                echo '<img src="./img/0'.$row[$x].'.jpg" width="20.px">';
            }
            echo '</td>';
        }

    }
    echo '</tr>';

    }

}
echo '</table>';

echo "<form method='post' name='gameform' action=''>"; //自分自身にaction
echo 'ユーザ名<input type="text"  name="user" value="user1" readonly><br>';
echo '<input type="hidden" name="pass" value="pass" readonly>';
echo 'HP<input type="text" name="hp" value="100" readonly><br>';
echo '<input type="hidden" name="user_x" value="' .$userx. '">';
echo '<input type="hidden" name="user_y" value="' .$usery. '">';
echo '<input type="hidden" name="user_map" value="1">';
echo '<input type="hidden" name="do" id="do" value="">';
echo '<table>';
echo '<tr>';
echo '<td width="30px" align="center"> </td>';
echo '<td width="23px" align="center"><input type ="button" value="↑" onclick="press_up_button();"></td>';
echo '<td width="30px" align="center"> </td>';
echo '<td width="100px" align="right"><input type ="button" name="left" value="MENU" onclick="press_menu_button();"></td>';
echo '</tr>';
echo '<tr>';
echo '<td width="30px" align="center"><input type ="button" name="left" value="←" onclick="press_left_button();"></td>';
echo '<td width="23px" align="center"> </td>';
echo '<td width="30px" align="center"><input type ="button" name="left" value="→" onclick="press_right_button();"></td>';
echo '<td width="100px" align="center"> </td>';
echo '</tr>';
echo '<tr>';
echo '<td width="30px" align="center"> </td>';
echo '<td width="23px" align="center"><input type ="button" name="left" value="↓" onclick="press_down_button();"></td>';
echo '<td width="30px" align="center"> </td>';
echo '<td width="100px" align="center"> </td>';
echo '</tr>';
echo '</table>';
echo "</form>";
?>
</body>
</html>

 もう少しきれいなソースを書けるように頑張りたいと思います。(かなり強引に作っています)

● マップデータ
 マップデータはテストデータなので、PHP内に直接書き込みました。いずれはDBにマップテーブルを作りたいと思っていますが、エクセルのような二次元配列テーブルを作るにはどうしようか考え中です。
 マップ番号をそのままファイル名にしています。(0:海 だったら 00.jpgとしました)
 画像ファイルをソースフォルダに配置すると見にくくなるので、画像ファイルは、
   /var/www/html/php/rpg/img
以下に配置し、
   フォルダのパーミッション 705
   画像ファイルのパーミッション 604
としています。

●チート対策
 メソッドをPOST限定にしているのはチート対策です。
 以前作成したプログラムで、GETメソッドから不正なコードを入力されたことがあったので、GETメソッドは極力使用しないようにしています。
 画面遷移後に、DBデータとの整合性チェックを行い、チート対策を行う予定です。

●画面遷移
 DOというパラメータに、押されたボタンを識別する文字列を入れて自分自身をsubmitで呼び出すという方法をとりました。
 この方法を使えば、一つのPHPファイルでゲームを実装できますが、ソースがスパゲッティになりやすいので注意が必要です。

実行画面

実行した画面は、こんな感じになります。

ゲームを実行した様子
 十字ボタンをマウスでクリックするとキャラクタが移動します。

作り始めたばかりなので、メニューや戦闘シーンなどは実装していませんが、これからタイミングを見て実装していきたいと思います。

今回作ったプログラムはこちらから確認できます。