Skip to content

Latest commit

 

History

1 Commit

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

⚖️ Balance Scale Showdown

A real-time multiplayer strategy game where players compete by picking numbers strategically. The player furthest from 80% of the average loses points each round — last player standing wins!


📁 Project Structure

balance-scale-showdown/
├── backend/                    # Node.js + Express + Socket.io
│   ├── models/
│   │   ├── Room.js             # MongoDB Room schema
│   │   └── GameHistory.js      # Game history schema
│   ├── routes/
│   │   ├── rooms.js            # REST: room lookup
│   │   └── games.js            # REST: history/leaderboard
│   ├── socket/
│   │   └── socketHandlers.js   # All Socket.io events
│   ├── utils/
│   │   └── roomManager.js      # In-memory room state (singleton)
│   ├── server.js               # Entry point
│   ├── package.json
│   └── .env.example
│
├── frontend/                   # React + Vite + TailwindCSS
│   ├── src/
│   │   ├── context/
│   │   │   ├── SocketContext.jsx  # Socket.io client provider
│   │   │   └── GameContext.jsx    # Global game state (useReducer)
│   │   ├── hooks/
│   │   │   └── useSocketEvents.js # Maps socket events → state
│   │   ├── pages/
│   │   │   ├── HomePage.jsx       # Landing + create/join
│   │   │   ├── LobbyPage.jsx      # Waiting room
│   │   │   ├── GamePage.jsx       # Main gameplay
│   │   │   ├── ResultsPage.jsx    # Round reveal animation
│   │   │   └── GameOverPage.jsx   # Winner + stats
│   │   ├── components/
│   │   │   ├── game/
│   │   │   │   ├── TimerRing.jsx  # SVG countdown timer
│   │   │   │   └── ScoreBoard.jsx # Live player scores
│   │   │   ├── lobby/
│   │   │   │   └── PlayerCard.jsx # Lobby player row
│   │   │   └── ui/
│   │   │       └── ChatPanel.jsx  # Real-time chat
│   │   ├── App.jsx               # Screen router
│   │   ├── main.jsx
│   │   └── index.css             # Tailwind + custom styles
│   ├── index.html
│   ├── vite.config.js
│   ├── tailwind.config.js
│   └── package.json
│
├── render.yaml                 # One-click Render deployment
├── package.json                # Monorepo convenience scripts
└── README.md

🎮 Game Rules

Rule Value
Starting points 10 per player
Points lost (loser/round) 2
Round timer 20 seconds
Number range 0 – 100
Target formula 80% × average of all picks
Elimination 0 points → out
Win condition Last player alive

Example: Players pick 30, 50, 70.
Average = 50. Target = 40.
Player who picked 70 (distance 30) is furthest → loses 2 points.


⚡ Socket.io Event Reference

Client → Server

Event Payload Description
create_room { username, playerId? } Create a new room
join_room { roomCode, username, playerId? } Join existing room
player_ready { roomCode, playerId } Toggle ready status
start_game { roomCode, playerId } Host starts game
submit_number { roomCode, playerId, number } Submit round pick
chat_message { roomCode, playerId, message } Send chat

Server → Client

Event Payload Description
room_created { roomCode, playerId, room } Room created confirmation
room_joined { roomCode, playerId, room, rejoined, asSpectator } Join confirmation
player_joined { room, username, rejoined } Broadcast to room
player_ready_update { room, playerId, isReady } Ready state changed
game_started { room, round } Game begins
round_timer { timeLeft, total, round } Countdown tick
number_submitted { success, number } Submission confirmed
submission_update { submittedCount, totalCount, playerId } Submission progress
reveal_results { result, room } Round results
update_scores { players } Score sync
eliminate_player { playerId, username } Player eliminated
next_round { round, room } New round starts
game_over { winner, room, roundHistory } Game finished
chat_message { id, playerId, username, message, timestamp } Chat message
player_disconnected { room, playerId, username } Player went offline
error { message } Error notification

🚀 Local Development

Prerequisites

  • Node.js 18+
  • MongoDB (local or Atlas free tier)

1. Clone & install

git clone <your-repo-url>
cd balance-scale-showdown

# Install all dependencies
npm run install:all
# or manually:
cd backend && npm install
cd ../frontend && npm install

2. Configure environment

# Backend
cp backend/.env.example backend/.env
# Edit: set MONGODB_URI (or leave default for local MongoDB)

# Frontend
cp frontend/.env.example frontend/.env
# Edit: VITE_BACKEND_URL=http://localhost:3001

3. Start development servers

# Start both together (requires concurrently in root)
npm install       # installs concurrently
npm run dev

# Or separately in two terminals:
cd backend && npm run dev     # → http://localhost:3001
cd frontend && npm run dev    # → http://localhost:5173

4. Open the game

Go to http://localhost:5173 in two or more browser tabs/windows to test multiplayer.

No MongoDB? The server runs in in-memory mode automatically — game state works but won't persist across restarts.


🌐 Deployment

Option A: Render.com (Recommended — free tier)

  1. Push your code to GitHub
  2. Go to render.com → New → Blueprint
  3. Connect your repo — Render auto-detects render.yaml
  4. Set environment variables in the Render dashboard:
    • Backend: MONGODB_URI, CLIENT_URL (your frontend URL)
    • Frontend: VITE_BACKEND_URL (your backend URL)
  5. Deploy!

Option B: Railway

# Install Railway CLI
npm install -g @railway/cli
railway login

# Deploy backend
cd backend
railway init
railway up

# Set env vars
railway variables set MONGODB_URI="mongodb+srv://..."
railway variables set CLIENT_URL="https://your-frontend.vercel.app"

Then deploy frontend to Vercel:

cd frontend
npx vercel
# Set VITE_BACKEND_URL to your Railway backend URL

Option C: VPS (Ubuntu/Debian)

# Install Node.js + PM2
curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash -
sudo apt-get install -y nodejs
npm install -g pm2

# Clone & setup
git clone <repo> && cd balance-scale-showdown
cd backend && npm install
cp .env.example .env && nano .env   # fill in your values

# Start backend with PM2
pm2 start server.js --name bss-backend
pm2 save && pm2 startup

# Build frontend
cd ../frontend && npm install
VITE_BACKEND_URL=https://your-backend.com npm run build

# Serve frontend with Nginx (or use Vercel/Netlify)
sudo cp -r dist /var/www/bss
# Configure Nginx to serve /var/www/bss + proxy /api and /socket.io to :3001

Option D: Vercel (Frontend) + Any Backend

  1. Deploy backend to Railway/Render/VPS
  2. In frontend/.env: set VITE_BACKEND_URL=<your backend URL>
  3. Run npm run build in /frontend
  4. Deploy dist/ to Vercel, Netlify, or Cloudflare Pages

🔧 Configuration

Edit backend/utils/roomManager.js → settings object to tune gameplay:

settings: {
  roundTimeLimit: 20,           // seconds per round
  startingPoints: 10,           // points each player begins with
  pointsDeductedPerRound: 2,    // penalty for the round loser
  targetMultiplier: 0.8,        // target = average × this
}

🏗️ Architecture Notes

  • In-memory state: RoomManager holds all live game state in a Map. Fast, zero latency. MongoDB syncs for persistence but is optional.
  • Rejoin support: Player IDs are saved in localStorage. On reconnect, the same ID re-attaches the socket to the existing room slot.
  • Spectator mode: Players who join a room mid-game are added as spectators automatically.
  • Timer authority: The server owns the round timer. Clients display it but can't manipulate it.
  • Auto-cleanup: Rooms with TTL index in MongoDB auto-delete after 24h. In-memory rooms are cleaned up when all players disconnect.

📦 Tech Stack

Layer Tech
Frontend React 18, Vite, TailwindCSS, Framer Motion
Backend Node.js, Express, Socket.io
Database MongoDB + Mongoose (optional)
Real-time Socket.io (WebSockets with fallback)
Deployment Render / Railway / Vercel / VPS

About

A real-time multiplayer strategy game where players compete by picking numbers strategically. The player furthest from 80% of the average loses points each round — last player standing wins!

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages