用Swoole來寫個聯機對戰遊戲呀!(三)完善遊戲功能
遊戲邏輯開發進度:■■■■□□□□□□□□
本章結束開發進度:■■■■■■■■□□□□
上一章的答案
createPlayer
方法其實就是建立一個 Player
物件,然後指定座標,放入 $players
陣列中,但是怎麼區分 追捕者
和 躲藏者
呢?我們可以用最簡單粗暴的方法,先來後到。
Game類:
public function createPlayer($playerId, $x, $y) { $player = new Player($playerId, $x, $y); if (!empty($this->players)) { $player->setType(Player::PLAYER_TYPE_HIDE); } $this->players[$playerId] = $player; }
第一個新增的將會使用 Player
類預設的 追捕者
,第二個新增的將 $player
物件設定為 躲藏者
。
playerMove()
方法也很簡單,通過傳入的 $direction
變數,增減對應 $player
的 x
或 y
座標,應該直接呼叫 $player
的移動方法,所以需要新增兩部分程式碼:
Game類:
public function playerMove($playerId, $direction) { $this->players[$playerId]->{$direction}(); }
Player類:
public function up() { $this->x--; } public function down() { $this->x++; } public function left() { $this->y--; } public function right() { $this->y++; }
嘗試列印地圖
目前我們三個實體類的基礎遊戲邏輯就寫得差不多了,但是我們的遊戲到現在都還沒執行過,我們需要一個能直觀看到地圖、玩家的畫面。
請童鞋們自己嘗試在 Game
類中新增 printGameMap()
方法,列印遊戲地圖。
- 在
Game
類中有一個變數$gameMap
就是我們的遊戲地圖物件。 -
Map
類中也有了getMapData()
方法能夠獲取地圖陣列資料,
Game類:
public function printGameMap() { $mapData = $this->gameMap->getMapData(); foreach ($mapData as $line) { foreach ($line as $value) { if (empty($value)) { echo "牆,"; } else { echo ""; } } echo PHP_EOL; } }
列印地圖的程式碼很簡單,就是遍歷我們的地圖資料,當數組裡的元素值為 0
的時候就是 牆
,否則就是 路
, 路
就不用輸出文字啦~
回到我們的 test.php
,我們將在這裡呼叫新寫的 printGameMap()
方法輸出地圖資料。由於我們要使用了 composer
的自動載入機制,所以要先在 test.php
檔案的開頭加上以下程式碼:
require_once __DIR__ . '/vendor/autoload.php';
引入 autoload.php
檔案後,我們就能愉快的使用名稱空間了,童鞋們記得要引入 Game
類哦。
test.php:
<?php require_once __DIR__ . '/vendor/autoload.php'; use App\Manager\Game; $redId = "red_player"; $blueId = "blue_player"; //建立遊戲控制器 $game = new Game(); //新增玩家 $game->createPlayer($redId, 6, 1); //新增玩家 $game->createPlayer($blueId, 6, 10); //移動座標 $game->playerMove($redId, 'up'); //列印地圖 $game->printGameMap();
在控制檯輸入以下程式碼,執行 test.php
檔案:
php test.php
如果童鞋們的程式碼沒問題的話,控制檯應該會輸出以下內容:
牆,牆,牆,牆,牆,牆,牆,牆,牆,牆,牆,牆, 牆,牆, 牆,牆,牆,牆, 牆,牆,牆,牆,牆,牆,牆,牆, 牆,牆,牆, 牆,牆,牆,牆,牆, 牆,牆,牆, 牆,牆,牆,牆,牆, 牆,牆,牆,牆,牆, 牆,牆,牆,牆,牆,牆, 牆,牆, 牆,牆,牆,牆,牆,牆,牆,牆,牆,牆,牆,牆,
加入玩家座標
光輸出地圖的資料可是不夠的,我們還要把玩家的座標加在地圖裡面,請童鞋們優化 printGameMap()
方法,使他能夠輸出兩個玩家的位置。
-
Game
類中的變數$players
儲存了兩個Player
物件。 -
Player
類中的變數$x
和$y
儲存了玩家的座標,$type
儲存了該物件的型別,但是好像是私有變數?如何獲取類中的私有變數呢?
Player類:
public function getType() { return $this->type; } public function getX() { return $this->x; } public function getY() { return $this->y; }
我們首先需要在 Player
類中新增一個方法 getType()
獲取物件的型別, getX()
、 getY()
獲取玩家的座標資料。
在列印地圖資料之前,將玩家的地圖座標,以及型別標識放進 $mapData
中,但由於我們的地圖裡 1
是路,玩家型別中 1
是 追捕者
,直接放進去就會搞混了玩家和路的值,所以我們要在玩家型別的值上進行 +1
操作再放進地圖,並且增加一個文字對映陣列。
-
test.php
中createPlayer()
傳入的座標資料小心不要和地圖上的牆
重疊了哦
Game類:
public function printGameMap() { $mapData = $this->gameMap->getMapData(); $font = [2 => '追', 3 => '躲']; /* @var Player $player */ foreach ($this->players as $player) { $mapData[$player->getX()][$player->getY()] = $player->getType() + 1; } foreach ($mapData as $line) { foreach ($line as $item) { if (empty($item)) { echo "牆,"; } elseif ($item == 1) { echo ""; } else { echo $font[$item] . ','; } } echo PHP_EOL; } }
重新執行一次我們的 test.php
檔案,應該就會輸出以下內容:
牆,牆,牆,牆,牆,牆,牆,牆,牆,牆,牆,牆, 牆,牆, 牆,牆,牆,牆, 牆,牆,牆,牆,牆,牆,牆,牆, 牆,牆,牆, 牆,追,牆,牆,牆,牆, 牆,牆,躲,牆, 牆,牆,牆,牆,牆, 牆,牆,牆,牆,牆, 牆,牆,牆,牆,牆,牆, 牆,牆, 牆,牆,牆,牆,牆,牆,牆,牆,牆,牆,牆,牆,
追捕者
和 躲藏者
就顯示出來啦,並且由於我們列印地圖前呼叫 playerMove()
方法移動 追捕者
並傳入了 up
, 追捕者
的座標在地圖上往上走了一步。
增加地圖判斷
我們嘗試把 追捕者
再往上走兩步試試,在 test.php
檔案中再呼叫兩次 playerMove()
方法並列印地圖,執行 test.php
檔案:
牆,牆,牆,牆,牆,牆,牆,牆,牆,牆,牆,牆, 牆,牆, 牆,牆,牆,牆, 牆,追,牆,牆,牆,牆,牆,牆, 牆,牆,牆, 牆,牆,牆,牆,牆, 牆,牆,躲,牆, 牆,牆,牆,牆,牆, 牆,牆,牆,牆,牆, 牆,牆,牆,牆,牆,牆, 牆,牆, 牆,牆,牆,牆,牆,牆,牆,牆,牆,牆,牆,牆,
哦嚯,我們的 追捕者
走到 牆
上面了,這誰頂得住啊。目前的 playerMove()
方法是不完整的,需要在其中再加入一個方法 canMoveToDirection()
去判斷傳入的方向是否可以移動。
Player $direction Game
Game類:
public function playerMove($playerId, $direction) { $player = $this->players[$playerId]; if ($this->canMoveToDirection($player, $direction)) { $player->{$direction}(); } } private function canMoveToDirection($player, $direction) { }
本章的Homework就在這裡啦,請童鞋們一定要儘量獨立完成哦,我們將在下一章進行解答。
當前目錄結構:
HideAndSeek ├── app │├── Manager ││└── Game.php │└── Model │├── Map.php │└── Player.php ├── composer.json ├── test.php └── vendor ├── autoload.php └── composer