WoTのゲームパッドフィードバックサポート

良い一日、親愛なるhabrasociety!



すぐにWorld of Tanksでゲームパッドをプレイしてから1年が経ちますが、誰かが見逃した場合は、ゲームで私の人生で最初のPCをどのように選んだか、 ここで尋ねます



ゲームパッドで遊ぶのはおもしろいですが、開発者は公式にサポートしたくないので、「何らかの機能」を手に入れるにはあらゆる方法で倒錯しなければなりません。







ちょっとした余談から始めて、「box 360」からゲームパッドのWoTでゲームの詳細を説明します。



多かれ少なかれ健全なゲームにはXpadderが必要です 。 設定したビデオ





遊び方 普通の戦いの例





リトリート。 私は魔術師でないが、学習しているだけなので、以下のコードの多くは私が書いたものではなく、自分の理解によってどのように何をしたかについての記述は私が書いたものなので、どんなコメントや助けでも喜んでいます。



さて、主なことです。

多くのゲームは、ゲームパッドまたはForceFeedbackからのいわゆるフィードバックを使用することを知っています。これにより、振動によりゲームプロセスに深く没頭できます(バンプを超える-振動がある、相手から打撃を受ける-振動があるなど)。 もちろん、私は「タンク」でゲームパッドの振動フィードバックを得る機会に興味がありました。

このトピックを掘り下げた後、これを可能にする次のポイントを見つけました。

1.必要なものはすべてpythonで書かれています。ゲームですべてを実行するために使用されるのはこの言語です(BigWorldコア以外はそう思います)。

2. stackoverflowで 、振動をゲームパッドに転送するために必要なコードを見つけました。

3. Wargamingは既にGameTrix振動スコープの振動掘削のためにゲームの振動に統合されており、 振動カプセルプロジェクト自体は開かれており、SDK全体およびその他のものは研究とダウンロードに利用できます。

4.ゲームフォルダーを検索すると、スクリプトの場所「World_of_Tanks \ res \ scripts \ client \ vibroeffect」が返されました。



ゲームのスクリプトである「棚上の」バイブロスクリーンSDKを分解すると、 XVM (World of Tanksの拡張視覚化Mod)の助けを借りて、BigWorld.WGVibrationをGamePadVibrationに直接置き換えて、ゲームパッドで必要な振動メソッドを直接呼び出すことができます。

しかし、ゲームpythonには本格的なctypesがないため、通常のpythonで「振動する」スクリプトを実行し、ゲームからコマンドを取得できるサービスを作成する必要がありました。 このようなサービスはFlaskを使用して作成されました。 以下は、ショット中に振動をゲームパッドに伝達し、ヒット/リコケットを獲得し、戦車にダメージを与える実行可能スクリプトのコードです。 振動効果は、振動スケールの元のものから私によって書かれました。

GPService.py
ENABLE_LOG = False d = dict() from flask import Flask from flask import request import ctypes # Define necessary structures class XINPUT_VIBRATION(ctypes.Structure): _fields_ = [("wLeftMotorSpeed", ctypes.c_ushort), ("wRightMotorSpeed", ctypes.c_ushort)] xinput = ctypes.windll.xinput1_3 # Load Xinput.dll # Set up function argument types and return type XInputSetState = xinput.XInputSetState XInputSetState.argtypes = [ctypes.c_uint, ctypes.POINTER(XINPUT_VIBRATION)] XInputSetState.restype = ctypes.c_uint # You can also create a helper function like this: def set_vibration(controller, left_motor, right_motor): vibration = XINPUT_VIBRATION(int(left_motor * 65535), int(right_motor * 65535)) XInputSetState(controller, ctypes.byref(vibration)) if not ENABLE_LOG: import logging log = logging.getLogger('werkzeug') log.setLevel(logging.ERROR) app = Flask(__name__) @app.route('/connect') def connect(): print 'Connection checked - Ok.' return 'True' @app.route('/loadEffectFromFile') def loadEffectFromFile(): effectHandle = request.args.get('effectHandle') fileName = request.args.get('fileName') #print #print 'loadEffectFromFile' #print 'effectHandle =', request.args.get('effectHandle') #print 'fileName =', request.args.get('fileName') if not effectHandle in d: d[effectHandle] = fileName return '' @app.route('/getEffectLength') def getEffectLength(): #print #print 'getEffectLength' #print 'effectHandle =', request.args.get('effectHandle') #print 'returnedLength =', request.args.get('returnedLength') return '' import threading, time def shot_main(): set_vibration(0, 1.0, 1.0) time.sleep(0.15) set_vibration(0, 0, 0) time.sleep(0.25) set_vibration(0, 0.5, 0) time.sleep(0.25) set_vibration(0, 0.0, 0.0) def shot_large(): set_vibration(0, 0.5, 0.6) time.sleep(0.1) set_vibration(0, 0.3, 0) time.sleep(0.1) set_vibration(0, 0.1, 0) time.sleep(0.1) set_vibration(0, 0, 0) time.sleep(0.1) set_vibration(0, 0, 0.5) time.sleep(0.1) set_vibration(0, 0.0, 0.0) def shot_medium(): set_vibration(0, 0, 0) time.sleep(0.1) set_vibration(0, 0.6, 0.6) time.sleep(0.1) set_vibration(0, 0.4, 0) time.sleep(0.1) set_vibration(0, 0.2, 0) time.sleep(0.1) set_vibration(0, 0, 0.6) time.sleep(0.2) set_vibration(0, 0.0, 0.0) def shot_small(): set_vibration(0, 0.6, 0.8) time.sleep(0.1) set_vibration(0, 0, 0.4) time.sleep(0.1) set_vibration(0, 0.0, 0.0) def hit_nonpenetration(): set_vibration(0, 0.5, 0.5) time.sleep(0.1) set_vibration(0, 0.0, 0.0) def hit_ricochet(): set_vibration(0, 0.8, 0.8) time.sleep(0.1) set_vibration(0, 0, 0) time.sleep(0.2) set_vibration(0, 0.0, 0.5) time.sleep(0.05) set_vibration(0, 0, 0) def hit_splash(): set_vibration(0, 0.8, 0) time.sleep(0.1) set_vibration(0, 0.4, 0.8) time.sleep(0.1) set_vibration(0, 0, 0.4) time.sleep(0.1) set_vibration(0, 0, 0) time.sleep(0.05) set_vibration(0, 0, 0.4) time.sleep(0.15) set_vibration(0, 0, 0) def hit(): set_vibration(0, 1, 0) time.sleep(0.1) set_vibration(0, 0, 0) time.sleep(0.05) set_vibration(0, 0, 1) time.sleep(0.1) set_vibration(0, 0, 0) time.sleep(0.05) set_vibration(0, 0.6, 0.6) time.sleep(0.1) set_vibration(0, 0.5, 0.5) time.sleep(0.05) set_vibration(0, 0.25, 0.25) time.sleep(0.05) set_vibration(0, 0, 0) def crit_contusion(): set_vibration(0, 1, 0) time.sleep(0.1) set_vibration(0, 0, 0) time.sleep(0.2) set_vibration(0, 0, 0.4) time.sleep(0.2) set_vibration(0, 0, 0) time.sleep(0.3) set_vibration(0, 0, 0.3) time.sleep(0.2) set_vibration(0, 0, 0) time.sleep(0.5) set_vibration(0, 0, 0.25) time.sleep(0.2) set_vibration(0, 0, 0) def crit_death(): set_vibration(0, 1, 1) time.sleep(0.1) set_vibration(0, 0.5, 0) time.sleep(0.1) set_vibration(0, 0, 1) time.sleep(0.1) set_vibration(0, 0, 0) time.sleep(0.1) set_vibration(0, 0, 0.8) time.sleep(0.1) set_vibration(0, 0.8, 0) time.sleep(0.1) set_vibration(0, 0, 0.8) time.sleep(0.1) set_vibration(0, 0, 0) time.sleep(0.1) set_vibration(0, 0.5, 0.5) time.sleep(0.1) set_vibration(0, 0.4, 0.3) time.sleep(0.1) set_vibration(0, 0.3, 0.1) time.sleep(0.1) set_vibration(0, 0.2, 0) time.sleep(0.1) set_vibration(0, 0.1, 0) time.sleep(0.1) set_vibration(0, 0, 0) def crit_engine(): set_vibration(0, 1, 0) time.sleep(0.1) set_vibration(0, 0, 0) time.sleep(0.1) set_vibration(0, 0.4, 0) time.sleep(0.1) set_vibration(0, 0.4, 0.6) time.sleep(0.3) set_vibration(0, 0, 0) time.sleep(0.1) set_vibration(0, 0, 0.6) time.sleep(0.1) set_vibration(0, 0, 0) time.sleep(0.1) set_vibration(0, 0.4, 0.6) time.sleep(0.1) set_vibration(0, 0.4, 0) time.sleep(0.1) set_vibration(0, 0.4, 0.6) time.sleep(0.1) set_vibration(0, 0, 0) time.sleep(0.1) set_vibration(0, 0, 0.6) time.sleep(0.1) set_vibration(0, 0, 0) time.sleep(0.1) set_vibration(0, 0.4, 0.6) time.sleep(0.1) set_vibration(0, 0.4, 0) time.sleep(0.2) set_vibration(0, 0, 0) def crit_fire(): set_vibration(0, 0.5, 0) time.sleep(0.1) set_vibration(0, 0, 0.3) time.sleep(0.1) set_vibration(0, 0, 0) time.sleep(0.5) set_vibration(0, 0.5, 0) time.sleep(0.1) set_vibration(0, 0, 0.3) time.sleep(0.1) set_vibration(0, 0, 0) time.sleep(0.5) set_vibration(0, 0.5, 0) time.sleep(0.1) set_vibration(0, 0, 0.3) time.sleep(0.1) set_vibration(0, 0, 0) time.sleep(0.5) set_vibration(0, 0.5, 0) time.sleep(0.1) set_vibration(0, 0, 0.3) time.sleep(0.1) set_vibration(0, 0, 0) time.sleep(0.5) set_vibration(0, 0.5, 0) time.sleep(0.1) set_vibration(0, 0, 0.3) time.sleep(0.1) set_vibration(0, 0, 0) time.sleep(0.5) set_vibration(0, 0.5, 0) time.sleep(0.1) set_vibration(0, 0, 0.3) time.sleep(0.1) set_vibration(0, 0, 0) time.sleep(0.5) set_vibration(0, 0.5, 0) time.sleep(0.1) set_vibration(0, 0, 0.3) time.sleep(0.1) set_vibration(0, 0, 0) time.sleep(0.5) set_vibration(0, 0.5, 0) time.sleep(0.1) set_vibration(0, 0, 0.3) time.sleep(0.1) set_vibration(0, 0, 0) time.sleep(0.5) set_vibration(0, 0.5, 0) time.sleep(0.1) set_vibration(0, 0, 0.3) time.sleep(0.1) set_vibration(0, 0, 0) time.sleep(0.5) set_vibration(0, 0.5, 0) time.sleep(0.1) set_vibration(0, 0, 0.3) time.sleep(0.1) set_vibration(0, 0, 0) time.sleep(0.5) set_vibration(0, 0.5, 0) time.sleep(0.1) set_vibration(0, 0, 0.3) time.sleep(0.1) set_vibration(0, 0, 0) time.sleep(0.5) set_vibration(0, 0.5, 0.5) time.sleep(2) set_vibration(0, 0, 0) def crit_run(): set_vibration(0, 1, 0) time.sleep(0.1) set_vibration(0, 0, 0) time.sleep(0.2) set_vibration(0, 0, 0.8) time.sleep(0.3) set_vibration(0, 0, 0) time.sleep(0.1) set_vibration(0, 0, 0.5) time.sleep(0.3) set_vibration(0, 0, 0) time.sleep(0.1) set_vibration(0, 0.8, 0) time.sleep(0.1) set_vibration(0, 0.6, 0) time.sleep(0.1) set_vibration(0, 0.4, 0) time.sleep(0.1) set_vibration(0, 0.2, 0) time.sleep(0.1) set_vibration(0, 0, 0) time.sleep(0.1) set_vibration(0, 0.4, 0) time.sleep(0.1) set_vibration(0, 0.2, 0) time.sleep(0.1) set_vibration(0, 0.1, 0) time.sleep(0.1) set_vibration(0, 0, 0) def crit_track_move(): set_vibration(0, 0.6, 0.2) time.sleep(0.1) set_vibration(0, 0, 0.1) time.sleep(0.1) set_vibration(0, 0, 0) time.sleep(0.4) set_vibration(0, 0, 0.1) time.sleep(0.1) set_vibration(0, 0, 0.05) time.sleep(0.1) set_vibration(0, 0, 0) time.sleep(0.1) set_vibration(0, 0, 0.1) time.sleep(0.1) set_vibration(0, 0, 0.05) time.sleep(0.1) set_vibration(0, 0, 0) def crit_track(): set_vibration(0, 0.8, 0) time.sleep(0.05) set_vibration(0, 0, 0) time.sleep(0.1) set_vibration(0, 0, 0.8) time.sleep(0.05) set_vibration(0, 0, 0) time.sleep(0.1) set_vibration(0, 0.5, 0.5) time.sleep(0.05) set_vibration(0, 0, 0) time.sleep(0.1) set_vibration(0, 0.5, 0.5) time.sleep(0.05) set_vibration(0, 0, 0) @app.route('/startEffect') def startEffect(): handle = request.args.get('handle') count = request.args.get('count') if handle in d: print 'startEffect: '+ d[handle] if 'shot_main' in d[handle]: print 'shot_main' # init thread t1 = threading.Thread(target=shot_main) # start threads t1.start() if 'shot_large' in d[handle]: print 'shot_large' # init thread t1 = threading.Thread(target=shot_large) # start threads t1.start() if 'shot_medium' in d[handle]: print 'shot_medium' # init thread t1 = threading.Thread(target=shot_medium) # start threads t1.start() if 'shot_small' in d[handle]: print 'shot_small' # init thread t1 = threading.Thread(target=shot_small) # start threads t1.start() if 'hit_nonpenetration' in d[handle]: print 'hit_nonpenetration' # init thread t1 = threading.Thread(target=hit_nonpenetration) # start threads t1.start() if 'hit_ricochet' in d[handle]: print 'hit_ricochet' # init thread t1 = threading.Thread(target=hit_ricochet) # start threads t1.start() if 'hit_splash' in d[handle]: print 'hit_splash' # init thread t1 = threading.Thread(target=hit_splash) # start threads t1.start() if 'hit' in d[handle]: print 'hit' # init thread t1 = threading.Thread(target=hit) # start threads t1.start() if 'crit_contusion' in d[handle]: print 'crit_contusion' # init thread t1 = threading.Thread(target=crit_contusion) # start threads t1.start() if 'crit_death' in d[handle]: print 'crit_death' # init thread t1 = threading.Thread(target=crit_death) # start threads t1.start() if 'crit_engine' in d[handle]: print 'crit_engine' # init thread t1 = threading.Thread(target=crit_engine) # start threads t1.start() if 'crit_fire' in d[handle]: print 'crit_fire' # init thread t1 = threading.Thread(target=crit_fire) # start threads t1.start() if 'crit_run' in d[handle]: print 'crit_run' # init thread t1 = threading.Thread(target=crit_run) # start threads t1.start() if 'crit_track_move' in d[handle]: print 'crit_track_move' # init thread t1 = threading.Thread(target=crit_track_move) # start threads t1.start() if 'crit_track' in d[handle]: print 'crit_track' # init thread t1 = threading.Thread(target=crit_track) # start threads t1.start() # print # print 'startEffect' # print 'handle =', handle # print 'count =', count return '' if __name__ == "__main__": app.debug = True app.run()
      
      









コントローラーの振動についても:

1. Python(最新バージョン )をインストールする必要があります。デフォルトのフォルダーを「C:\ Python27」にします。



2. Flaskをインストールする必要があります 。この指示に従って行いましたdistribute_setup.pyファイルをフォルダー「C:\ temp」(たとえば)にダウンロードし、コンソール「Win + R」-cmdを実行し、コマンド「C:\ Python27 \ python.exe C:\ temp \ distribute_setup.py」を実行し、読み込みプロセスを観察します「C:\ Python27 \ Scripts」フォルダに必要なファイルを追加し、コンソールでコマンドを順番に起動して実行を観察します。

C:\ Python27 \ python.exe C:\ Python27 \ Scripts \ easy_install-2.7-script.py Flask

C:\ Python27 \ python.exe C:\ Python27 \ Scripts \ easy_install-2.7-script.py Jinja2

C:\ Python27 \ python.exe C:\ Python27 \ Scripts \ easy_install-2.7-script.py Werkzeug

C:\ Python27 \ python.exe C:\ Python27 \ Scripts \ easy_install-2.7-script.py Virtualenv



デフォルトのフォルダー「C:\ Python27」からのシステムpythonの非表示の開始は、GPsettings.xmlファイルで指定されています。



現在、ミキシングエフェクトを含む振動スケールファイルから直接エフェクトを選択するスクリプトをテストしています。



戦いのすべての人に幸運を!



PS habrasocietyの関心が低いことに関連して、誰もが公式WoTフォーラムに興味を持っています。



All Articles