Allow players to play couch co-op in your game using their mobile devices as controllers.
npm install touch-coopA TypeScript library that enables couch co-op gaming on the web, using mobile devices as controllers.

TouchCoop is designed to allow up to four players to connect to a game server using their mobile devices as controllers. Each player can use touch controls on their device to send input events to the game.
TouchCoop is intended for playing games on a TV or monitor, while players use their phones or tablets as controllers.
TouchCoop is ideal for casual multiplayer games, such as platformers, puzzle games, or party games. TouchCoop is not intended for games that require low-latency input, such as first-person shooters.
TouchCoop does not require servers or user accounts for gameplay. However, it requires the PeerJS server (or your own signaling server) for initial connection setup. All communication is done using WebRTC, which allows for peer-to-peer connections between the players' devices.
TouchCoop is powered by PeerJS, which provides a simple API for WebRTC peer-to-peer connections. By default, TouchCoop uses the public PeerJS servers for signaling and STUN/TURN services.
- Status Page: Check the status of PeerJS public servers at https://status.peerjs.com/.
- Custom Servers: If you need more control or reliability, you can deploy your own PeerJS server. See the PeerJS documentation for instructions on setting up your own server. You can pass custom PeerJS options to the Match and Player constructors to connect to your own server.
``ts
// Example: Using a custom PeerJS server
import { Match, Player } from "touch-coop";
const customPeerConfig = {
host: 'your-peerjs-server.com',
port: 9000,
path: '/peerjs'
};
const match = new Match();
await match.createLobby(gamePadURL, handlePlayerEvent, customPeerConfig);
const player = new Player(customPeerConfig);
`
`bash`
npm install touch-coop
The library expects your game to use the Match and Player classes. Your game will require a minimum of two pages with unique URLs:
The main game page hosts the game and creates a Match instance. This page uses createLobby() to generate a QR code that players can scan to join the game.
`ts
import { Match, type PlayerEvent } from "touch-coop";
// PlayerEvent type:
// type PlayerEvent =
// | { action: "JOIN" | "LEAVE"; playerId: string; playerName: string; timestamp: number; }
// | { action: "MOVE"; playerId: string; playerName: string; button: string; timestamp: number; }
const gamePadURL = "http://localhost:8080/demos/gamepad";
function handlePlayerEvent(event: PlayerEvent) {
switch (event.action) {
case "JOIN":
console.log(Player ${event.playerId} ${event.playerName} joined the game.);Player ${event.playerId} ${event.playerName} left the game.
break;
case "LEAVE":
console.log();Player ${event.playerId} ${event.playerName} pressed ${event.button}
break;
case "MOVE":
console.log();
break;
}
}
export function Lobby() {
const [lobby, setLobby] = React.useState<{
dataUrl: string;
shareURL: string;
} | null>(null);
React.useEffect(() => {
(async () => {
if (lobby === null) {
const match = new Match();
const { dataUrl, shareURL } = await match.createLobby(
gamePadURL, handlePlayerEvent
);
setLobby({ dataUrl, shareURL });
}
})();
}, [lobby]);
return lobby === null ? (
$3
Each player scans a QR code to join the game. The QR code contains a unique URL that opens a web page with touch controls. This page uses the
Player class to connect to the game match with player.joinMatch() and send input events with player.sendMove("X").`ts
import React from "react";
import { Player } from "touch-coop";const player = new Player();
export default function GamePad() {
const [loading, setLoading] = React.useState(true);
React.useEffect(() => {
`ts
import React from "react";
import { Player } from "touch-coop"; const player = new Player();
export default function GamePad() {
const [loading, setLoading] = React.useState(true);
React.useEffect(() => {
(async () => {
const playerName = prompt("Enter your player name:") || "Player";
await player.joinMatch(playerName);
setLoading(false);
})();
}, []);
if (loading) {
return
Loading…;
} return (
);
}
`You can try a live demo of TouchCoop at https://SlaneyEE.github.io/touch-coop/demos/match.html.
The demo contains a simple game where players can join by scanning a QR Code and use their mobile devices as controllers. Each player can use the on-screen buttons to send input events to the game.
The game page is ./demos/match.html. The QR code redirects players to ./demos/gamepad/index.html.
You need to run a local server to host the demo files. You can use a simple HTTP server like
http-server or live-server to serve the files from the root directory and then access http://localhost:8080/demos/match.html in your browser.---
$3
#### PlayerEvent type
`ts
type PlayerEvent =
| { action: "JOIN" | "LEAVE"; playerId: string; playerName: string; timestamp: number; }
| { action: "MOVE"; playerId: string; playerName: string; button: string; timestamp: number; };
`#### Match constructor
`ts
new Match(gamepadUiUrl: string, onPlayerEvent: (event: PlayerEvent) => void)
`#### createLobby
`ts
async createLobby(peerConfig?: Peer.PeerOptions): Promise<{ dataUrl: string; shareURL: string; }>
`#### getInvitationStatus
`ts
getInvitationStatus(playerId: string): boolean | undefined
`#### destroy
`ts
destroy(): void
``