react-native-earl-gamepad 0.5.0 → 0.5.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +47 -1
- package/dist/GamepadBridge.d.ts +2 -2
- package/dist/GamepadBridge.js +10 -5
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
# react-native-earl-gamepad
|
|
2
|
+

|
|
3
|
+

|
|
4
|
+

|
|
2
5
|
|
|
3
6
|
WebView-based gamepad bridge for React Native. Polls `navigator.getGamepads()` in a hidden WebView and surfaces buttons, sticks, d-pad, and connection events to JS.
|
|
4
|
-
|
|
5
7
|
- Components: `GamepadBridge`, `useGamepad`, and `GamepadDebug`.
|
|
6
8
|
- Deadzone handling (default `0.15`) with auto-clear on disconnect.
|
|
7
9
|
- Typed events for buttons, axes, d-pad, and status.
|
|
@@ -45,6 +47,50 @@ export function Controls() {
|
|
|
45
47
|
}
|
|
46
48
|
```
|
|
47
49
|
|
|
50
|
+
### Control Logic Example
|
|
51
|
+
|
|
52
|
+
Here is an example of mapping D-pad events to movement vectors
|
|
53
|
+
|
|
54
|
+
```tsx
|
|
55
|
+
import { useState, useCallback } from "react";
|
|
56
|
+
import { GamepadBridge, type DpadEvent } from "react-native-earl-gamepad";
|
|
57
|
+
type MoveKey = keyof typeof MOVES;
|
|
58
|
+
|
|
59
|
+
const MOVES: Record<string, [number, number]> = {
|
|
60
|
+
up: [1, 0],
|
|
61
|
+
down: [-1, 0],
|
|
62
|
+
right: [0, 1],
|
|
63
|
+
left: [0, -1],
|
|
64
|
+
stop: [0, 0],
|
|
65
|
+
|
|
66
|
+
axis_left_x_neg: [0, -1],
|
|
67
|
+
axis_left_x_pos: [0, 1],
|
|
68
|
+
axis_left_y_pos: [1, 0],
|
|
69
|
+
axis_left_y_neg: [-1, 0],
|
|
70
|
+
|
|
71
|
+
// add more
|
|
72
|
+
}; // example only for the control logic
|
|
73
|
+
|
|
74
|
+
export function Controls() {
|
|
75
|
+
const [active, setActive] = useState<string | null>(null);
|
|
76
|
+
|
|
77
|
+
const handleDpad = useCallback(
|
|
78
|
+
(event: DpadEvent) => {
|
|
79
|
+
const key = event.key as MoveKey;
|
|
80
|
+
if (event.pressed) {
|
|
81
|
+
if (active !== key) {
|
|
82
|
+
console.log("Dpad press", key);
|
|
83
|
+
}
|
|
84
|
+
} else if (active === key) {
|
|
85
|
+
// do something
|
|
86
|
+
}
|
|
87
|
+
},
|
|
88
|
+
[active]
|
|
89
|
+
);
|
|
90
|
+
return <GamepadBridge enabled onDpad={handleDpad} axisThreshold={0.15} />;
|
|
91
|
+
}
|
|
92
|
+
```
|
|
93
|
+
|
|
48
94
|
### Hook for stateful consumption
|
|
49
95
|
|
|
50
96
|
`useGamepad` keeps pressed state and axes for you. You still need to render the provided `bridge` element once.
|
package/dist/GamepadBridge.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { StyleProp, ViewStyle } from
|
|
2
|
-
import type { AxisEvent, ButtonEvent, DpadEvent, StatusEvent } from
|
|
1
|
+
import { StyleProp, ViewStyle } from "react-native";
|
|
2
|
+
import type { AxisEvent, ButtonEvent, DpadEvent, StatusEvent } from "./types";
|
|
3
3
|
type Props = {
|
|
4
4
|
enabled?: boolean;
|
|
5
5
|
axisThreshold?: number;
|
package/dist/GamepadBridge.js
CHANGED
|
@@ -118,16 +118,16 @@ function GamepadBridge({ enabled = true, axisThreshold = 0.15, onDpad, onButton,
|
|
|
118
118
|
const handleMessage = (event) => {
|
|
119
119
|
try {
|
|
120
120
|
const data = JSON.parse(event.nativeEvent.data);
|
|
121
|
-
if (data.type ===
|
|
121
|
+
if (data.type === "dpad") {
|
|
122
122
|
onDpad === null || onDpad === void 0 ? void 0 : onDpad(data);
|
|
123
123
|
}
|
|
124
|
-
else if (data.type ===
|
|
124
|
+
else if (data.type === "button") {
|
|
125
125
|
onButton === null || onButton === void 0 ? void 0 : onButton(data);
|
|
126
126
|
}
|
|
127
|
-
else if (data.type ===
|
|
127
|
+
else if (data.type === "axis") {
|
|
128
128
|
onAxis === null || onAxis === void 0 ? void 0 : onAxis(data);
|
|
129
129
|
}
|
|
130
|
-
else if (data.type ===
|
|
130
|
+
else if (data.type === "status") {
|
|
131
131
|
onStatus === null || onStatus === void 0 ? void 0 : onStatus(data);
|
|
132
132
|
}
|
|
133
133
|
}
|
|
@@ -135,5 +135,10 @@ function GamepadBridge({ enabled = true, axisThreshold = 0.15, onDpad, onButton,
|
|
|
135
135
|
// ignore malformed messages
|
|
136
136
|
}
|
|
137
137
|
};
|
|
138
|
-
return ((0, jsx_runtime_1.jsx)(react_native_webview_1.default, { ref: webviewRef, source: { html }, originWhitelist: [
|
|
138
|
+
return ((0, jsx_runtime_1.jsx)(react_native_webview_1.default, { ref: webviewRef, source: { html }, originWhitelist: ["*"], onMessage: handleMessage, javaScriptEnabled: true, onLoad: focusBridge, onLayout: focusBridge, onTouchStart: focusBridge, style: style !== null && style !== void 0 ? style : {
|
|
139
|
+
width: 1,
|
|
140
|
+
height: 1,
|
|
141
|
+
position: "absolute",
|
|
142
|
+
opacity: 0,
|
|
143
|
+
} }));
|
|
139
144
|
}
|