Jump to content
Korean Random
kharlashkin

[Заказ] Обратная связь или ForceFeedback

Recommended Posts

Я себе представляю так. Выбираем коэффициенты передачи в левый и правый мотор для каждой из 6 зон накидки и производим нормировку в соответствии с этими коэффициентами.

Например можно выбрать такие (в квадратных скобках указаны коэффициенты передачи в левый и правый моторы соответственно)

K_SIT_LEFT       = [0.333, 0.000]
K_SIT_RIGHT      = [0.333, 0.000]
K_BACK_LOW_LEFT  = [0.167, 0.167]
K_BACK_LOW_RIGHT = [0.167, 0.167]
K_BACK_MID_LEFT  = [0.000, 0.333]
K_BACK_MID_RIGHT = [0.000, 0.333] 

И затем, для этих коэффициентов в процессе тестов подобрать наиболее оптимальные значения

 

Да, согласен. Надо будет так же добавить вот это:

K_LEFT = 0xE00 // Левая сторона накидки

K_RIGHT = 0x00E // Правая сторона накидки

K_SIT = 0x202 // Сиденье

K_BACK_LOW = 0x404 // Низ спины

K_BACK_MID = 0x808 // Середина спины

K_ALL_ZONES = 0xE0E // Все зоны 

Но вот ещё момент, разбирая эффекты обнаружил две незадокументированные зоны - zones="C" и zones="C00", которые крутят Спина справа/Спина слева (оба двигателя).

Share this post


Link to post

Short link
Share on other sites

Да я видел. Это комбинации битов. На самом деле все просто: берем число 12 бит - и в нем проверяем наличие/отсутствие 2,3,4 и 10,11,12 битов. Каждый из этих битов отвечает за один из 6 моторчиков накидки.

Share this post


Link to post

Short link
Share on other sites

Ок скрипт для тестов готов нужно проверять

 

Скрипт отрабатывает, выдает "Exit" и всё, наверное надо стопорить скрипт для ожидания ввода команды с клавиатуры.

 

Или надо как-то необычно его запускать?

Выкладываю на тестирование "модифицированный вариант", первоначального скрипта на python, куда добавил разные эффекты при выстреле и повреждения. Распаковать в папку "Х:\Games\World_of_Tanks", путь к системному python прописан как "C:\Python27\python.exe".

 

Код скрипта 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)
    
@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()
                        
    # print 
    # print 'startEffect'
    # print 'handle =', handle
    # print 'count =', count
    
    return ''

if __name__ == "__main__":
    app.debug = True
    app.run()
 

 

P.S. Эффекты надо бы ещё доработать, но играть так стало намного интереснее ;)

res_mods.7z

Edited by kharlashkin

Share this post


Link to post

Short link
Share on other sites

Выкладываю обновленный вариант эффектов. Добавил виброэффекты повреждений (гусля, пожар, контузия и прочее), сделал скрытый режим запуска скриптов.

 

Что пока не работает - нет смешивания эффектов (при пожаре и затем попадании, пожар перестает вибрировать); наблюдаю немного запаздывания (около 0,5 секунды) не всегда, но есть. Но в общем скрипт работает и получается более полное погружение в игровой процесс.

 

Наверное попробую сегодня/завтра скомпилировать файл GPService.py в GPService.pyc, в связи с этим должно немного повыситься быстродействие скрипта. что должно ускорить срабатывание вибраций.

res_mods.7z

Edited by kharlashkin

Share this post


Link to post

Short link
Share on other sites

Привет. В общем вроде допилил многопоточность. Все эффекты берутся из файлов uwv в папке vibroeffects. Коэффициенты передачи для зон настраиваются в xml. Также, не забудь в xml изменить название своей dll XInput. Уровень эффектов должен меняться регуляторами в настройках игры. Проверь задержки. Я контролил fps и ping - изменений не заметил. Но у меня и геймпада ведь нет. Такие огромные задержки - 0,5с - это очень плохо. Если они не исчезнут в этой версии, сообщи, разберемся откуда они..

gpVibroManager.zip

Share this post


Link to post

Short link
Share on other sites

Доброе время суток. Распаковал скрипт в нужную папку, указал путь к системному питону, указал нужную dll (xinput1_3) и сразу промах - при запуске игры не появляется окошко python, соответственно дальше ничего не работает. Пробовал с учетом регистра указать путь - ничего не получилось.

 

Расковырял код, копаюсь...

Share this post


Link to post

Short link
Share on other sites

При запуске в консоли Windows скрипты ругались на несответствие версий python. Переустановил версию на 2.6 - все взлетело :) Буду теперь тестировать и допиливать эффекты.

Share this post


Link to post

Short link
Share on other sites

Прошу прощение за задержку, рождественские праздники, знаете ли...

 

Итак, протестировав обновленный мод, могу сказать, что уважаемый inj3ct0r потрудился на славу:

1. Виброэффекты действительно работают как родные (не зря разрабы хвалились, что эффекты делал звукорежиссер).

2. Мной не замечено никаких абсолютно задержек, все вовремя.

3. Есть смешивание эффектов.

4. Ползунки в настройках игры работают (можно уменьшить/добавить/отключить).

 

Как будет свободное время буду пробовать изменять коэффициенты в xml файле.

 

Огромное спасибо всем, кто участвовал (словом, советом, делом) в написании этого мода!

 

P.S. Разумеется inj3ct0r получил подарок "под ёлочку" (чтобы меня не обвинили в недобросовестности).

Share this post


Link to post

Short link
Share on other sites

Подтверждаю насчет оплаты уважаемый kharlashkin перевел все деньги как и обещал $50 за скрипт и еще $30 на геймпад который я все равно никогда не куплю, за что ему огромное спасибо.

Рад что мы это сделали. Было очень интересно.

Большое спасибо Sirmax за помощь поэтому $30 хочу передать ему - скажи куда.

Share this post


Link to post

Short link
Share on other sites
Большое спасибо Sirmax за помощь поэтому $30 хочу передать ему - скажи куда.

 

Доброй ты души человек ;)

 

Тему закрываю, только в первый пост добавлю решение как и что куда - кому лень читать ветку.

Edited by kharlashkin
  • Upvote 4

Share this post


Link to post

Short link
Share on other sites
Guest
This topic is now closed to further replies.

  • Recently Browsing   0 members

    No registered users viewing this page.

×
×
  • Create New...