A classic Tetris game implementation using vanilla JavaScript and DOM manipulation, built without any frameworks or canvas library.
This project is a browser-based Tetris game that demonstrates understanding of game loops, DOM manipulation, CSS animations, and performance optimization using requestAnimationFrame. The game follows the classic Tetris gameplay where players arrange falling tetrominoes to complete horizontal lines.
- Classic Tetris Mechanics: All 7 standard tetrominoes (T, O, L, J, S, Z, I shapes)
- Piece Movement: Left, right, down movement with arrow keys
- Rotation: Clockwise rotation with collision detection
- Hard Drop: Instantly drop piece to bottom with spacebar
- Line Clearing: Complete horizontal lines are cleared with scoring
- Game Over Detection: Game ends when pieces stack to the top
- Score Display: Real-time score tracking (13 points per line cleared)
- Timer: Elapsed game time counter
- Start Menu: Initial game start screen
- Pause Menu:
- Resume game option
- Restart game option
- Game Over Screen: End game display with restart option
| Key | Action |
|---|---|
← Arrow Left |
Move piece left |
→ Arrow Right |
Move piece right |
↓ Arrow Down |
Move piece down (soft drop) |
↑ Arrow Up |
Rotate piece clockwise |
Space |
Hard drop (instant drop) |
Escape |
Pause/Resume game |
- Color-coded Tetrominoes: Each piece type has distinct colors
- CSS Animations:
- Drop animation for falling pieces
- Rotation animation for line clears
- Grid Display: 20x10 classic Tetris grid
- Visual Feedback: Active pieces vs. fixed pieces styling
make-your-game/
├── index.html # HTML structure
├── style.css # Styling and animations
└── game.js # Game logic and rendering
The game uses requestAnimationFrame for smooth 60 FPS rendering:
function gameLoop(timestamp) {
updateTimer(timestamp);
if (gameover) { /* handle game over */ }
if (pause) return;
if (time > dropInterval) {
moveDown();
dropStart = timestamp;
}
requestAnimationFrame(gameLoop);
}- Grid Size: 20 rows x 10 columns
- Cell States:
0: Empty cell1: Active (falling) piece2: Fixed (placed) piece
All 7 standard Tetris pieces implemented as 2D arrays:
| Shape | Name | Pattern |
|---|---|---|
| T | T-shape | [[0,1,0],[1,1,1]] |
| O | O-shape (Square) | [[1,1],[1,1]] |
| L | L-shape | [[1,0,0],[1,1,1]] |
| J | J-shape | [[0,0,1],[1,1,1]] |
| S | S-shape | [[0,1,1],[1,1,0]] |
| Z | Z-shape | [[1,1,0],[0,1,1]] |
| I | I-shape (Line) | [[1,1,1,1]] |
The game validates moves before execution:
- Boundary checking (left, right, bottom walls)
- Collision with fixed pieces
- Rotation collision with wall kick fallback
- Initial Render:
initGrid()creates DOM elements - Update Render:
renderGrid()updates cell classes without recreating DOM - Efficient Updates: Only modifies cells that change state
- Single DOM creation on init
- Class-based updates instead of DOM recreation
- Minimal reflows through batched updates
- CSS animations for visual effects
requestAnimationFramefor game loop- Timestamp-based timing for consistent speed
- Grid state stored in JavaScript array
- DOM updated only on state changes
- Fixed elements styled with CSS classes
| Parameter | Value | Description |
|---|---|---|
ROWS |
20 | Grid height |
COLUMNS |
10 | Grid width |
dropInterval |
400ms | Piece drop speed |
scoreInc |
13 | Points per line |
- Open
index.htmlin a web browser - Click "Start" to begin the game
- Use arrow keys to move and rotate pieces
- Complete horizontal lines to score points
- Avoid stacking pieces to the top
- Press
Escapeto pause the game
| Requirement | Status | Notes |
|---|---|---|
| Pre-approved game type | ✅ | Tetris |
| Plain JavaScript/DOM | ✅ | No frameworks |
| No canvas library | ✅ | DOM-based rendering |
| requestAnimationFrame | ✅ | Used in game loop |
| Requirement | Status | Notes |
|---|---|---|
| 60 FPS target | ✅ | requestAnimationFrame implementation |
| Minimal layer usage | ✅ | Efficient DOM structure |
| Smooth animations | ✅ | CSS animations |
| Requirement | Status | Notes |
|---|---|---|
| Timer/Clock | ✅ | Elapsed time display |
| Score/Points | ✅ | Line clear scoring |
| Lives remaining | N/A for Tetris (single life) |
| Requirement | Status | Notes |
|---|---|---|
| Continue option | ✅ | Resume button |
| Restart option | ✅ | Restart button |
| Frame rate maintained | ✅ | Game loop pauses cleanly |
| Requirement | Status | Notes |
|---|---|---|
| Keyboard-only controls | ✅ | Arrow keys + Space + Escape |
| Smooth motion | ✅ | Immediate response |
| No key spamming required | ✅ | Single keypress actions |
- Basic HTML5 structure
- Game board container
- Script and stylesheet links
- Grid and cell styling
- Animation keyframes (drop, rotate)
- Menu styling (pause, start, game over)
- Responsive button styles
- Game state management
- Tetromino definitions and colors
- Grid initialization and rendering
- Movement and rotation logic
- Collision detection
- Line clearing mechanics
- Pause/Start/Game Over menus
- Game loop with timing
- Chrome (recommended)
- Firefox
- Safari
- Edge
- No piece preview (next piece display)
- No hold piece functionality
- No level progression (speed increase)
- No high score persistence
- No sound effects
- No ghost piece (drop preview)
- Add next piece preview
- Implement hold piece feature
- Add progressive difficulty (faster drops)
- Local storage for high scores
- Sound effects and music
- Ghost piece indicator
- Mobile touch controls
- Multiplayer mode
To verify 60 FPS performance:
- Open Chrome DevTools (F12)
- Go to Performance tab
- Record during gameplay
- Check for consistent frame timing (~16.67ms)
Alternatively:
- Open DevTools
- Press Ctrl+Shift+P
- Type "Show FPS"
- Monitor FPS counter during gameplay
This project is part of the Zone01 curriculum and is intended for educational purposes.
Developed as part of the Make Your Game project at Zone01 Oujda.
- Hamza Boutaleb - GitHub
- Yassine Omari - Co-developer
- Khalid El Amrani - Co-developer


