Java library for accessing input devices
The JInput Project hosts an implementation of an API for game controller discovery and polled input. It is part of a suite of open-source technologies initiated by the Game Technology Group at Sun Microsystems with intention of making the development of high performance games in Java a reality.
The API itself is pure Java and presents a platform-neutral completely portable model of controller discovery and polling. It can handle arbitrary controllers and returns both human and machine understandable descriptions of the inputs available.
The implementation hosted here also includes plug-ins to allow the API to adapt to various specific platforms. These plug-ins often contain a native code portion to interface to the host system.
Controller 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 public abstract class AbstractController implements Controller { public synchronized boolean poll () { Component[] components = getComponents(); try { pollDevice(); for (int i = 0 ; i < components.length; i++) { AbstractComponent component = (AbstractComponent)components[i]; if (component.isRelative()) { component.setPollData(0 ); } else { component.resetHasPolled(); } } while (getNextDeviceEvent(event)) { AbstractComponent component = (AbstractComponent)event.getComponent(); float value = event.getValue(); if (component.isRelative()) { if (value == 0 ) continue ; component.setPollData(component.getPollData() + value); } else { if (value == component.getEventValue()) continue ; component.setEventValue(value); } if (!event_queue.isFull()) event_queue.add(event); } return true ; } catch (IOException e) { ControllerEnvironment.log("Failed to poll device: " + e.getMessage()); return false ; } } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 final class DIAbstractController extends AbstractController { private final IDirectInputDevice device; public final void pollDevice () throws IOException { device.pollAll(); } protected final boolean getNextDeviceEvent (Event event) throws IOException { return DIControllers.getNextDeviceEvent(event, device); } } final class DIControllers { private final static DIDeviceObjectData di_event = new DIDeviceObjectData(); public final static synchronized boolean getNextDeviceEvent (Event event, IDirectInputDevice device) throws IOException { if (!device.getNextEvent(di_event)) return false ; DIDeviceObject object = device.mapEvent(di_event); DIComponent component = device.mapObject(object); if (component == null ) return false ; int event_value; if (object.isRelative()) { event_value = object.getRelativeEventValue(di_event.getData()); } else { event_value = di_event.getData(); } event.set(component, component.getDeviceObject().convertValue(event_value), di_event.getNanos()); return true ; } public final static float poll (Component component, DIDeviceObject object) throws IOException { int poll_data = object.getDevice().getPollData(object); float result; if (object.isRelative()) { result = object.getRelativePollValue(poll_data); } else { result = poll_data; } return object.convertValue(result); } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 final class IDirectInputDevice { public final synchronized void pollAll () throws IOException { checkReleased(); poll(); getDeviceState(device_state); queue.compact(); getDeviceData(queue); queue.flip(); } private final boolean getDeviceData (DataQueue<DIDeviceObjectData> queue) throws IOException { int res = nGetDeviceData(address, 0 , queue, queue.getElements(), queue.position(), queue.remaining()); if (res != DI_OK && res != DI_BUFFEROVERFLOW) { if (res == DIERR_NOTACQUIRED) { acquire(); return false ; } throw new IOException("Failed to get device data (" + Integer.toHexString(res) + ")" ); } return true ; } private final static native int nGetDeviceData (long address, int flags, DataQueue<DIDeviceObjectData> queue, Object[] queue_elements, int position, int remaining) ; public synchronized final boolean getNextEvent (DIDeviceObjectData data) { DIDeviceObjectData next_event = queue.get(); if (next_event == null ) return false ; data.set(next_event); return true ; } } final class DataQueue <T > { private final T[] elements; private int position; private int limit; public final void compact () { int index = 0 ; while (hasRemaining()) { swap(position, index); position++; index++; } position = index; limit = elements.length; } public final void flip () { limit = position; position = 0 ; } public final boolean hasRemaining () { return remaining() > 0 ; } public final int remaining () { return limit - position; } public final void clear () { position = 0 ; limit = elements.length; } } final class DIDeviceObjectData { private int format_offset; private int data; private int millis; private int sequence; public final void set (int format_offset, int data, int millis, int sequence) { this .format_offset = format_offset; this .data = data; this .millis = millis; this .sequence = sequence; } public final void set (DIDeviceObjectData other) { set(other.format_offset, other.data, other.millis, other.sequence); } public final int getData () { return data; } public final int getFormatOffset () { return format_offset; } public final long getNanos () { return millis*1000000L ; } }
总结 通过Controller
查询输入数据,最终调用Device
查询底层输入数据,保存到队列queue
中,再从队列queue
中取出作为event
传递到Controller
中的component
,并更新其属性pollData
。