map_chipで作成したマップ素材を配置して、マップを編集する管理者ページを作成します。あらかじめmap_chipが登録されている必要があります。
環境
OS ubuntu22.04
Webサーバ apache2.4.52
(自身のIP 192.168.19.128、公開フォルダ /var/www/html/php/rpg)
PHP 8.1.2-1ubuntu2.14
DB MySQL Ver 8.0.34-ubuntu0.22.04.1
マップ編集画面の作成
まずは次のSQLでマップ用データの保存テーブルを作成します。
create table map (map_no int,x int ,y int ,chip_no int ,mask int ,event text,primary key (map_no, x,y));
次は、下のPHPを作成して
/var/www/html/php/rpg/
に配置し、パーミッションを705にしました。
ファイル名 map_edit.php
<?php
// MySQL接続情報
$servername = "192.168.19.128"; // データベースのホスト名
$username = "********"; // データベースのユーザー名
$password = "********"; // データベースのパスワード
$dbname = "****"; // 使用するデータベース名
$DEF_MAKE = "make";
$DEF_INSERT = "insert";
$DEF_OPEN = "open";
$DEF_UPDATE = "update";
?>
<!DOCTYPE html>
<html>
<body>
<style>
.image_pass {
border: 2px solid blue; /* 赤い枠線を追加 */
display: inline-block; /* インラインブロック要素として表示 */
}
.image_block {
border: 2px solid red; /* 赤い枠線を追加 */
display: inline-block; /* インラインブロック要素として表示 */
}
</style>
<script type="text/javascript">
<!--
function makeForm(param){
if(document.getElementById("x_"+param).value =="" || document.getElementById("y_"+param).value =="") {
alert("XとYの最大値を入力してください");
exit;
}
if(Number.isSafeInteger(document.getElementById("x_"+param).value) || Number.isSafeInteger(document.getElementById("y_"+param).value)) {
alert("XとYは数字で入力して下さい");
exit;
}
if(document.getElementById("x_"+param).value < 5 || document.getElementById("x_"+param).value > 100 || document.getElementById("y_"+param).value < 5 || document.getElementById("y_"+param).value > 100) {
alert("X,Yは5~100の整数で指定してください");
exit;
}
document.getElementById("do").value="<?php echo $DEF_MAKE ?>";
document.getElementById("do_no").value=param;
document.getElementById("x").value=Math.floor(document.getElementById("x_"+param).value);
document.getElementById("y").value=Math.floor(document.getElementById("y_"+param).value);
document.update.submit();
}
function insertForm(){
document.getElementById("do").value="<?php echo $DEF_INSERT ?>";
document.update.submit();
}
function openForm(param){
document.getElementById("do").value="<?php echo $DEF_OPEN ?>";
document.getElementById("do_no").value=param;
document.getElementById("x").value=Math.floor(document.getElementById("x_"+param).value);
document.getElementById("y").value=Math.floor(document.getElementById("y_"+param).value);
document.update.submit();
}
function updateForm(x_max,y_max){
if(document.getElementById("edit_x").value =="" || document.getElementById("edit_y").value =="") {
alert("XとYの値を入力してください");
exit;
}
if(Number.isSafeInteger(document.getElementById("edit_x").value) || Number.isSafeInteger(document.getElementById("edit_y").value)) {
alert("XとYは数字で入力して下さい");
exit;
}
if(document.getElementById("edit_x").value > x_max || document.getElementById("edit_x").value <= 0 || document.getElementById("edit_y").value > y_max || document.getElementById("edit_y").value <= 0) {
alert("Xは"+x_max+"以下、Yは"+y_max+"以下で指定してください");
exit;
}
document.getElementById("do").value="<?php echo $DEF_UPDATE ?>";
document.getElementById("edit_x").value=Math.floor(document.getElementById("edit_x").value);
document.getElementById("edit_y").value=Math.floor(document.getElementById("edit_y").value);
document.update.submit();
}
-->
</script>
<h1>MAP_編集画面</h1>
<?php
$do="";
$do_no="";
$do_x="";
$do_y="";
//db読込
// MySQLサーバーへの接続
$conn = new mysqli($servername, $username, $password, $dbname);
// 接続エラーの確認
if ($conn->connect_error) {
die("Connection failed: " . $conn->connect_error);
}
//
if ($_SERVER['REQUEST_METHOD'] === 'POST'
&& isset($_POST['do'])
&& $_POST['do'] === $DEF_MAKE
&& isset($_POST['do_no'])
&& isset($_POST['x'])
&& isset($_POST['y'])){
//マップ編集画面(新規)
edit_map($conn,$_POST);
} elseif ($_SERVER['REQUEST_METHOD'] === 'POST'
&& isset($_POST['do'])
&& $_POST['do'] === $DEF_INSERT
&& isset($_POST['do_no'])
&& isset($_POST['x'])
&& isset($_POST['y'])){
//DB登録(新規)
create_map_ondb($conn,$_POST);
} elseif ($_SERVER['REQUEST_METHOD'] === 'POST'
&& isset($_POST['do'])
&& $_POST['do'] === $DEF_OPEN
&& isset($_POST['do_no'])
&& isset($_POST['x'])
&& isset($_POST['y'])){
//マップ編集画面(更新)
update_map($conn,$_POST);
} elseif ($_SERVER['REQUEST_METHOD'] === 'POST'
&& isset($_POST['do'])
&& $_POST['do'] === $DEF_UPDATE
&& isset($_POST['do_no'])
&& isset($_POST['sel_update'])
&& isset($_POST['edit_x'])
&& isset($_POST['edit_y'])
&& isset($_POST['x'])
&& isset($_POST['y'])){
//DB登録(更新)
update_map_ondb($conn,$_POST);
//マップ編集画面(更新)
update_map($conn,$_POST);
} else {
//初期表示画面
first_menu($conn);
}
//Footer
echo '<A href="./map_chip.php">マップチップ編集画面へ</a><br>';
echo '<A href="./map_edit.php">reload</a><br>';
$conn->close();
?>
</body>
</html>
<?PHP
//*********************************************************************************************************************
//最初に表示されるページ
//*********************************************************************************************************************
function first_menu($conn){
//既存マップ一覧の読み込み(初期画面)
echo "編集するマップを選んでください。<br>";
echo "新しいマップを作成する場合は、マップのサイズ(5<=X<=100,5<=Y<100)を指定してから「MAKE」ボタンを押してください。<br>";
echo "マップのサイズは後から変更できません。";
$count=0;
$sql = "SELECT map_no,max(x) as x,max(y) as y from map group by map_no ";
$result = $conn->query($sql);
echo '<form action="" name="update" method="post">';
echo '<input type="hidden" name="do" id="do" value="">';
echo '<input type="hidden" name="do_no" id="do_no" value="">';
echo '<input type="hidden" name="x" id="x" value ="">';
echo '<input type="hidden" name="y" id="y" value ="">';
echo "<table border=1><tr><td>map_no</td><td>MAX_X</td><td>MAX_Y</td><td>BUTTON</td></tr>";
if ($result->num_rows > 0) {
while($row = $result->fetch_assoc()) {
$count++;
echo "<tr><td>";
echo "<input type='text' value='" . $row["map_no"] . "' size=3 readonly>";
echo "</td><td>";
echo "<input type='text' id='x_".$row["map_no"]."' name='x_".$row["map_no"]."' value='" . $row["x"] . "' size=3 readonly>";
echo "</td><td>";
echo "<input type='text' id='y_".$row["map_no"]."' name='y_".$row["map_no"]."' value='" . $row["y"] . "' size=3 readonly>";
echo "</td><td>";
echo "<button type='button' onclick='openForm(".$row["map_no"].");' >OPEN</button>";
echo "</td></tr>";
}
}
$count++;
echo "<tr><td>";
echo "<input type='text' value='".$count."' size=3 readonly>";
echo "</td><td>";
echo "<input type='text' id='x_".$count."' name='x_".$count."' value='' size=3 >";
echo "</td><td>";
echo "<input type='text' id='y_".$count."' name='y_".$count."' value='' size=3 >";
echo "</td><td>";
echo "<button type='button' onclick='makeForm(".$count.");' >MAKE</button>";
echo "</td></tr>";
echo "</table></form>";
}
//*********************************************************************************************************************
//マップデータ上にマップチップを配置するページ(新規)
//*********************************************************************************************************************
function edit_map($conn,$PO){
//MAKE
$do = $PO['do'];
$do_no=$PO['do_no'];
$do_x=$PO['x'];
$do_y=$PO['y'];
$count=0;
$sql = "SELECT * from map_chip";
$result = $conn->query($sql);
if ($result->num_rows > 0) {
$chip = array();
while ($row = $result->fetch_assoc()) {
$chip[] = $row;
}
echo '<form action="" name="update" method="post">';
echo "<input type=hidden name='do' id='do' value='' >";
echo "max x<input type=text name='x' id='x' value='".$do_x."' readonly><br>";
echo "max y<input type=text name='y' id='y' value='".$do_y."' readonly><br>";
echo "map no<input type=hidden name='do_no' id='do_no' value='".$do_no."'>$do_no<br>";
for ($y = 1; $y <= $do_y; $y++) {
for($x = 1; $x <= $do_x ; $x++) {
//echo "(".$x.":".$y.")";
echo "<select name='sel_".$x."_".$y."' id='sel_".$x."_".$y."'>";
foreach ($chip as $sel) {
echo "<option value='".$sel["chip_no"]."_0' >〇".$sel["descript"]."</option>";
echo "<option value='".$sel["chip_no"]."_1' >×".$sel["descript"]."</option>";
}
echo "<select>";
}
echo "<br>";
}
echo "<button type='button' onclick='insertForm();' >登録</button>";
echo "</form>";
echo "〇は通過できるチップ、×は通過できないチップ<br>";
} else {
echo "先にマップチップデータを登録して下さい。";
}
}
//*********************************************************************************************************************
//マップデータをDB上に登録する
//*********************************************************************************************************************
function create_map_ondb($conn,$PO){
$do = $PO['do'];
$do_no=$PO['do_no'];
$do_x=$PO['x'];
$do_y=$PO['y'];
$map = array();
for ($y = 1; $y <= $do_y; $y++) {
for ($x = 1; $x <= $do_x; $x++) {
$map[$x][$y] = $PO['sel_'.$x.'_'.$y];
}
}
for ($y = 1; $y <= $do_y; $y++) {
for ($x = 1; $x <= $do_x; $x++) {
list($map_chip, $mask) = explode("_", $map[$x][$y]);
$sql="insert into map(map_no,x,y,chip_no,mask) VALUES(?,?,?,?,?) ON DUPLICATE KEY UPDATE chip_no = VALUES(chip_no), mask = VALUES(mask)";
$stmt = $conn->prepare($sql);
$stmt->bind_param("iiiii", $do_no, $x, $y, $map_chip, $mask);
if ($stmt->execute()) {
//echo "レコードに追加されました(".$x.",".$y.")";
} else {
echo "Error: " . $stmt->error;
}
}
}
}
//*********************************************************************************************************************
//マップデータ上にマップチップを配置するページ(更新)
//*********************************************************************************************************************
function update_map($conn,$PO){
$do = $PO['do'];
$do_no=$PO['do_no'];
$do_x=$PO['x'];
$do_y=$PO['y'];
$sql = "select map_no,map.x as x,map.y as y,map.chip_no as chip_no,mask,event,filename,descript from map,map_chip where map.chip_no = map_chip.chip_no and map.map_no=? order by y,x";
$stmt = $conn->prepare($sql);
$stmt->bind_param("i", $do_no);
$stmt->execute();
$result = $stmt->get_result();
$count=0;
if ($result->num_rows > 0) {
echo "<table border=1><tr>";
echo "<td></td>";
for ($i = 1; $i <= $do_x ;$i++){
echo "<td>".$i."</td>";
}
echo "</tr>";
while($row = $result->fetch_assoc()) {
$count++;
if(($count-1) % $do_x === 0){
echo "<tr><td>".floor($count / $do_x + 1)."</td>";
}
echo "<td>";
echo '<img src='.$row["filename"].' width="20.px" alt="'.$row["descript"].'" ';
if ($row["mask"] === 0 ){
echo 'class="image_pass" ';
} else {
echo 'class="image_block" ';
}
echo 'onclick="mapSelectFunc('.$count.')">';
echo '<input type="hidden" name="mask_'.$count.'" id="mask_'.$count.'" value ="'.$row["mask"].'">';
echo '<input type="hidden" name="chip_'.$count.'" id="chip_'.$count.'" value ="'.$row["chip_no"].'">';
echo '<input type="hidden" name="event_'.$count.'" id="event_'.$count.'" value ="'.$row["event"].'">';
echo '<input type="hidden" name="x_'.$count.'" id="x_'.$count.'" value ="'.$row["x"].'">';
echo '<input type="hidden" name="y_'.$count.'" id="y_'.$count.'" value ="'.$row["y"].'">';
echo "</td>";
if($count % $do_x === 0){
echo "</tr>";
}
}
echo "</table>";
echo "青枠は通過可能、赤枠は通過不可能です。<br>";
echo "地図更新 マップNo".$do_no;
echo '<form action="" name="update" method="post">';
echo 'X座標<input type="text" name="edit_x" id="edit_x" value ="" size=4>';
echo 'Y座標<input type="text" name="edit_y" id="edit_y" value ="" size=4>';
echo '<input type="hidden" name="x" id="x" value ="'.$do_x.'">';
echo '<input type="hidden" name="y" id="y" value ="'.$do_y.'">';
echo '<input type="hidden" name="do" id="do" value="">';
echo '<input type="hidden" name="do_no" id="do_no" value="'.$do_no.'">';
$sql = "SELECT * from map_chip";
$result = $conn->query($sql);
if ($result->num_rows > 0) {
$chip = array();
while ($row = $result->fetch_assoc()) {
$chip[] = $row;
}
echo "<select name='sel_update' id='sel_update'>";
foreach ($chip as $sel) {
echo "<option value='".$sel["chip_no"]."_0' >〇".$sel["descript"]."</option>";
echo "<option value='".$sel["chip_no"]."_1' >×".$sel["descript"]."</option>";
}
echo "<select>";
}
echo "〇は通過できるチップ、×は通過できないチップ<br>";
echo 'イベント<input type="text" name="event" id="event" value ="" size=10>';
echo "<button type='button' onclick='updateForm(". $do_x.",".$do_y .")' >更新</button><br>";
echo "</form>";
?>
<script type="text/javascript">
<!--
function mapSelectFunc(param){
document.getElementById("edit_x").value = document.getElementById("x_"+param).value;
document.getElementById("edit_y").value = document.getElementById("y_"+param).value;
document.getElementById("event").value = document.getElementById("event_"+param).value;
var ss = document.getElementById("chip_"+param).value + "_" + document.getElementById("mask_"+param).value;
var sel = document.getElementById("sel_update").options;
for (i =0 ;i<sel.length;i++){
if(sel[i].value === ss){
sel[i].selected = true;
} else {
sel[i].selected = false;
}
}
}
-->
</script>
<?PHP
} else {
echo "地図データが見つからないか壊れています<br>";
}
}
//*********************************************************************************************************************
//マップデータをDB上で更新する
//*********************************************************************************************************************
function update_map_ondb($conn,$PO){
$do = $PO['do'];
$do_no=$PO['do_no'];
$do_x=$PO['edit_x'];
$do_y=$PO['edit_y'];
$sel_update=$PO['sel_update'];
$event=$PO['event'];
list($map_chip, $mask) = explode("_", $sel_update);
$sql="insert into map(map_no,x,y,chip_no,mask,event) VALUES(?,?,?,?,?,?) ON DUPLICATE KEY UPDATE chip_no = VALUES(chip_no), mask = VALUES(mask) ,event = VALUES(event)";
$stmt = $conn->prepare($sql);
$stmt->bind_param("iiiiis", $do_no, $do_x, $do_y, $map_chip, $mask,$event);
if ($stmt->execute()) {
//echo "レコードに追加されました";
} else {
echo "Error: " . $stmt->error;
}
}
?>
PHPはまだ慣れていないので、おかしなところがあれば教えていただけると助かります。(以前はPerl派だったので、PHPはまだ1か月弱です)
実行すると、次のような画面になります。
map編集画面を実行した様子。
20×20マスのマップを開くとこんな感じです。
後々ですが、海の中の隠し通路とか、アイテムがないと入れない森の中等が作れるといいかと思い、map_chip毎に透過属性(MASK)を持たせるのではなく、マップデータにMASK属性を持たせています。
青枠は通過できるマスで、赤枠は通過できないマスとなっています。
フィールドマップから、他のマップへの移動はイベントを使う予定です。