| Feature | Status | |---------|--------| | Works without backend | ✅ | | 2 local players | ✅ | | Clear controls display | ✅ | | No page reload on rematch | ✅ | | Works on Chrome/Firefox/Edge | ✅ | | Game state preserved after resize | ✅ |
When searching for "2 player games githubio," you will encounter several distinct genres. Knowing these helps you find exactly what you are in the mood for.
How it plays: Two spaceships in an arena with asteroids. Fire lasers and missiles. Controls: WASD to move, F to shoot; Arrow Keys to move, Period to shoot. Why it’s great: It adds environmental hazards (asteroids) to the mix, upping the skill ceiling.
Here are some of the most popular and fun titles you can play right now (you can search these names to find their GitHub.io links): 2 player games githubio
Before we dive into the games, let’s break down the keyword. GitHub is a development platform where programmers store code. Io (or .io) refers to a domain extension that became popular for browser-based games (like Agar.io).
When you combine them, "2 player games githubio" refers to HTML5, JavaScript, or WebGL games hosted for free on GitHub Pages. Independent developers upload their creations, and thanks to GitHub’s free hosting, players can access these games instantly without downloads, ads, or installation.
For the player, this means zero friction. You type in the URL, press a key to start, and hand half the keyboard to your opponent. | Feature | Status | |---------|--------| | Works
The search term usually refers to local multiplayer (two players on one device, sharing a keyboard) or same-network multiplayer. Here are common genres you’ll find:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no"> <title>Realm Clash – 2 Player Duel</title> <style> * box-sizing: border-box; user-select: none; body background: linear-gradient(145deg, #1a2a1f 0%, #0e1a0c 100%); font-family: 'Courier New', monospace; display: flex; justify-content: center; align-items: center; min-height: 100vh; margin: 0; padding: 20px; .game-container max-width: 900px; width: 100%; background: #2c2118; border-radius: 48px; box-shadow: 0 20px 35px rgba(0,0,0,0.5), inset 0 1px 3px rgba(255,255,200,0.1); padding: 20px; border: 2px solid #dab066; .players display: flex; flex-wrap: wrap; gap: 20px; margin-bottom: 30px; .player-card flex: 1; background: #1f1a14; border-radius: 32px; padding: 20px; text-align: center; box-shadow: inset 0 0 0 2px #3e2e22, 0 8px 12px black; color: #f5e7c8; .active-glow box-shadow: 0 0 0 3px #ffcc55, inset 0 0 0 2px #ffcc55; background: #2a221b; .hp-bar-bg background: #3a2820; border-radius: 20px; height: 20px; width: 100%; margin: 10px 0; overflow: hidden; .hp-fill background: #b34e3a; width: 100%; height: 100%; transition: width 0.3s ease; .stats font-size: 1.3rem; font-weight: bold; margin: 12px 0; .action-panel background: #00000077; border-radius: 36px; padding: 20px; backdrop-filter: blur(4px); text-align: center; .action-buttons display: flex; flex-wrap: wrap; gap: 14px; justify-content: center; margin: 20px 0; button background: #4a3729; border: none; font-family: monospace; font-weight: bold; font-size: 1.2rem; padding: 12px 24px; border-radius: 60px; color: #ffefcf; cursor: pointer; transition: 0.1s linear; box-shadow: 0 4px 0 #1e130e; button:active transform: translateY(2px); box-shadow: 0 1px 0 #1e130e; .log background: #0c0a07; border-radius: 28px; padding: 15px; height: 150px; overflow-y: auto; font-size: 0.9rem; margin-top: 20px; color: #cbbd9a; border: 1px solid #6a4e36; .reset-btn background: #6e3b2c; margin-top: 16px; width: 100%; .turn-indicator font-size: 1.5rem; font-weight: bold; text-align: center; background: #00000099; border-radius: 40px; padding: 8px; margin-bottom: 20px; @media (max-width: 650px) .action-buttons button padding: 8px 16px; font-size: 1rem; .stats font-size: 1rem; </style> </head> <body> <div class="game-container"> <div class="turn-indicator" id="turnText">👑 Player 1's turn</div> <div class="players"> <div class="player-card" id="p1Card"> <h2>⚔️ LORD ALDRIC</h2> <div class="stats">❤️ HP: <span id="p1Hp">100</span> | 🪙 Gold: <span id="p1Gold">20</span></div> <div class="hp-bar-bg"><div class="hp-fill" id="p1HpFill" style="width: 100%"></div></div> <div id="p1ActionDisplay">⏳ waiting...</div> </div> <div class="player-card" id="p2Card"> <h2>🛡️ LADY MORWEN</h2> <div class="stats">❤️ HP: <span id="p2Hp">100</span> | 🪙 Gold: <span id="p2Gold">20</span></div> <div class="hp-bar-bg"><div class="hp-fill" id="p2HpFill" style="width: 100%"></div></div> <div id="p2ActionDisplay">⏳ waiting...</div> </div> </div> <div class="action-panel"> <div class="action-buttons" id="actionButtons"> <button data-action="attack">⚔️ ATTACK</button> <button data-action="defend">🛡️ DEFEND</button> <button data-action="steal">💰 STEAL</button> <button data-action="heal">💚 HEAL (8 gold → +15 HP)</button> </div> <div class="log" id="battleLog"> > The realm awaits your commands...<br> > Player 1, choose wisely. </div> <button class="reset-btn" id="resetGame">🔄 RESET DUEL</button> </div> </div><script> // Game state let players = [ hp: 100, gold: 20, lastAction: null, defended: false, name: "Lord Aldric" , hp: 100, gold: 20, lastAction: null, defended: false, name: "Lady Morwen" ]; let currentTurn = 0; // 0 = player1, 1 = player2 let waitingForAction = true; let p1ChosenAction = null; let p2ChosenAction = null; let gameActive = true;
// DOM elements const p1HpSpan = document.getElementById('p1Hp'); const p2HpSpan = document.getElementById('p2Hp'); const p1GoldSpan = document.getElementById('p1Gold'); const p2GoldSpan = document.getElementById('p2Gold'); const p1Fill = document.getElementById('p1HpFill'); const p2Fill = document.getElementById('p2HpFill'); const p1ActionDisplay = document.getElementById('p1ActionDisplay'); const p2ActionDisplay = document.getElementById('p2ActionDisplay'); const turnText = document.getElementById('turnText'); const battleLog = document.getElementById('battleLog'); const p1Card = document.getElementById('p1Card'); const p2Card = document.getElementById('p2Card'); function log(msg) const p = document.createElement('div'); p.innerHTML = `> $msg`; battleLog.appendChild(p); battleLog.scrollTop = battleLog.scrollHeight; while(battleLog.children.length > 20) battleLog.removeChild(battleLog.firstChild); function updateUI() p1HpSpan.innerText = players[0].hp; p2HpSpan.innerText = players[1].hp; p1GoldSpan.innerText = players[0].gold; p2GoldSpan.innerText = players[1].gold; let p1Percent = Math.max(0, (players[0].hp / 100) * 100); let p2Percent = Math.max(0, (players[1].hp / 100) * 100); p1Fill.style.width = p1Percent + '%'; p2Fill.style.width = p2Percent + '%'; if(players[0].hp <= 0) p1Fill.style.background = "#5a2a1a"; if(players[1].hp <= 0) p2Fill.style.background = "#5a2a1a"; function checkGameOver() if(players[0].hp <= 0) log("🏆 LADY MORWEN VICTORY! The realm is hers."); gameActive = false; turnText.innerText = "💀 GAME OVER - Player 2 wins!"; return true; else if(players[1].hp <= 0) log("🏆 LORD ALDRIC VICTORY! Glory to his house."); gameActive = false; turnText.innerText = "💀 GAME OVER - Player 1 wins!"; return true; return false; function resolveRound() function updateActiveCard() if(!gameActive) return; if(currentTurn === 0) p1Card.classList.add('active-glow'); p2Card.classList.remove('active-glow'); else p2Card.classList.add('active-glow'); p1Card.classList.remove('active-glow'); function handleAction(action) if(!gameActive) log("Game over. Press RESET."); return; if(!waitingForAction) log("Round already resolved! Wait for next turn."); return; // store action for current player if(currentTurn === 0 && p1ChosenAction === null) p1ChosenAction = action; p1ActionDisplay.innerText = `🗡️ $action.toUpperCase() chosen`; log(`$players[0].name chose $action`); currentTurn = 1; turnText.innerText = "🛡️ Player 2's turn"; updateActiveCard(); // if both chosen, resolve if(p2ChosenAction !== null) waitingForAction = false; resolveRound(); else if(currentTurn === 1 && p2ChosenAction === null) p2ChosenAction = action; p2ActionDisplay.innerText = `🗡️ $action.toUpperCase() chosen`; log(`$players[1].name chose $action`); currentTurn = 0; turnText.innerText = "👑 Player 1's turn"; updateActiveCard(); if(p1ChosenAction !== null) waitingForAction = false; resolveRound(); else log("Wait! Already chose an action this round."); function resetGame() players = [ hp: 100, gold: 20, lastAction: null, defended: false, name: "Lord Aldric" , hp: 100, gold: 20, lastAction: null, defended: false, name: "Lady Morwen" ]; currentTurn = 0; waitingForAction = true; gameActive = true; p1ChosenAction = null; p2ChosenAction = null; p1ActionDisplay.innerText = "⏳ awaiting choice"; p2ActionDisplay.innerText = "⏳ awaiting choice"; turnText.innerText = "👑 Player 1's turn"; updateUI(); updateActiveCard(); battleLog.innerHTML = "> The realm resets. New duel begins!<br>"; log("Both monarchs rise again."); // attach event listeners document.querySelectorAll('[data-action]').forEach(btn => btn.addEventListener('click', (e) => let action = btn.getAttribute('data-action'); handleAction(action); ); ); document.getElementById('resetGame').addEventListener('click', resetGame); updateUI(); updateActiveCard();
</script> </body> </html>
Explore Popular Game Tags:
Check out GitHub Collections: