A simple yet addictive math puzzle game where you combine numbers on a 3D cube to reach higher values.
- Use arrow keys (↑, ↓, ←, →) or swipe gestures to interact with the cube
- When two adjacent sides have the same number:
- The chosen side's value increases by 1
- The front side gets a new random value
- When numbers are different, the cube rotates instead
- Use the [+1] button to increase the front side value by 1
- Compete for the top spot on the monthly leaderboard at the end of the game
- 3D cube visualization with smooth rotations
- Touch support for mobile devices
- Progressive difficulty
- Score tracking
- Tutorial for new players
- Responsive design that works well on mobile devices
- Vite for build tooling and development server
- TypeScript for type-safe code
- CSS for styling and animations
- Web Audio API for sound effects
- FastAPI for serving the game and handling bot interactions
- Uvicorn as ASGI server
- Install dependencies:
# Install Node.js dependencies
npm install
# Install Python dependencies
pip install -r requirements.txt- Create
.envfile in the root directory with:
BOT_TOKEN=your_telegram_bot_token
WEBAPP_URL=your_webapp_url
IS_PRODUCTION=false
DATABASE_URL=your_database_url
- Build the frontend:
npm run build- Start the development server:
python -m uvicorn api.index:app --reload- A Telegram bot token (get it from @BotFather)
- A Vercel account for hosting
- Install Vercel CLI (optional):
npm i -g vercel-
Deploy to Vercel:
- Using CLI: Run
vercelin the project directory - Or using Vercel Dashboard:
- Import your GitHub repository
- Select Python framework
- Set environment variables:
BOT_TOKEN: Your Telegram bot tokenWEBAPP_URL: Your Vercel app URLIS_PRODUCTION: trueDATABASE_URL: Your database URL
- Register a webhook:
curl -X POST https://api.telegram.org/bot<BOT_TOKEN>/setWebhook -d "url=<WEBAPP_URL>/telegram-webhook/<BOT_TOKEN>"
- Using CLI: Run
-
After deployment, set up your Telegram Mini App:
- Go to @BotFather
- Use /setmenubutton
- Select your bot
- Enter your Vercel app URL
cubegame/
├── src/ # Frontend TypeScript source
│ ├── classes/ # Game classes and core logic
│ │ └── Cube.ts # Main cube logic and game mechanics
│ ├── handlers/ # Event handlers
│ │ ├── events.ts # Keyboard and general events
│ │ └── touch.ts # Touch gesture handling
│ ├── types/ # TypeScript type definitions
│ │ └── interfaces.ts # Type interfaces
│ ├── utils/ # Utility functions
│ │ ├── colors.ts # Color generation
│ │ ├── helpers.ts # Common helper functions
│ │ └── ui.ts # UI management
│ ├── game.ts # Main game logic
│ ├── i18n.ts # Internationalization
│ ├── store.ts # Game state management
│ ├── tutorial.ts # Tutorial logic
│ └── translations/ # Translation files
│ ├── en.json # English translations
│ └── ru.json # Russian translations
├── public/ # Static assets
│ ├── img/ # Images and icons
│ │ ├── cubes.png # Background pattern
│ │ ├── arrow_r.gif # Tutorial arrows
│ │ └── arrow_u.gif # Tutorial arrows
│ └── sounds/ # Game sound effects
│ ├── rotate.mp3 # Cube rotation sound
│ ├── win.mp3 # Success sound
│ ├── fail.mp3 # Failure sound
│ └── increase.mp3 # Number increase sound
├── dist/ # Built frontend files (generated)
│ ├── assets/ # Compiled and hashed assets
│ ├── img/ # Copied and optimized images
│ └── sounds/ # Copied sound files
├── api/index.py # Main FastAPI application
│ ├── startup() # Server startup configuration
│ ├── shutdown() # Cleanup handlers
│ ├── polling() # Development mode bot updates
│ └── webhook() # Production mode bot updates
│ ├── /telegram-webhook/{bot_token} # Handles incoming Telegram updates
│ ├── /save-score # Saves the game score
│ ├── / # Serves the main index.html file
│ ├── /main-{hash}.{ext} # Serves the main assets
│ ├── /img/{file_path:path} # Serves images
│ ├── /sounds/{file_path:path} # Serves sounds
│ └── /{file_path:path} # Serves other static files
├── requirements.txt # Python dependencies
│ ├── fastapi # Web framework
│ ├── python-telegram-bot # Telegram Bot API
│ └── uvicorn # ASGI server
├── package.json # Node.js dependencies
├── vite.config.js # Vite build configuration
├── render.yaml # Render.com deployment config
│ ├── buildCommand # Build steps
│ ├── startCommand # Server startup
│ └── envVars # Environment variables
└── .env # Environment variables (not in repo)
├── BOT_TOKEN # Telegram Bot API token
├── WEBAPP_URL # Application URL
└── IS_PRODUCTION # Environment mode flag
└── DATABASE_URL # Database URL
The bot logic is now implemented within the api/index.py file. It operates in two modes:
- Development: Uses polling for receiving updates
- Production: Uses webhooks for better performance
Commands:
/start: Displays a button to launch the game
- The leaderboard should be deduced by players, and your position should be shown not by game but by position in the leaderboard.
- In the info box with the number 5, add text indicating that you should press the spacebar or tap the screen to continue.
- On the third step of the tutorial, which explains the "plus one" button, add an arrow pointing to where you need to click.
- The full leaderboard in chat.
- My results in chat.
- Analytics.
- Paid actions.
-
- Star
-
- Card
- Translations.
The game supports translations for multiple languages. Currently, the following languages are supported:
- English
- Russian
Translations are managed using a key-based system. Each string in the game is associated with a unique key. The src/i18n.ts file handles the loading of translations and provides a t() function to retrieve translated strings based on the current language.
The current language is determined by the lang cookie. If the cookie is not set, the default language is English.
To add a new language, you need to:
- Create a new JSON file in the
src/translationsdirectory with the language code as the filename (e.g.,fr.jsonfor French). - Add the translations to the JSON file, using the same keys as the English translation file.
- Import the new translation file in
src/i18n.ts. - Add the new language to the
translationsobject insrc/i18n.ts.
Feel free to submit issues and pull requests.
MIT License
Originally created by titulus