Яндекс.Метрика

    Ни о чём

    Перебираем двигатель через выхлопную трубу, или как получить нормальное клавиатурное управление в FIFA 12

    Как это случилось


    In the long hidden past
    Was the world just like ours
    Once beautiful, but every flower dies...

    — All Mankind, «Break the spell»

    Завязка истории тривиальна. Давным-давно, в далёкой-далёкой галактике была отличная игра под названием «Fifa». Она бы таковой и оставалась, если бы св нехорошие люди из ЕА в 2010м году не возжелали окончательно убить клавиатурное управление во имя геймпадов.
    Я же решил нести возмездие во имя луны вернуть нормальное клавиатурное управление обратно. Хроники борьбы бобра с ослом можно посмотреть под катом.

    Как было раньше


    До знакового 2010го года фифа обладала вполне сносным клавиатурным управлением. Наибольшее преимущество геймпада (по крайней мере, на мой взгляд) заключалось в существенно большей доступности особых, уличных приёмов работы с мячом (для них применялся right analog stick). В клавиатурной версии оба стика (и движение, и финты) были привязаны к обычным стрелочкам, и нажатие левого шифта позволяло исполнять хитрые трюки. На самом деле, это вполне сносное решение, с которым вполне можно играть: одними стрелочками я могу управлять бегущим человеком и, когда нужно, исполнять трюки, удерживая LShift.

    Как убивали клавишников в Fifa 11


    А очень просто. В этой версии right stick целиком перенесли на numpad, а движение оставили на стрелках.
    Что здесь плохого? Исключительно то, что теперь это — разные кнопки. Вся привычная схема, основанная на шифте, полетела к чёрту, и было совершенно очевидно, что восстановить такую схему не представляется возможным. Оно сработало, клавишников стало куда меньше, чем в 10ке.
    Надо отметить, что я долго собирался. Терпел такое управление я целый год, но буквально пару дней назад чаша терпения была окончательно переполнена.

    Начало боевых действий


    Заварив чаю покрепче, скачал я WDK, открыл пример клавиатурного фильтра, и решил подкорректировать его под собственные нужды. Но беда была в том, что это был мой первый (и практически неудачный) опыт создания драйвера. Короче говоря, после примерно полусотни перезагрузок виртуальной машины (смена драйвера клавиатуры требовала перезагрузки) мне слегка наскучило ковыряться в сишном коде в шестом часу утра, и я уснул.
    Утро, как известно, всегда вечера мудренее, и оно принесло свежую мысль. Если фифа так любит геймпад — почему бы и нет? Сэмулируем его… Надо сказать, многие ребята так и делали, пользуясь штуковиной под названием KeyToJoy. Она не умела того, чего хотел я, но пользовалась популярностью, так как в 11й фифе, например, клавиатура вообще не являлась полноценным контроллером. Предупрежу сразу, поиск по этому ключевому слову однажды привёл меня к архиву, в котором сидел вирус. Я предупредил.
    В общем, я решил, что было бы неплохо найти какой-нибудь эмулятор геймпада, желательно с открытым кодом, и поправить его так, чтобы клавиатурное управление максимально приблизить к привычному мне.
    И нашёл. Вот он: VJoy homepage.
    Автор этого продукта — большая няша и просто хороший человек, поскольку обеспечил его прекрасным примером работы, переделать который нужным мне образом не составило никакого труда.

    Установка виртуального геймпада

    Ничего сложного. Качаем дистрибутив (ссылка на сайт выше), несколько раз нажимаем «далее» — и готово.
    Нет, правда. А про что тут писать-то?

    Настройка параметров девайса

    После установки потребуется настроить параметры геймпада (число кнопок, осей...), для чего потребуется утилита vJoyConf. Там тоже всё очень просто. Для фифы достаточно 10 кнопок (A,B,X,Y,start,back,LT,RT,LB,RB), четыре оси (х, у, z, rz), D-Pad с четырьмя направлениями. Программа не отражает текущих настроек виртуального геймпада, а только позволяет задать новые, поэтому не нужно пугаться, что «настройки не сохранились» — всё там сохранилось.

    Настроились, где проверить?

    Всё очень просто — запускаем апплет «игровые устройства» панели управления (joy.cpl в «выполнить» — самый быстрый вариант доступа) и смотрим на наш виртуальный геймпад. Что с ним делать? Пока ничего, т.к. им пока никто не управляет.

    Управляем джойстиком

    А для этого нам потребуется, например, MS Visual C++ Express. Ну да, сейчас мы будем слушать клавиатуру и говорить нашему геймпаду, какие кнопочки считать нажатыми. А что, мне в фифу без финтов что ли играть?
    Итак, вот тут создатель VJoy дарит миру простенькое консольное приложение на С++, которое посылает геймпаду команды установки нового состояния.
    Код примера отлично документирован, и за пару минут переделывается так, как требуется нам в контексте конкретной задачи (для игры в фифу). Например, вот этот код обеспечивает столь нужное мне переключение с left stick-а на right stick:
    	bool shift = 0!=GetAsyncKeyState(VK_LSHIFT);
    
    	bool leftKey = 0!=GetAsyncKeyState(VK_LEFT);
    	bool rightKey = 0!=GetAsyncKeyState(VK_RIGHT);
    	bool upKey = 0!=GetAsyncKeyState(VK_UP);
    	bool downKey = 0!=GetAsyncKeyState(VK_DOWN);
    
    	Y = X = 0x3fff;	//оси изначально в нейтральном положении
    	Z = ZR = 0x3fff;
    	//Вообще это очень топорное решение. Нужно плавнее.
    	//Но финты относительно сносно работают уже даже так. 
    	if(!leftKey != !rightKey)
    	{
    		if (!shift)
    			X = leftKey ? 0 : 0x7FFF; //Это такие крайние положения у осей
    		else
    			Z = leftKey ? 0 : 0x7FFF;
    	}
    	if(!upKey != !downKey)
    	{
    		if(!shift)
    			Y = upKey ? 0 : 0x7FFF;
    		else
    			ZR = upKey ? 0 : 0x7FFF;
    	}
    	//Где-то много дальше по коду, после впиленных мной 
    	//тривиальных обработчиков для кнопок джойстика
    	if (!DeviceIoControl (hDevice, IoCode, pPositionMessage, IoSize, NULL, 0, &bytes, NULL)) 
    	{
    		_tprintf(_T("Ioctl to vJoy device failed\n"));
    		break;
    	}
    


    На самом деле, всё весьма несложно. Отслеживаем кнопочки, передаём их геймпаду.
    В чём бонус? Очевидно, что сложность логики нажатия кнопочек может быть абсолютно любой,
    а не только «одна кнопка клавиатуры = одна кнопка геймпада», как это бывает в простых готовых эмуляторах. Настроить можно как угодно, и это может представлять интерес.

    Заключение


    Кому всё это нужно? Не знаю, просто пишу о том, как я кое-что задумал и успешно исполнил задуманное. Вдруг кому-нибудь подобное решение окажется полезным?

    Пару слов о получившемся эмуляторе. Полные исходники сырого, ненастраиваемого, однако рабочего изделия можно увидеть тут, в них, как мне кажется, нет ничего такого, о чём стоит писать отдельно и подробно. Более того, эта штука с точки зрения производительности не очень-то эффективна, я уверен, что можно сделать куда грамотнее, если посидеть с этим подольше. Однако в тот знаменательный вечер у меня слишком чесались руки опробовать творение, поэтому едва компилятор выплюнул ехе-файл, все мысли о модификациях моментально куда-то улетучились.

    Ещё стоит отметить, что чтобы познакомить фифу с новым джойстиком, нужно слегка помухлевать с файлом buttonDataSetup.ini в пользовательском каталоге фифы. Я не уверен, что эти подробности (также установимые самостоятельно за пять-десять минут) имеет смысл приводить здесь, но если кого-то заинтересует этот вопрос, то я освещу и его.