Главная
Блог разработчиков phpBB
 
+ 17 предустановленных модов
+ SEO-оптимизация форума
+ авторизация через соц. сети
+ защита от спама

Помощь обратной связи геймпадом в WoT

Anna | 15.06.2014 | нет комментариев
Доброе время суток, уважаемое програсообщество!

Скоро будет год, как я играю на геймпаде в World of Tanks, если кто-то пропустил мимо, как я выбирал 1-й в своей жизни ПК для игры умоляю сюда.

Играть геймпадом увлекательно, но разработчики не хотят официально поддерживать его, соответственно доводится различно извращаться для приобретения «некоторого функционала».

Начну с небольшого отступления и опишу подробности игры в WoT на геймпаде от «коробки 360».

Для больше-менее приписываемой игры нужен Xpadder. Видео, как я настраивал

Как играть? Пример рядового боя

Отхождение. Так как я не кудесник, а только учусь, дюже много кода ниже было написано не мною, изложение как и что делалось я писал по собственному пониманию, буду рад любым примечаниям и помощи.

Сейчас к основному.
Каждому вестимо, что во многих играх применяется так называемая обратная связь с геймпадом либо ForceFeedback, которая дает больше большое погружение в игровой процесс за счет вибраций (едешь по кочкам — есть вибрация, получаешь удар от противника — есть вибрация и т.п.). Разумеется, что меня заинтересовала вероятность получить виброотдачу на геймпаде в «танчиках».
Покопав данную тему обнаружил следующие моменты, дозволяющие это сделать:
1. Всё что необходимо пишется на python, именно данный язык применяется в игре для выполнения каждого и каждая (думаю, что помимо ядра BigWorld).
2. На stackoverflow, обнаружил необходимый мне код, дозволяющий передавать вибрации в геймпад.
3. Wargaming теснее встроил в свою игру вибрации для виброжопки вибронакидки GameTrix, сам план вибронакидки является открытым и каждый SDK и другое доступно для постижения и скачивания.
4. Поиск по папкам игры выдал местонахождение скриптов «World_of_Tanks\res\scripts\client\vibroeffect».

Разобрав «по полочкам» SDK вибронакидки, скрипты игры — выходит, что с поддержкой XVM (eXtended Visualization Mod for World of Tanks), дозволено испробовать подменить 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

В файле GPsettings.xml прописан спрятанный запуск системного python из папки по умолчанию «C:\Python27».

В реальное время я тестирую скрипт для забора результатов напрямую из файлов для вибронакидки со смешиванием результатов.

Везения каждому в боях!

Источник: programmingmaster.ru
Оставить комментарий
Форум phpBB, русская поддержка форума phpBB
Рейтинг@Mail.ru 2008 - 2017 © BB3x.ru - русская поддержка форума phpBB