Motivo
Acabo de escribir por mero hobby un pequeño programa en C que emite eventos de teclado al leer un joystick común y corriente en Linux. A pesar de ser bastante simple, cumple bien su cometido. Sin embargo, posee una carencia mortal: no puedo apuntarle a nada.
Sugerencia
Añadir un botón de
Cycle Target que seleccione a los aliados más cercanos, sin orden de prioridad necesario.
Análisis
Dada la existencia de la tecla para visualizar la vida de los
jugadores aliados, no existen motivos para no implementar un "auto target" de los mismos.
La sugerencia no corre para los enemigos u otros objetos, ya que un sistema que presione repetidas veces dicha tecla podría descubrir a aquellos que usen el terreno como ventaja táctica (para ocultarse).
Usos
Es una gran herramienta para conjuradores de soporte. En mi caso particular, he notado un deterioro en las capacidades de selección del juego, principalmente causado por la poca definición que brinda el cursor.
Extras
Adjunto el código del programa que mencioné. Los cambios para utilizar lectura asincrónica son mínimos, pero no valía la pena implementarlos para un programa con un solo file descriptor.
Bonus: insertarlo en cualquier framework de eventos o en un event loop propio es muy fácil ya que es leer desde un file descriptor, y como no hay que tocar nada extra se puede wrappear todo en un #ifndef _WIN32
ADVERTENCIA: Es código de ejemplo, no un haiku.
Code:
/* Resources
*
* see: http://www.linuxquestions.org/questions/programming-9/key-press-202968/
* http://www.mjmwired.net/kernel/Documentation/input/joystick-api.txt
* http://www.mjmwired.net/kernel/Documentation/input/joystick.txt
*
* You need libxtst-dev to compile this.
* Compile with: gcc -o js js.c -lX11 -lXtst
* Execute as: ./js /dev/input/js0
* */
/*#define XK_LATIN1*/ /* enable this if you have problems */
#define XK_MISCELLANY
#define XK_XKB_KEYS
#include <X11/keysymdef.h>
#include <X11/Xlib.h>
#include <X11/extensions/XTest.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#define JS_EVENT_BUTTON 0x01 /* button pressed/released */
#define JS_EVENT_AXIS 0x02 /* joystick moved */
#define JS_EVENT_INIT 0x80 /* initial state of device */
typedef struct jsEvt{
unsigned int time; /* event timestamp in milliseconds */
short int value; /* value */
unsigned char type; /* event type */
unsigned char number; /* axis/button number */
} js_event;
void send_key(KeySym, int, Display *);
void send_wsad(int no, int val, Display * d);
/* Sequence of actions. Index is event number */
KeySym buttons[] = {XK_1, XK_2, XK_3, XK_4, XK_space, XK_r, XK_F1, XK_F2};
int
main(int argc, char** argv)
{
int joystick;
js_event event_data;
Display* pDisplay = XOpenDisplay(NULL);
if(pDisplay == NULL) return 1;
if(argc < 2) return 2;
joystick = open(argv[1], O_RDONLY);
/* We open a file that happens to be a FIFO where the kernel just writes a raw structure. */
while(read(joystick, &event_data, sizeof(js_event)) > 0){
if (!(event_data.type & JS_EVENT_INIT)){
if(event_data.type & JS_EVENT_BUTTON){
send_key(buttons[event_data.number], event_data.value, pDisplay);
}
else if (event_data.type & JS_EVENT_AXIS){
send_wsad(event_data.number, event_data.value, pDisplay);
}
}
}
close(joystick);
XCloseDisplay(pDisplay);
return EXIT_SUCCESS;
}
/* could be a macro */
void
send_key(KeySym key, int status, Display *d){
XTestFakeKeyEvent(d, XKeysymToKeycode(d, key), status, CurrentTime);
XFlush(d);
}
/* WARNING: No boundary check. Throwaway code.
* This function translates analog values to WSAD movement.
*/
void
send_wsad(int no, int val, Display * d){
KeySym key_pos = no ? XK_s : XK_d;
KeySym key_neg = no ? XK_w : XK_a;
if (abs(val) < 16000){
send_key(key_pos, 0, d);
send_key(key_neg, 0, d);
} else
send_key(val > 0 ? key_pos : key_neg, 1, d);
}