簡體   English   中英

在終端中運行php腳本,直到按下某個鍵

[英]Run php script in terminal until a key is pressed

我正在用PHP編寫一個終端游戲,我面臨着真正的困境:如果我按下(特定)密鑰,我怎樣才能使我的腳本自由運行?

我知道我可以使用readline()等來獲取用戶輸入但是如何通過按鍵暫停已經運行的腳本?

您可以嘗試使用PHP 生成器來多任務游戲。 看看這篇文章使用協同程序進行協作式多任務處理(在PHP中!) 還有庫https://github.com/recoilphp/recoil - 一個用於PHP 7的異步協程內核,它可以幫助您編寫異步任務。

作為概念的證明,您可以嘗試這個腳本,這遠非完美。 任務和調度程序的實現取自文章。

//Tested on PHP 7.1.11 and MacOS


class 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();

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM