乐趣区

用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 变量,增减对应 $playerxy 坐标,应该直接调用 $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() 方法,打印游戏地图。

  1. Game 类中有一个变量 $gameMap 就是我们的游戏地图对象。
  2. 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() 方法,使他能够输出两个玩家的位置。

  1. Game类中的变量 $players 保存了两个 Player 对象。
  2. 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.phpcreatePlayer() 传入的坐标数据小心不要和地图上的 重叠了哦

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() 去判断传入的方向是否可以移动。

  1. 每个 Player 对象可以获取当前坐标。
  2. 根据传入的 $direction 方向计算出目标坐标。
  3. 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

退出移动版