Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- <!DOCTYPE html>
- <html lang="fr">
- <head>
- <meta charset="UTF-8">
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
- <title>Tetris 3D Pro</title>
- <style>
- body {
- margin: 0;
- padding: 0;
- background: #000;
- color: #fff;
- font-family: Arial, sans-serif;
- overflow: hidden;
- }
- #gameContainer {
- position: relative;
- width: 100vw;
- height: 100vh;
- }
- .controls {
- position: absolute;
- top: 20px;
- right: 20px;
- background: rgba(0, 0, 0, 0.8);
- padding: 20px;
- border-radius: 10px;
- min-width: 250px;
- border: 2px solid #0ff;
- box-shadow: 0 0 20px rgba(0, 255, 255, 0.5);
- }
- .controls h3 {
- margin-top: 0;
- color: #0ff;
- text-shadow: 0 0 10px #0ff;
- }
- button {
- background: #0ff;
- color: #000;
- border: none;
- padding: 10px 15px;
- cursor: pointer;
- border-radius: 5px;
- font-weight: bold;
- margin: 5px 0;
- width: 100%;
- transition: all 0.3s;
- }
- button:hover {
- background: #fff;
- transform: scale(1.05);
- }
- .score-display {
- font-size: 20px;
- margin: 10px 0;
- color: #0ff;
- }
- .controls-info {
- background: rgba(51, 51, 51, 0.8);
- padding: 10px;
- border-radius: 5px;
- margin-top: 20px;
- font-size: 14px;
- }
- .controls-info kbd {
- background: #555;
- padding: 2px 5px;
- border-radius: 3px;
- margin: 0 2px;
- }
- #loadingScreen {
- position: absolute;
- top: 0;
- left: 0;
- width: 100%;
- height: 100%;
- background: #000;
- display: flex;
- flex-direction: column;
- justify-content: center;
- align-items: center;
- z-index: 1000;
- }
- .loader {
- border: 5px solid #333;
- border-top: 5px solid #0ff;
- border-radius: 50%;
- width: 50px;
- height: 50px;
- animation: spin 1s linear infinite;
- }
- @keyframes spin {
- 0% { transform: rotate(0deg); }
- 100% { transform: rotate(360deg); }
- }
- </style>
- <script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
- </head>
- <body>
- <div id="gameContainer">
- <div id="loadingScreen">
- <div class="loader"></div>
- <p>Chargement du jeu...</p>
- </div>
- <div class="controls">
- <h3>Tetris 3D Pro</h3>
- <div class="score-display">
- Score: <span id="score">0</span><br>
- Lignes: <span id="lines">0</span><br>
- Niveau: <span id="level">1</span>
- </div>
- <button onclick="togglePause()">Pause</button>
- <button onclick="resetGame()">Nouveau Jeu</button>
- <div class="controls-info">
- <strong>Contrôles:</strong><br>
- <kbd>←</kbd> <kbd>→</kbd> Déplacer<br>
- <kbd>↑</kbd> Rotation<br>
- <kbd>↓</kbd> Descente rapide<br>
- <kbd>Espace</kbd> Chute instantanée<br>
- <kbd>P</kbd> Pause
- </div>
- </div>
- </div>
- <script>
- // Configuration
- const COLS = 10;
- const ROWS = 20;
- const BLOCK_SIZE = 1;
- // Variables
- let scene, camera, renderer;
- let gameGroup;
- let board = [];
- let currentPiece = null;
- let score = 0;
- let lines = 0;
- let level = 1;
- let dropCounter = 0;
- let lastTime = 0;
- let paused = false;
- // Textures
- let textures = [];
- // Pièces Tetris
- const pieces = {
- I: {
- shape: [[1,1,1,1]],
- rotationStates: [
- [[1,1,1,1]],
- [[1],[1],[1],[1]],
- [[1,1,1,1]],
- [[1],[1],[1],[1]]
- ],
- color: 0x00ffff
- },
- O: {
- shape: [[1,1],[1,1]],
- rotationStates: [
- [[1,1],[1,1]],
- [[1,1],[1,1]],
- [[1,1],[1,1]],
- [[1,1],[1,1]]
- ],
- color: 0xffff00
- },
- T: {
- shape: [[0,1,0],[1,1,1]],
- rotationStates: [
- [[0,1,0],[1,1,1]],
- [[1,0],[1,1],[1,0]],
- [[1,1,1],[0,1,0]],
- [[0,1],[1,1],[0,1]]
- ],
- color: 0xff00ff
- },
- S: {
- shape: [[0,1,1],[1,1,0]],
- rotationStates: [
- [[0,1,1],[1,1,0]],
- [[1,0],[1,1],[0,1]],
- [[0,1,1],[1,1,0]],
- [[1,0],[1,1],[0,1]]
- ],
- color: 0x00ff00
- },
- Z: {
- shape: [[1,1,0],[0,1,1]],
- rotationStates: [
- [[1,1,0],[0,1,1]],
- [[0,1],[1,1],[1,0]],
- [[1,1,0],[0,1,1]],
- [[0,1],[1,1],[1,0]]
- ],
- color: 0xff0000
- },
- J: {
- shape: [[1,0,0],[1,1,1]],
- rotationStates: [
- [[1,0,0],[1,1,1]],
- [[1,1],[1,0],[1,0]],
- [[1,1,1],[0,0,1]],
- [[0,1],[0,1],[1,1]]
- ],
- color: 0x0000ff
- },
- L: {
- shape: [[0,0,1],[1,1,1]],
- rotationStates: [
- [[0,0,1],[1,1,1]],
- [[1,0],[1,0],[1,1]],
- [[1,1,1],[1,0,0]],
- [[1,1],[0,1],[0,1]]
- ],
- color: 0xffa500
- }
- };
- class TetrisPiece {
- constructor() {
- const types = 'IOTSZJL';
- this.type = types[Math.floor(Math.random() * types.length)];
- this.rotationState = 0;
- this.matrix = pieces[this.type].shape.map(row => [...row]);
- this.x = Math.floor((COLS - this.matrix[0].length) / 2);
- this.y = 0;
- this.mesh = new THREE.Group();
- this.blocks = [];
- this.pieceColor = pieces[this.type].color;
- this.pieceFaceIndices = this.generatePieceFaceIndices();
- this.createMesh();
- }
- generatePieceFaceIndices() {
- const maxBlocks = 9;
- const indices = [];
- for (let i = 0; i < maxBlocks; i++) {
- indices.push(Array(6).fill().map(() =>
- Math.floor(Math.random() * textures.length)
- ));
- }
- return indices;
- }
- createMesh() {
- this.mesh.clear();
- this.blocks = [];
- let blockIndex = 0;
- for (let y = 0; y < this.matrix.length; y++) {
- this.blocks[y] = [];
- for (let x = 0; x < this.matrix[y].length; x++) {
- if (this.matrix[y][x]) {
- const block = this.createCubeWithSpecificFaces(this.pieceFaceIndices[blockIndex]);
- block.position.set(x * BLOCK_SIZE, -y * BLOCK_SIZE, 0);
- this.mesh.add(block);
- this.blocks[y][x] = block;
- blockIndex++;
- }
- }
- }
- this.updatePosition();
- }
- createCubeWithSpecificFaces(faceIndices) {
- const geometry = new THREE.BoxGeometry(BLOCK_SIZE * 0.95, BLOCK_SIZE * 0.95, BLOCK_SIZE * 0.95);
- const materials = [];
- for (let i = 0; i < 6; i++) {
- materials.push(new THREE.MeshPhongMaterial({
- map: textures[faceIndices[i]],
- color: this.pieceColor,
- emissive: this.pieceColor,
- emissiveIntensity: 0.2
- }));
- }
- const cube = new THREE.Mesh(geometry, materials);
- const edges = new THREE.EdgesGeometry(geometry);
- const line = new THREE.LineSegments(edges, new THREE.LineBasicMaterial({ color: 0x000000 }));
- cube.add(line);
- return cube;
- }
- updatePosition() {
- this.mesh.position.set(
- (this.x - COLS/2 + 0.5) * BLOCK_SIZE,
- (ROWS/2 - this.y - 0.5) * BLOCK_SIZE,
- 0
- );
- }
- rotate() {
- const nextRotationState = (this.rotationState + 1) % 4;
- const nextMatrix = pieces[this.type].rotationStates[nextRotationState];
- const oldMatrix = this.matrix;
- const oldRotationState = this.rotationState;
- this.matrix = nextMatrix.map(row => [...row]);
- this.rotationState = nextRotationState;
- if (this.isValidPosition()) {
- this.createMesh();
- return true;
- }
- this.matrix = oldMatrix;
- this.rotationState = oldRotationState;
- return false;
- }
- isValidPosition(dx = 0, dy = 0) {
- for (let y = 0; y < this.matrix.length; y++) {
- for (let x = 0; x < this.matrix[y].length; x++) {
- if (this.matrix[y][x]) {
- const newX = this.x + x + dx;
- const newY = this.y + y + dy;
- if (newX < 0 || newX >= COLS || newY >= ROWS) {
- return false;
- }
- if (newY >= 0 && board[newY] && board[newY][newX]) {
- return false;
- }
- }
- }
- }
- return true;
- }
- move(dx, dy) {
- if (this.isValidPosition(dx, dy)) {
- this.x += dx;
- this.y += dy;
- this.updatePosition();
- return true;
- }
- return false;
- }
- }
- function init() {
- scene = new THREE.Scene();
- scene.background = new THREE.Color(0x000000);
- camera = new THREE.PerspectiveCamera(50, window.innerWidth / window.innerHeight, 0.1, 1000);
- camera.position.set(0, 0, 25);
- camera.lookAt(0, 0, 0);
- renderer = new THREE.WebGLRenderer({ antialias: true });
- renderer.setSize(window.innerWidth, window.innerHeight);
- document.getElementById('gameContainer').appendChild(renderer.domElement);
- const ambientLight = new THREE.AmbientLight(0xffffff, 0.6);
- scene.add(ambientLight);
- const directionalLight = new THREE.DirectionalLight(0xffffff, 0.8);
- directionalLight.position.set(10, 20, 10);
- scene.add(directionalLight);
- gameGroup = new THREE.Group();
- scene.add(gameGroup);
- createGameBoard();
- board = Array(ROWS).fill().map(() => Array(COLS).fill(null));
- loadTextures();
- window.addEventListener('resize', onWindowResize);
- document.addEventListener('keydown', onKeyDown);
- document.getElementById('loadingScreen').style.display = 'none';
- }
- function loadTextures() {
- // Créer 5 textures colorées
- for (let i = 0; i < 5; i++) {
- const canvas = document.createElement('canvas');
- canvas.width = 64;
- canvas.height = 64;
- const ctx = canvas.getContext('2d');
- const gradient = ctx.createLinearGradient(0, 0, 64, 64);
- gradient.addColorStop(0, `hsl(${i * 72}, 70%, 40%)`);
- gradient.addColorStop(1, `hsl(${i * 72}, 100%, 60%)`);
- ctx.fillStyle = gradient;
- ctx.fillRect(0, 0, 64, 64);
- ctx.fillStyle = '#fff';
- ctx.font = 'bold 32px Arial';
- ctx.textAlign = 'center';
- ctx.textBaseline = 'middle';
- ctx.fillText(i + 1, 32, 32);
- textures[i] = new THREE.CanvasTexture(canvas);
- }
- startGame();
- }
- function createGameBoard() {
- const borderMaterial = new THREE.MeshPhongMaterial({ color: 0x00ffff });
- const borderThickness = 0.2;
- const leftBorder = new THREE.Mesh(
- new THREE.BoxGeometry(borderThickness, ROWS * BLOCK_SIZE, 2),
- borderMaterial
- );
- leftBorder.position.x = -COLS * BLOCK_SIZE / 2 - borderThickness / 2;
- gameGroup.add(leftBorder);
- const rightBorder = new THREE.Mesh(
- new THREE.BoxGeometry(borderThickness, ROWS * BLOCK_SIZE, 2),
- borderMaterial
- );
- rightBorder.position.x = COLS * BLOCK_SIZE / 2 + borderThickness / 2;
- gameGroup.add(rightBorder);
- const bottomBorder = new THREE.Mesh(
- new THREE.BoxGeometry(COLS * BLOCK_SIZE + borderThickness * 2, borderThickness, 2),
- borderMaterial
- );
- bottomBorder.position.y = -ROWS * BLOCK_SIZE / 2 - borderThickness / 2;
- gameGroup.add(bottomBorder);
- }
- function startGame() {
- currentPiece = new TetrisPiece();
- gameGroup.add(currentPiece.mesh);
- animate();
- }
- function animate(time = 0) {
- requestAnimationFrame(animate);
- if (!paused) {
- const deltaTime = time - lastTime;
- lastTime = time;
- dropCounter += deltaTime;
- if (dropCounter > (1000 / level)) {
- dropPiece();
- dropCounter = 0;
- }
- }
- renderer.render(scene, camera);
- }
- function dropPiece() {
- if (!currentPiece) return;
- if (!currentPiece.move(0, 1)) {
- lockPiece();
- checkLines();
- spawnNewPiece();
- }
- }
- function lockPiece() {
- let blockIndex = 0;
- currentPiece.matrix.forEach((row, y) => {
- row.forEach((value, x) => {
- if (value) {
- const boardY = currentPiece.y + y;
- const boardX = currentPiece.x + x;
- if (boardY >= 0 && boardY < ROWS && boardX >= 0 && boardX < COLS) {
- const faceIndices = currentPiece.pieceFaceIndices[blockIndex];
- const block = currentPiece.createCubeWithSpecificFaces(faceIndices);
- block.position.set(
- (boardX - COLS/2 + 0.5) * BLOCK_SIZE,
- (ROWS/2 - boardY - 0.5) * BLOCK_SIZE,
- 0
- );
- board[boardY][boardX] = block;
- gameGroup.add(block);
- }
- blockIndex++;
- }
- });
- });
- gameGroup.remove(currentPiece.mesh);
- }
- function checkLines() {
- let linesCleared = 0;
- for (let y = ROWS - 1; y >= 0; y--) {
- let isComplete = true;
- for (let x = 0; x < COLS; x++) {
- if (!board[y][x]) {
- isComplete = false;
- break;
- }
- }
- if (isComplete) {
- for (let x = 0; x < COLS; x++) {
- if (board[y][x]) {
- gameGroup.remove(board[y][x]);
- }
- }
- for (let moveY = y - 1; moveY >= 0; moveY--) {
- for (let x = 0; x < COLS; x++) {
- if (board[moveY][x]) {
- board[moveY][x].position.y -= BLOCK_SIZE;
- board[moveY + 1][x] = board[moveY][x];
- } else {
- board[moveY + 1][x] = null;
- }
- }
- }
- for (let x = 0; x < COLS; x++) {
- board[0][x] = null;
- }
- linesCleared++;
- y++;
- }
- }
- if (linesCleared > 0) {
- lines += linesCleared;
- score += linesCleared * 100 * level;
- level = Math.floor(lines / 10) + 1;
- updateScore();
- }
- }
- function spawnNewPiece() {
- currentPiece = new TetrisPiece();
- if (!currentPiece.isValidPosition()) {
- gameGroup.remove(currentPiece.mesh);
- currentPiece = null;
- gameOver();
- return;
- }
- gameGroup.add(currentPiece.mesh);
- }
- function gameOver() {
- alert(`Game Over!\nScore: ${score}\nLignes: ${lines}`);
- resetGame();
- }
- function resetGame() {
- for (let y = 0; y < ROWS; y++) {
- for (let x = 0; x < COLS; x++) {
- if (board[y][x]) {
- gameGroup.remove(board[y][x]);
- board[y][x] = null;
- }
- }
- }
- board = Array(ROWS).fill().map(() => Array(COLS).fill(null));
- score = 0;
- lines = 0;
- level = 1;
- dropCounter = 0;
- updateScore();
- if (currentPiece && currentPiece.mesh) {
- gameGroup.remove(currentPiece.mesh);
- }
- currentPiece = null;
- spawnNewPiece();
- paused = false;
- }
- function updateScore() {
- document.getElementById('score').textContent = score;
- document.getElementById('lines').textContent = lines;
- document.getElementById('level').textContent = level;
- }
- function onKeyDown(event) {
- if (!currentPiece) return;
- if (paused && event.key !== 'p' && event.key !== 'P') return;
- switch(event.key) {
- case 'ArrowLeft':
- currentPiece.move(-1, 0);
- break;
- case 'ArrowRight':
- currentPiece.move(1, 0);
- break;
- case 'ArrowDown':
- if (currentPiece.move(0, 1)) {
- score++;
- updateScore();
- dropCounter = 0;
- }
- break;
- case 'ArrowUp':
- currentPiece.rotate();
- break;
- case ' ':
- while (currentPiece.move(0, 1)) {
- score += 2;
- }
- updateScore();
- dropCounter = 0;
- lockPiece();
- checkLines();
- spawnNewPiece();
- break;
- case 'p':
- case 'P':
- togglePause();
- break;
- }
- }
- function onWindowResize() {
- camera.aspect = window.innerWidth / window.innerHeight;
- camera.updateProjectionMatrix();
- renderer.setSize(window.innerWidth, window.innerHeight);
- }
- function togglePause() {
- paused = !paused;
- }
- window.addEventListener('load', () => {
- init();
- });
- </script>
- </body>
Advertisement
Add Comment
Please, Sign In to add comment