4

Python 3を使用してターンベースのゲームを作成します.2人のキャラクター(敵と敵)が攻撃し、ランダム+速度に基づいて一時停止し、生きている場合は再度攻撃します。

私が直面している問題は、 time.sleep がどちらか一方ではなく両方のモジュールをフリーズすることです。これを効果的に機能させるための提案はありますか?

from multiprocessing import Process
import time
import random

def timing1():  
    speed=60#SPEED IS NORMALLY A KEY FROM LIST, USING 60 FOR EXAMPLE  
    sleeptime=36/((random.randint(1,20)+speed)/5)  
    print (sleeptime)  
    time.sleep(sleeptime)  
    input('HERO ACTION')  

def timing2():  
    speed=45  
    sleeptime=36/((random.randint(1,20)+speed)/5)  
    print (sleeptime)  
    time.sleep(sleeptime)  
    input('FOE ACTION')  

if __name__ == '__main__':  
    p1=Process(target=timing1)  
    p1.start()  
    p2=Process(target=timing2)  
    p2.start()  
    p1.join()  
    p2.join()
4

2 に答える 2

0

JFについて詳しく説明する

スレッド化に関する私の一般的なアドバイスは、絶対に必要な場合にのみ導入することです。

  • 文字通り低レベルの I/O をブロックしており、ネイティブ スレッドを使用する以外に方法はありません。
  • あなたは計算の限界に達しており、より多くのコアを利用する必要があります。その場合、Python はGILであるため、とにかくあなたに不利に働く可能性があります。

別の方法として、イベントのスケジューリングにネイティブ スレッドに依存しない、twistedgeventなどのスケジューラを提供するライブラリを利用します。

イベント

スレッド モデルを念頭に置いた方法でゲームを作成できますが、スレッド間のリソース競合について心配する必要はありません。あなたの例では、 sleepのようなさまざまな関数の gevent バージョンを使用することに注意する必要があります。

import random
import gevent


def hero():
    speed = 60
    sleeptime = 36 / ((random.randint(1, 20) + speed) / 5)
    print (sleeptime)
    gevent.sleep(sleeptime)
    input('HERO ACTION')


def foe():
    speed = 45
    sleeptime = 36 / ((random.randint(1, 20) + speed) / 5)
    print (sleeptime)
    gevent.sleep(sleeptime)
    input('FOE ACTION')


if __name__ == "__main__":
    heroThread = gevent.Greenlet(hero)
    foeThread = gevent.Greenlet(foe)

    heroThread.start()
    foeThread.start()

    gevent.joinall([heroThread, foeThread])

ねじれた

純粋な python で記述されたイベント リアクターを提供し、単一のスレッド化されたイベント リアクター (イベント ループとも呼ばれます) にすぎないふりをしません。これには、例をより大きく書き直す必要があります。

import random
from twisted.internet import reactor


def heroAction():
    input('HERO ACTION')


def heroStart():
    speed = 60
    sleeptime = 36 / ((random.randint(1, 20) + speed) / 5)
    print (sleeptime)
    reactor.callLater(sleeptime, heroAction)


def foeAction():
    input('FOE ACTION')


def foeStart():
    speed = 45
    sleeptime = 36 / ((random.randint(1, 20) + speed) / 5)
    print (sleeptime)
    reactor.callLater(sleeptime, foeAction)


if __name__ == "__main__":
    # Call when the reactor has started.
    reactor.callWhenRunning(heroStart)
    reactor.callWhenRunning(foeStart)
    reactor.run()

ツイスト リアクターは、何もすることがなくなったときにシャットダウンしないことに注意してください。これは、明示的にプログラマーに任されています。

ローリング・ユア・オウン

学習目的で独自のスケジューラーを作成することは興味深いことかもしれませんし、それを必要とする公平性などの要件がゲームにあるかもしれません。良い出発点は、インスピレーションを得るために別の最小限のスケジューラーを調べることです。

于 2012-11-17T14:25:01.163 に答える
0

1 回のターンの後、プロセスはコードで終了します。メインプロセスは、両方のプロセスを呼び出して終了するのを待ちます。.join()つまり、time.sleep()他のプロセスをフリーズしません。

while True:関数の先頭に追加して、timing*()複数の移動を行います。

ここでは、複数のプロセスは必要ありません。スレッドまたは単一のスレッドを使用してターンを実装できます。

于 2012-11-07T09:32:06.347 に答える