Запускать скрипт php в терминале до нажатия клавиши

В настоящее время я пишу терминальную игру на php, и я столкнулся с реальной борьбой: как я могу заставить мой скрипт свободно работать, пока я не нажму (определенную) клавишу?

Я знаю, что могу принять пользовательский ввод с readline() и т.д., но как я могу приостановить уже запущенный скрипт нажатием клавиши?

3

Решение

Вы можете попробовать использовать PHP генераторы Многозадачность вашей игры.
Посмотрите на эту статью Совместная многозадачность с использованием сопрограмм (в PHP!). Также есть библиотека https://github.com/recoilphp/recoil — асинхронное ядро ​​сопрограммы для PHP 7, которое может помочь вам написать асинхронные задачи.

В качестве доказательства концепции вы можете попробовать этот скрипт, который далек от совершенства. Реализация задачи и планировщика взята из статьи.

//Tested on PHP 7.1.11 and MacOSclass Task {
protected $taskId;
protected $coroutine;
protected $sendValue = null;
protected $beforeFirstYield = true;

public function __construct($taskId, Generator $coroutine) {
$this->taskId = $taskId;
$this->coroutine = $coroutine;
}

public function getTaskId() {
return $this->taskId;
}

public function setSendValue($sendValue) {
$this->sendValue = $sendValue;
}

public function run() {
if ($this->beforeFirstYield) {
$this->beforeFirstYield = false;
return $this->coroutine->current();
} else {
$retval = $this->coroutine->send($this->sendValue);
$this->sendValue = null;
return $retval;
}
}

public function isFinished() {
return !$this->coroutine->valid();
}
}class Scheduler {
protected $maxTaskId = 0;
protected $taskMap = []; // taskId => task
protected $taskQueue;

public function __construct() {
$this->taskQueue = new SplQueue();
}

public function newTask(Generator $coroutine) {
$tid = ++$this->maxTaskId;
$task = new Task($tid, $coroutine);
$this->taskMap[$tid] = $task;
$this->schedule($task);
return $tid;
}

public function schedule(Task $task) {
$this->taskQueue->enqueue($task);
}

public function run() {
while (!$this->taskQueue->isEmpty()) {
$task = $this->taskQueue->dequeue();
$task->run();

if ($task->isFinished()) {
unset($this->taskMap[$task->getTaskId()]);
} else {
$this->schedule($task);
}
}
}
}function game($state) {
while (true) {

if($state->isTheGamePaused === true) {
echo "The game is paused\n";
} else {
echo "Game is running\n";
}
yield;
}
}

function pauseKeyListener($state) {
readline_callback_handler_install('', function() { });
while (true) {
$r = [STDIN];
$w = NULL;
$e = NULL;
$n = stream_select($r, $w, $e, null);
if ($n && in_array(STDIN, $r)) {
$pressedChar = stream_get_contents(STDIN, 1);

// Pause the game if the 'p' is pressed
if($pressedChar === 'p') {
$state->isTheGamePaused = true;
//Resume the game if the 'r' is pressed
} elseif ($pressedChar === 'r') {
$state->isTheGamePaused = false;
}

echo "Char read: $pressedChar\n";
}
yield;
}
}

$state = new stdClass();
$state->isTheGamePaused = false;

$scheduler = new Scheduler;

$scheduler->newTask(game($state));
$scheduler->newTask(pauseKeyListener($state));

$scheduler->run();
1

Другие решения

Других решений пока нет …

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector