Guest User

Untitled

a guest
May 31st, 2025
27
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 22.08 KB | None | 0 0
  1. <!DOCTYPE html>
  2. <html lang="fr">
  3. <head>
  4.     <meta charset="UTF-8">
  5.     <meta name="viewport" content="width=device-width, initial-scale=1.0">
  6.     <title>Tetris 3D Pro</title>
  7.     <style>
  8.         body {
  9.             margin: 0;
  10.             padding: 0;
  11.             background: #000;
  12.             color: #fff;
  13.             font-family: Arial, sans-serif;
  14.             overflow: hidden;
  15.         }
  16.  
  17.         #gameContainer {
  18.             position: relative;
  19.             width: 100vw;
  20.             height: 100vh;
  21.         }
  22.  
  23.         .controls {
  24.             position: absolute;
  25.             top: 20px;
  26.             right: 20px;
  27.             background: rgba(0, 0, 0, 0.8);
  28.             padding: 20px;
  29.             border-radius: 10px;
  30.             min-width: 250px;
  31.             border: 2px solid #0ff;
  32.             box-shadow: 0 0 20px rgba(0, 255, 255, 0.5);
  33.         }
  34.  
  35.         .controls h3 {
  36.             margin-top: 0;
  37.             color: #0ff;
  38.             text-shadow: 0 0 10px #0ff;
  39.         }
  40.  
  41.         button {
  42.             background: #0ff;
  43.             color: #000;
  44.             border: none;
  45.             padding: 10px 15px;
  46.             cursor: pointer;
  47.             border-radius: 5px;
  48.             font-weight: bold;
  49.             margin: 5px 0;
  50.             width: 100%;
  51.             transition: all 0.3s;
  52.         }
  53.  
  54.         button:hover {
  55.             background: #fff;
  56.             transform: scale(1.05);
  57.         }
  58.  
  59.         .score-display {
  60.             font-size: 20px;
  61.             margin: 10px 0;
  62.             color: #0ff;
  63.         }
  64.  
  65.         .controls-info {
  66.             background: rgba(51, 51, 51, 0.8);
  67.             padding: 10px;
  68.             border-radius: 5px;
  69.             margin-top: 20px;
  70.             font-size: 14px;
  71.         }
  72.  
  73.         .controls-info kbd {
  74.             background: #555;
  75.             padding: 2px 5px;
  76.             border-radius: 3px;
  77.             margin: 0 2px;
  78.         }
  79.  
  80.         #loadingScreen {
  81.             position: absolute;
  82.             top: 0;
  83.             left: 0;
  84.             width: 100%;
  85.             height: 100%;
  86.             background: #000;
  87.             display: flex;
  88.             flex-direction: column;
  89.             justify-content: center;
  90.             align-items: center;
  91.             z-index: 1000;
  92.         }
  93.  
  94.         .loader {
  95.             border: 5px solid #333;
  96.             border-top: 5px solid #0ff;
  97.             border-radius: 50%;
  98.             width: 50px;
  99.             height: 50px;
  100.             animation: spin 1s linear infinite;
  101.         }
  102.  
  103.         @keyframes spin {
  104.             0% { transform: rotate(0deg); }
  105.             100% { transform: rotate(360deg); }
  106.         }
  107.     </style>
  108.     <script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
  109. </head>
  110. <body>
  111.     <div id="gameContainer">
  112.         <div id="loadingScreen">
  113.             <div class="loader"></div>
  114.             <p>Chargement du jeu...</p>
  115.         </div>
  116.        
  117.         <div class="controls">
  118.             <h3>Tetris 3D Pro</h3>
  119.             <div class="score-display">
  120.                 Score: <span id="score">0</span><br>
  121.                 Lignes: <span id="lines">0</span><br>
  122.                 Niveau: <span id="level">1</span>
  123.             </div>
  124.            
  125.             <button onclick="togglePause()">Pause</button>
  126.             <button onclick="resetGame()">Nouveau Jeu</button>
  127.            
  128.             <div class="controls-info">
  129.                 <strong>Contrôles:</strong><br>
  130.                 <kbd></kbd> <kbd></kbd> Déplacer<br>
  131.                 <kbd></kbd> Rotation<br>
  132.                 <kbd></kbd> Descente rapide<br>
  133.                 <kbd>Espace</kbd> Chute instantanée<br>
  134.                 <kbd>P</kbd> Pause
  135.             </div>
  136.         </div>
  137.     </div>
  138.  
  139.     <script>
  140.         // Configuration
  141.         const COLS = 10;
  142.         const ROWS = 20;
  143.         const BLOCK_SIZE = 1;
  144.        
  145.         // Variables
  146.         let scene, camera, renderer;
  147.         let gameGroup;
  148.         let board = [];
  149.         let currentPiece = null;
  150.         let score = 0;
  151.         let lines = 0;
  152.         let level = 1;
  153.         let dropCounter = 0;
  154.         let lastTime = 0;
  155.         let paused = false;
  156.        
  157.         // Textures
  158.         let textures = [];
  159.        
  160.         // Pièces Tetris
  161.         const pieces = {
  162.             I: {
  163.                 shape: [[1,1,1,1]],
  164.                 rotationStates: [
  165.                     [[1,1,1,1]],
  166.                     [[1],[1],[1],[1]],
  167.                     [[1,1,1,1]],
  168.                     [[1],[1],[1],[1]]
  169.                 ],
  170.                 color: 0x00ffff
  171.             },
  172.             O: {
  173.                 shape: [[1,1],[1,1]],
  174.                 rotationStates: [
  175.                     [[1,1],[1,1]],
  176.                     [[1,1],[1,1]],
  177.                     [[1,1],[1,1]],
  178.                     [[1,1],[1,1]]
  179.                 ],
  180.                 color: 0xffff00
  181.             },
  182.             T: {
  183.                 shape: [[0,1,0],[1,1,1]],
  184.                 rotationStates: [
  185.                     [[0,1,0],[1,1,1]],
  186.                     [[1,0],[1,1],[1,0]],
  187.                     [[1,1,1],[0,1,0]],
  188.                     [[0,1],[1,1],[0,1]]
  189.                 ],
  190.                 color: 0xff00ff
  191.             },
  192.             S: {
  193.                 shape: [[0,1,1],[1,1,0]],
  194.                 rotationStates: [
  195.                     [[0,1,1],[1,1,0]],
  196.                     [[1,0],[1,1],[0,1]],
  197.                     [[0,1,1],[1,1,0]],
  198.                     [[1,0],[1,1],[0,1]]
  199.                 ],
  200.                 color: 0x00ff00
  201.             },
  202.             Z: {
  203.                 shape: [[1,1,0],[0,1,1]],
  204.                 rotationStates: [
  205.                     [[1,1,0],[0,1,1]],
  206.                     [[0,1],[1,1],[1,0]],
  207.                     [[1,1,0],[0,1,1]],
  208.                     [[0,1],[1,1],[1,0]]
  209.                 ],
  210.                 color: 0xff0000
  211.             },
  212.             J: {
  213.                 shape: [[1,0,0],[1,1,1]],
  214.                 rotationStates: [
  215.                     [[1,0,0],[1,1,1]],
  216.                     [[1,1],[1,0],[1,0]],
  217.                     [[1,1,1],[0,0,1]],
  218.                     [[0,1],[0,1],[1,1]]
  219.                 ],
  220.                 color: 0x0000ff
  221.             },
  222.             L: {
  223.                 shape: [[0,0,1],[1,1,1]],
  224.                 rotationStates: [
  225.                     [[0,0,1],[1,1,1]],
  226.                     [[1,0],[1,0],[1,1]],
  227.                     [[1,1,1],[1,0,0]],
  228.                     [[1,1],[0,1],[0,1]]
  229.                 ],
  230.                 color: 0xffa500
  231.             }
  232.         };
  233.        
  234.         class TetrisPiece {
  235.             constructor() {
  236.                 const types = 'IOTSZJL';
  237.                 this.type = types[Math.floor(Math.random() * types.length)];
  238.                 this.rotationState = 0;
  239.                 this.matrix = pieces[this.type].shape.map(row => [...row]);
  240.                 this.x = Math.floor((COLS - this.matrix[0].length) / 2);
  241.                 this.y = 0;
  242.                 this.mesh = new THREE.Group();
  243.                 this.blocks = [];
  244.                 this.pieceColor = pieces[this.type].color;
  245.                 this.pieceFaceIndices = this.generatePieceFaceIndices();
  246.                 this.createMesh();
  247.             }
  248.            
  249.             generatePieceFaceIndices() {
  250.                 const maxBlocks = 9;
  251.                 const indices = [];
  252.                 for (let i = 0; i < maxBlocks; i++) {
  253.                     indices.push(Array(6).fill().map(() =>
  254.                         Math.floor(Math.random() * textures.length)
  255.                     ));
  256.                 }
  257.                 return indices;
  258.             }
  259.            
  260.             createMesh() {
  261.                 this.mesh.clear();
  262.                 this.blocks = [];
  263.                
  264.                 let blockIndex = 0;
  265.                 for (let y = 0; y < this.matrix.length; y++) {
  266.                     this.blocks[y] = [];
  267.                     for (let x = 0; x < this.matrix[y].length; x++) {
  268.                         if (this.matrix[y][x]) {
  269.                             const block = this.createCubeWithSpecificFaces(this.pieceFaceIndices[blockIndex]);
  270.                             block.position.set(x * BLOCK_SIZE, -y * BLOCK_SIZE, 0);
  271.                             this.mesh.add(block);
  272.                             this.blocks[y][x] = block;
  273.                             blockIndex++;
  274.                         }
  275.                     }
  276.                 }
  277.                
  278.                 this.updatePosition();
  279.             }
  280.            
  281.             createCubeWithSpecificFaces(faceIndices) {
  282.                 const geometry = new THREE.BoxGeometry(BLOCK_SIZE * 0.95, BLOCK_SIZE * 0.95, BLOCK_SIZE * 0.95);
  283.                 const materials = [];
  284.                
  285.                 for (let i = 0; i < 6; i++) {
  286.                     materials.push(new THREE.MeshPhongMaterial({
  287.                         map: textures[faceIndices[i]],
  288.                         color: this.pieceColor,
  289.                         emissive: this.pieceColor,
  290.                         emissiveIntensity: 0.2
  291.                     }));
  292.                 }
  293.                
  294.                 const cube = new THREE.Mesh(geometry, materials);
  295.                
  296.                 const edges = new THREE.EdgesGeometry(geometry);
  297.                 const line = new THREE.LineSegments(edges, new THREE.LineBasicMaterial({ color: 0x000000 }));
  298.                 cube.add(line);
  299.                
  300.                 return cube;
  301.             }
  302.            
  303.             updatePosition() {
  304.                 this.mesh.position.set(
  305.                     (this.x - COLS/2 + 0.5) * BLOCK_SIZE,
  306.                     (ROWS/2 - this.y - 0.5) * BLOCK_SIZE,
  307.                     0
  308.                 );
  309.             }
  310.            
  311.             rotate() {
  312.                 const nextRotationState = (this.rotationState + 1) % 4;
  313.                 const nextMatrix = pieces[this.type].rotationStates[nextRotationState];
  314.                
  315.                 const oldMatrix = this.matrix;
  316.                 const oldRotationState = this.rotationState;
  317.                
  318.                 this.matrix = nextMatrix.map(row => [...row]);
  319.                 this.rotationState = nextRotationState;
  320.                
  321.                 if (this.isValidPosition()) {
  322.                     this.createMesh();
  323.                     return true;
  324.                 }
  325.                
  326.                 this.matrix = oldMatrix;
  327.                 this.rotationState = oldRotationState;
  328.                 return false;
  329.             }
  330.            
  331.             isValidPosition(dx = 0, dy = 0) {
  332.                 for (let y = 0; y < this.matrix.length; y++) {
  333.                     for (let x = 0; x < this.matrix[y].length; x++) {
  334.                         if (this.matrix[y][x]) {
  335.                             const newX = this.x + x + dx;
  336.                             const newY = this.y + y + dy;
  337.                            
  338.                             if (newX < 0 || newX >= COLS || newY >= ROWS) {
  339.                                 return false;
  340.                             }
  341.                            
  342.                             if (newY >= 0 && board[newY] && board[newY][newX]) {
  343.                                 return false;
  344.                             }
  345.                         }
  346.                     }
  347.                 }
  348.                 return true;
  349.             }
  350.            
  351.             move(dx, dy) {
  352.                 if (this.isValidPosition(dx, dy)) {
  353.                     this.x += dx;
  354.                     this.y += dy;
  355.                     this.updatePosition();
  356.                     return true;
  357.                 }
  358.                 return false;
  359.             }
  360.         }
  361.        
  362.         function init() {
  363.             scene = new THREE.Scene();
  364.             scene.background = new THREE.Color(0x000000);
  365.            
  366.             camera = new THREE.PerspectiveCamera(50, window.innerWidth / window.innerHeight, 0.1, 1000);
  367.             camera.position.set(0, 0, 25);
  368.             camera.lookAt(0, 0, 0);
  369.            
  370.             renderer = new THREE.WebGLRenderer({ antialias: true });
  371.             renderer.setSize(window.innerWidth, window.innerHeight);
  372.             document.getElementById('gameContainer').appendChild(renderer.domElement);
  373.            
  374.             const ambientLight = new THREE.AmbientLight(0xffffff, 0.6);
  375.             scene.add(ambientLight);
  376.            
  377.             const directionalLight = new THREE.DirectionalLight(0xffffff, 0.8);
  378.             directionalLight.position.set(10, 20, 10);
  379.             scene.add(directionalLight);
  380.            
  381.             gameGroup = new THREE.Group();
  382.             scene.add(gameGroup);
  383.            
  384.             createGameBoard();
  385.             board = Array(ROWS).fill().map(() => Array(COLS).fill(null));
  386.            
  387.             loadTextures();
  388.            
  389.             window.addEventListener('resize', onWindowResize);
  390.             document.addEventListener('keydown', onKeyDown);
  391.            
  392.             document.getElementById('loadingScreen').style.display = 'none';
  393.         }
  394.        
  395.         function loadTextures() {
  396.             // Créer 5 textures colorées
  397.             for (let i = 0; i < 5; i++) {
  398.                 const canvas = document.createElement('canvas');
  399.                 canvas.width = 64;
  400.                 canvas.height = 64;
  401.                 const ctx = canvas.getContext('2d');
  402.                
  403.                 const gradient = ctx.createLinearGradient(0, 0, 64, 64);
  404.                 gradient.addColorStop(0, `hsl(${i * 72}, 70%, 40%)`);
  405.                 gradient.addColorStop(1, `hsl(${i * 72}, 100%, 60%)`);
  406.                
  407.                 ctx.fillStyle = gradient;
  408.                 ctx.fillRect(0, 0, 64, 64);
  409.                
  410.                 ctx.fillStyle = '#fff';
  411.                 ctx.font = 'bold 32px Arial';
  412.                 ctx.textAlign = 'center';
  413.                 ctx.textBaseline = 'middle';
  414.                 ctx.fillText(i + 1, 32, 32);
  415.                
  416.                 textures[i] = new THREE.CanvasTexture(canvas);
  417.             }
  418.            
  419.             startGame();
  420.         }
  421.        
  422.         function createGameBoard() {
  423.             const borderMaterial = new THREE.MeshPhongMaterial({ color: 0x00ffff });
  424.             const borderThickness = 0.2;
  425.            
  426.             const leftBorder = new THREE.Mesh(
  427.                 new THREE.BoxGeometry(borderThickness, ROWS * BLOCK_SIZE, 2),
  428.                 borderMaterial
  429.             );
  430.             leftBorder.position.x = -COLS * BLOCK_SIZE / 2 - borderThickness / 2;
  431.             gameGroup.add(leftBorder);
  432.            
  433.             const rightBorder = new THREE.Mesh(
  434.                 new THREE.BoxGeometry(borderThickness, ROWS * BLOCK_SIZE, 2),
  435.                 borderMaterial
  436.             );
  437.             rightBorder.position.x = COLS * BLOCK_SIZE / 2 + borderThickness / 2;
  438.             gameGroup.add(rightBorder);
  439.            
  440.             const bottomBorder = new THREE.Mesh(
  441.                 new THREE.BoxGeometry(COLS * BLOCK_SIZE + borderThickness * 2, borderThickness, 2),
  442.                 borderMaterial
  443.             );
  444.             bottomBorder.position.y = -ROWS * BLOCK_SIZE / 2 - borderThickness / 2;
  445.             gameGroup.add(bottomBorder);
  446.         }
  447.        
  448.         function startGame() {
  449.             currentPiece = new TetrisPiece();
  450.             gameGroup.add(currentPiece.mesh);
  451.             animate();
  452.         }
  453.        
  454.         function animate(time = 0) {
  455.             requestAnimationFrame(animate);
  456.            
  457.             if (!paused) {
  458.                 const deltaTime = time - lastTime;
  459.                 lastTime = time;
  460.                
  461.                 dropCounter += deltaTime;
  462.                 if (dropCounter > (1000 / level)) {
  463.                     dropPiece();
  464.                     dropCounter = 0;
  465.                 }
  466.             }
  467.            
  468.             renderer.render(scene, camera);
  469.         }
  470.        
  471.         function dropPiece() {
  472.             if (!currentPiece) return;
  473.            
  474.             if (!currentPiece.move(0, 1)) {
  475.                 lockPiece();
  476.                 checkLines();
  477.                 spawnNewPiece();
  478.             }
  479.         }
  480.        
  481.         function lockPiece() {
  482.             let blockIndex = 0;
  483.             currentPiece.matrix.forEach((row, y) => {
  484.                 row.forEach((value, x) => {
  485.                     if (value) {
  486.                         const boardY = currentPiece.y + y;
  487.                         const boardX = currentPiece.x + x;
  488.                         if (boardY >= 0 && boardY < ROWS && boardX >= 0 && boardX < COLS) {
  489.                             const faceIndices = currentPiece.pieceFaceIndices[blockIndex];
  490.                             const block = currentPiece.createCubeWithSpecificFaces(faceIndices);
  491.                             block.position.set(
  492.                                 (boardX - COLS/2 + 0.5) * BLOCK_SIZE,
  493.                                 (ROWS/2 - boardY - 0.5) * BLOCK_SIZE,
  494.                                 0
  495.                             );
  496.                             board[boardY][boardX] = block;
  497.                             gameGroup.add(block);
  498.                         }
  499.                         blockIndex++;
  500.                     }
  501.                 });
  502.             });
  503.            
  504.             gameGroup.remove(currentPiece.mesh);
  505.         }
  506.        
  507.         function checkLines() {
  508.             let linesCleared = 0;
  509.            
  510.             for (let y = ROWS - 1; y >= 0; y--) {
  511.                 let isComplete = true;
  512.                
  513.                 for (let x = 0; x < COLS; x++) {
  514.                     if (!board[y][x]) {
  515.                         isComplete = false;
  516.                         break;
  517.                     }
  518.                 }
  519.                
  520.                 if (isComplete) {
  521.                     for (let x = 0; x < COLS; x++) {
  522.                         if (board[y][x]) {
  523.                             gameGroup.remove(board[y][x]);
  524.                         }
  525.                     }
  526.                    
  527.                     for (let moveY = y - 1; moveY >= 0; moveY--) {
  528.                         for (let x = 0; x < COLS; x++) {
  529.                             if (board[moveY][x]) {
  530.                                 board[moveY][x].position.y -= BLOCK_SIZE;
  531.                                 board[moveY + 1][x] = board[moveY][x];
  532.                             } else {
  533.                                 board[moveY + 1][x] = null;
  534.                             }
  535.                         }
  536.                     }
  537.                    
  538.                     for (let x = 0; x < COLS; x++) {
  539.                         board[0][x] = null;
  540.                     }
  541.                    
  542.                     linesCleared++;
  543.                     y++;
  544.                 }
  545.             }
  546.            
  547.             if (linesCleared > 0) {
  548.                 lines += linesCleared;
  549.                 score += linesCleared * 100 * level;
  550.                 level = Math.floor(lines / 10) + 1;
  551.                 updateScore();
  552.             }
  553.         }
  554.        
  555.         function spawnNewPiece() {
  556.             currentPiece = new TetrisPiece();
  557.            
  558.             if (!currentPiece.isValidPosition()) {
  559.                 gameGroup.remove(currentPiece.mesh);
  560.                 currentPiece = null;
  561.                 gameOver();
  562.                 return;
  563.             }
  564.            
  565.             gameGroup.add(currentPiece.mesh);
  566.         }
  567.        
  568.         function gameOver() {
  569.             alert(`Game Over!\nScore: ${score}\nLignes: ${lines}`);
  570.             resetGame();
  571.         }
  572.        
  573.         function resetGame() {
  574.             for (let y = 0; y < ROWS; y++) {
  575.                 for (let x = 0; x < COLS; x++) {
  576.                     if (board[y][x]) {
  577.                         gameGroup.remove(board[y][x]);
  578.                         board[y][x] = null;
  579.                     }
  580.                 }
  581.             }
  582.            
  583.             board = Array(ROWS).fill().map(() => Array(COLS).fill(null));
  584.             score = 0;
  585.             lines = 0;
  586.             level = 1;
  587.             dropCounter = 0;
  588.             updateScore();
  589.            
  590.             if (currentPiece && currentPiece.mesh) {
  591.                 gameGroup.remove(currentPiece.mesh);
  592.             }
  593.            
  594.             currentPiece = null;
  595.             spawnNewPiece();
  596.             paused = false;
  597.         }
  598.        
  599.         function updateScore() {
  600.             document.getElementById('score').textContent = score;
  601.             document.getElementById('lines').textContent = lines;
  602.             document.getElementById('level').textContent = level;
  603.         }
  604.        
  605.         function onKeyDown(event) {
  606.             if (!currentPiece) return;
  607.             if (paused && event.key !== 'p' && event.key !== 'P') return;
  608.            
  609.             switch(event.key) {
  610.                 case 'ArrowLeft':
  611.                     currentPiece.move(-1, 0);
  612.                     break;
  613.                 case 'ArrowRight':
  614.                     currentPiece.move(1, 0);
  615.                     break;
  616.                 case 'ArrowDown':
  617.                     if (currentPiece.move(0, 1)) {
  618.                         score++;
  619.                         updateScore();
  620.                         dropCounter = 0;
  621.                     }
  622.                     break;
  623.                 case 'ArrowUp':
  624.                     currentPiece.rotate();
  625.                     break;
  626.                 case ' ':
  627.                     while (currentPiece.move(0, 1)) {
  628.                         score += 2;
  629.                     }
  630.                     updateScore();
  631.                     dropCounter = 0;
  632.                     lockPiece();
  633.                     checkLines();
  634.                     spawnNewPiece();
  635.                     break;
  636.                 case 'p':
  637.                 case 'P':
  638.                     togglePause();
  639.                     break;
  640.             }
  641.         }
  642.        
  643.         function onWindowResize() {
  644.             camera.aspect = window.innerWidth / window.innerHeight;
  645.             camera.updateProjectionMatrix();
  646.             renderer.setSize(window.innerWidth, window.innerHeight);
  647.         }
  648.        
  649.         function togglePause() {
  650.             paused = !paused;
  651.         }
  652.        
  653.         window.addEventListener('load', () => {
  654.             init();
  655.         });
  656.     </script>
  657. </body>
Advertisement
Add Comment
Please, Sign In to add comment