commit def6d56662e2ba0afb78ab071db1fa3fe04c1d48
Author: root <root@hub.scroll.pub>
Date: 2024-12-28 12:19:23 +0000
Subject: Initial commit
diff --git a/body.html b/body.html
new file mode 100644
index 0000000..49160a4
--- /dev/null
+++ b/body.html
@@ -0,0 +1,17 @@
+<main>
+ <h1>Tetris</h1>
+ <div class="game-container">
+ <div class="grid"></div>
+ <div class="sidebar">
+ <div class="next-piece">
+ <h2>Next</h2>
+ <div class="mini-grid"></div>
+ </div>
+ <div class="score">
+ <h2>Score</h2>
+ <p>0</p>
+ </div>
+ <button class="start-button">Start/Pause</button>
+ </div>
+ </div>
+</main>
\ No newline at end of file
diff --git a/index.scroll b/index.scroll
new file mode 100644
index 0000000..5111d3e
--- /dev/null
+++ b/index.scroll
@@ -0,0 +1,8 @@
+buildHtml
+baseUrl https://tetris.scroll.pub
+metaTags
+editButton /edit.html
+title Tetris Game - Classic Puzzle Fun
+style.css
+body.html
+script.js
\ No newline at end of file
diff --git a/prompt.json b/prompt.json
new file mode 100644
index 0000000..db7e888
--- /dev/null
+++ b/prompt.json
@@ -0,0 +1,25 @@
+{
+ "id": "af4c76fe-b4f7-4889-8273-b842c970abbf",
+ "object": "chat.completion",
+ "created": 1735388332,
+ "model": "deepseek-chat",
+ "choices": [
+ {
+ "index": 0,
+ "message": {
+ "role": "assistant",
+ "content": "---domain---\ntetris.scroll.pub\n---index.scroll---\nbuildHtml\nbaseUrl https://tetris.scroll.pub\nmetaTags\neditButton /edit.html\ntitle Tetris Game - Classic Puzzle Fun\nstyle.css\nbody.html\nscript.js\n---body.html---\n<main>\n <h1>Tetris</h1>\n <div class=\"game-container\">\n <div class=\"grid\"></div>\n <div class=\"sidebar\">\n <div class=\"next-piece\">\n <h2>Next</h2>\n <div class=\"mini-grid\"></div>\n </div>\n <div class=\"score\">\n <h2>Score</h2>\n <p>0</p>\n </div>\n <button class=\"start-button\">Start/Pause</button>\n </div>\n </div>\n</main>\n---style.css---\n:root {\n --primary: #2c3e50;\n --secondary: #34495e;\n --accent: #e74c3c;\n --text: #ecf0f1;\n}\n\n* {\n margin: 0;\n padding: 0;\n box-sizing: border-box;\n}\n\nbody {\n font-family: 'Arial', sans-serif;\n background: var(--primary);\n color: var(--text);\n min-height: 100vh;\n display: flex;\n justify-content: center;\n align-items: center;\n}\n\nh1 {\n text-align: center;\n margin-bottom: 2rem;\n font-size: 3rem;\n color: var(--accent);\n}\n\n.game-container {\n display: flex;\n gap: 2rem;\n}\n\n.grid, .mini-grid {\n display: grid;\n background: var(--secondary);\n border: 2px solid var(--accent);\n}\n\n.grid {\n grid-template-rows: repeat(20, 20px);\n grid-template-columns: repeat(10, 20px);\n}\n\n.mini-grid {\n grid-template-rows: repeat(4, 20px);\n grid-template-columns: repeat(4, 20px);\n margin-top: 1rem;\n}\n\n.sidebar {\n display: flex;\n flex-direction: column;\n gap: 2rem;\n}\n\n.score {\n text-align: center;\n}\n\n.start-button {\n padding: 0.5rem 1rem;\n background: var(--accent);\n color: var(--text);\n border: none;\n border-radius: 4px;\n cursor: pointer;\n font-size: 1rem;\n transition: background 0.3s;\n}\n\n.start-button:hover {\n background: #c0392b;\n}\n\n@media (max-width: 600px) {\n .game-container {\n flex-direction: column;\n align-items: center;\n }\n}\n---script.js---\nconst grid = document.querySelector('.grid');\nconst miniGrid = document.querySelector('.mini-grid');\nconst scoreDisplay = document.querySelector('.score p');\nconst startButton = document.querySelector('.start-button');\nconst width = 10;\nlet squares = Array.from(grid.querySelectorAll('div'));\nlet miniSquares = Array.from(miniGrid.querySelectorAll('div'));\nlet nextRandom = 0;\nlet timerId;\nlet score = 0;\nlet isPaused = false;\n\nconst colors = [\n '#e74c3c', // red\n '#3498db', // blue\n '#2ecc71', // green\n '#9b59b6', // purple\n '#f1c40f' // yellow\n];\n\nconst lTetromino = [\n [1, width+1, width*2+1, 2],\n [width, width+1, width+2, width*2+2],\n [1, width+1, width*2+1, width*2],\n [width, width*2, width*2+1, width*2+2]\n];\n\nconst zTetromino = [\n [0, width, width+1, width*2+1],\n [width+1, width+2, width*2, width*2+1],\n [0, width, width+1, width*2+1],\n [width+1, width+2, width*2, width*2+1]\n];\n\nconst tTetromino = [\n [1, width, width+1, width+2],\n [1, width+1, width+2, width*2+1],\n [width, width+1, width+2, width*2+1],\n [1, width, width+1, width*2+1]\n];\n\nconst oTetromino = [\n [0, 1, width, width+1],\n [0, 1, width, width+1],\n [0, 1, width, width+1],\n [0, 1, width, width+1]\n];\n\nconst iTetromino = [\n [1, width+1, width*2+1, width*3+1],\n [width, width+1, width+2, width+3],\n [1, width+1, width*2+1, width*3+1],\n [width, width+1, width+2, width+3]\n];\n\nconst theTetrominoes = [lTetromino, zTetromino, tTetromino, oTetromino, iTetromino];\n\nlet currentPosition = 4;\nlet currentRotation = 0;\nlet random = Math.floor(Math.random() * theTetrominoes.length);\nlet current = theTetrominoes[random][currentRotation];\n\nfunction draw() {\n current.forEach(index => {\n squares[currentPosition + index].classList.add('tetromino');\n squares[currentPosition + index].style.backgroundColor = colors[random];\n });\n}\n\nfunction undraw() {\n current.forEach(index => {\n squares[currentPosition + index].classList.remove('tetromino');\n squares[currentPosition + index].style.backgroundColor = '';\n });\n}\n\nfunction control(e) {\n if (isPaused) return;\n \n if (e.keyCode === 37) {\n moveLeft();\n } else if (e.keyCode === 38) {\n rotate();\n } else if (e.keyCode === 39) {\n moveRight();\n } else if (e.keyCode === 40) {\n moveDown();\n }\n}\n\ndocument.addEventListener('keydown', control);\n\nfunction moveDown() {\n undraw();\n currentPosition += width;\n draw();\n freeze();\n}\n\nfunction freeze() {\n if (current.some(index => squares[currentPosition + index + width].classList.contains('taken'))) {\n current.forEach(index => squares[currentPosition + index].classList.add('taken'));\n random = nextRandom;\n nextRandom = Math.floor(Math.random() * theTetrominoes.length);\n current = theTetrominoes[random][currentRotation];\n currentPosition = 4;\n draw();\n displayShape();\n addScore();\n gameOver();\n }\n}\n\nfunction moveLeft() {\n undraw();\n const isAtLeftEdge = current.some(index => (currentPosition + index) % width === 0);\n \n if (!isAtLeftEdge) currentPosition -= 1;\n \n if (current.some(index => squares[currentPosition + index].classList.contains('taken'))) {\n currentPosition += 1;\n }\n \n draw();\n}\n\nfunction moveRight() {\n undraw();\n const isAtRightEdge = current.some(index => (currentPosition + index) % width === width - 1);\n \n if (!isAtRightEdge) currentPosition += 1;\n \n if (current.some(index => squares[currentPosition + index].classList.contains('taken'))) {\n currentPosition -= 1;\n }\n \n draw();\n}\n\nfunction rotate() {\n undraw();\n currentRotation++;\n if (currentRotation === current.length) {\n currentRotation = 0;\n }\n current = theTetrominoes[random][currentRotation];\n draw();\n}\n\nfunction displayShape() {\n miniSquares.forEach(square => {\n square.classList.remove('tetromino');\n square.style.backgroundColor = '';\n });\n \n theTetrominoes[nextRandom][0].forEach(index => {\n miniSquares[index].classList.add('tetromino');\n miniSquares[index].style.backgroundColor = colors[nextRandom];\n });\n}\n\nstartButton.addEventListener('click', () => {\n if (timerId) {\n clearInterval(timerId);\n timerId = null;\n isPaused = true;\n startButton.textContent = 'Start';\n } else {\n draw();\n timerId = setInterval(moveDown, 1000);\n isPaused = false;\n startButton.textContent = 'Pause';\n }\n});\n\nfunction addScore() {\n for (let i = 0; i < 199; i += width) {\n const row = [i, i+1, i+2, i+3, i+4, i+5, i+6, i+7, i+8, i+9];\n \n if (row.every(index => squares[index].classList.contains('taken'))) {\n score += 10;\n scoreDisplay.textContent = score;\n row.forEach(index => {\n squares[index].classList.remove('taken');\n squares[index].classList.remove('tetromino');\n squares[index].style.backgroundColor = '';\n });\n \n const squaresRemoved = squares.splice(i, width);\n squares = squaresRemoved.concat(squares);\n squares.forEach(cell => grid.appendChild(cell));\n }\n }\n}\n\nfunction gameOver() {\n if (current.some(index => squares[currentPosition + index].classList.contains('taken'))) {\n scoreDisplay.textContent = 'end';\n clearInterval(timerId);\n isPaused = true;\n }\n}\n---end---"
+ },
+ "logprobs": null,
+ "finish_reason": "stop"
+ }
+ ],
+ "usage": {
+ "prompt_tokens": 240,
+ "completion_tokens": 2142,
+ "total_tokens": 2382,
+ "prompt_cache_hit_tokens": 192,
+ "prompt_cache_miss_tokens": 48
+ },
+ "system_fingerprint": "fp_f1afce2943"
+}
\ No newline at end of file
diff --git a/readme.scroll b/readme.scroll
new file mode 100644
index 0000000..bd6271b
--- /dev/null
+++ b/readme.scroll
@@ -0,0 +1,2 @@
+# tetris.scroll.pub
+Website generated by DeepSeek from prompt: creat a tetris game
\ No newline at end of file
diff --git a/script.js b/script.js
new file mode 100644
index 0000000..d2e2dd7
--- /dev/null
+++ b/script.js
@@ -0,0 +1,202 @@
+const grid = document.querySelector('.grid');
+const miniGrid = document.querySelector('.mini-grid');
+const scoreDisplay = document.querySelector('.score p');
+const startButton = document.querySelector('.start-button');
+const width = 10;
+let squares = Array.from(grid.querySelectorAll('div'));
+let miniSquares = Array.from(miniGrid.querySelectorAll('div'));
+let nextRandom = 0;
+let timerId;
+let score = 0;
+let isPaused = false;
+
+const colors = [
+ '#e74c3c', // red
+ '#3498db', // blue
+ '#2ecc71', // green
+ '#9b59b6', // purple
+ '#f1c40f' // yellow
+];
+
+const lTetromino = [
+ [1, width+1, width*2+1, 2],
+ [width, width+1, width+2, width*2+2],
+ [1, width+1, width*2+1, width*2],
+ [width, width*2, width*2+1, width*2+2]
+];
+
+const zTetromino = [
+ [0, width, width+1, width*2+1],
+ [width+1, width+2, width*2, width*2+1],
+ [0, width, width+1, width*2+1],
+ [width+1, width+2, width*2, width*2+1]
+];
+
+const tTetromino = [
+ [1, width, width+1, width+2],
+ [1, width+1, width+2, width*2+1],
+ [width, width+1, width+2, width*2+1],
+ [1, width, width+1, width*2+1]
+];
+
+const oTetromino = [
+ [0, 1, width, width+1],
+ [0, 1, width, width+1],
+ [0, 1, width, width+1],
+ [0, 1, width, width+1]
+];
+
+const iTetromino = [
+ [1, width+1, width*2+1, width*3+1],
+ [width, width+1, width+2, width+3],
+ [1, width+1, width*2+1, width*3+1],
+ [width, width+1, width+2, width+3]
+];
+
+const theTetrominoes = [lTetromino, zTetromino, tTetromino, oTetromino, iTetromino];
+
+let currentPosition = 4;
+let currentRotation = 0;
+let random = Math.floor(Math.random() * theTetrominoes.length);
+let current = theTetrominoes[random][currentRotation];
+
+function draw() {
+ current.forEach(index => {
+ squares[currentPosition + index].classList.add('tetromino');
+ squares[currentPosition + index].style.backgroundColor = colors[random];
+ });
+}
+
+function undraw() {
+ current.forEach(index => {
+ squares[currentPosition + index].classList.remove('tetromino');
+ squares[currentPosition + index].style.backgroundColor = '';
+ });
+}
+
+function control(e) {
+ if (isPaused) return;
+
+ if (e.keyCode === 37) {
+ moveLeft();
+ } else if (e.keyCode === 38) {
+ rotate();
+ } else if (e.keyCode === 39) {
+ moveRight();
+ } else if (e.keyCode === 40) {
+ moveDown();
+ }
+}
+
+document.addEventListener('keydown', control);
+
+function moveDown() {
+ undraw();
+ currentPosition += width;
+ draw();
+ freeze();
+}
+
+function freeze() {
+ if (current.some(index => squares[currentPosition + index + width].classList.contains('taken'))) {
+ current.forEach(index => squares[currentPosition + index].classList.add('taken'));
+ random = nextRandom;
+ nextRandom = Math.floor(Math.random() * theTetrominoes.length);
+ current = theTetrominoes[random][currentRotation];
+ currentPosition = 4;
+ draw();
+ displayShape();
+ addScore();
+ gameOver();
+ }
+}
+
+function moveLeft() {
+ undraw();
+ const isAtLeftEdge = current.some(index => (currentPosition + index) % width === 0);
+
+ if (!isAtLeftEdge) currentPosition -= 1;
+
+ if (current.some(index => squares[currentPosition + index].classList.contains('taken'))) {
+ currentPosition += 1;
+ }
+
+ draw();
+}
+
+function moveRight() {
+ undraw();
+ const isAtRightEdge = current.some(index => (currentPosition + index) % width === width - 1);
+
+ if (!isAtRightEdge) currentPosition += 1;
+
+ if (current.some(index => squares[currentPosition + index].classList.contains('taken'))) {
+ currentPosition -= 1;
+ }
+
+ draw();
+}
+
+function rotate() {
+ undraw();
+ currentRotation++;
+ if (currentRotation === current.length) {
+ currentRotation = 0;
+ }
+ current = theTetrominoes[random][currentRotation];
+ draw();
+}
+
+function displayShape() {
+ miniSquares.forEach(square => {
+ square.classList.remove('tetromino');
+ square.style.backgroundColor = '';
+ });
+
+ theTetrominoes[nextRandom][0].forEach(index => {
+ miniSquares[index].classList.add('tetromino');
+ miniSquares[index].style.backgroundColor = colors[nextRandom];
+ });
+}
+
+startButton.addEventListener('click', () => {
+ if (timerId) {
+ clearInterval(timerId);
+ timerId = null;
+ isPaused = true;
+ startButton.textContent = 'Start';
+ } else {
+ draw();
+ timerId = setInterval(moveDown, 1000);
+ isPaused = false;
+ startButton.textContent = 'Pause';
+ }
+});
+
+function addScore() {
+ for (let i = 0; i < 199; i += width) {
+ const row = [i, i+1, i+2, i+3, i+4, i+5, i+6, i+7, i+8, i+9];
+
+ if (row.every(index => squares[index].classList.contains('taken'))) {
+ score += 10;
+ scoreDisplay.textContent = score;
+ row.forEach(index => {
+ squares[index].classList.remove('taken');
+ squares[index].classList.remove('tetromino');
+ squares[index].style.backgroundColor = '';
+ });
+
+ const squaresRemoved = squares.splice(i, width);
+ squares = squaresRemoved.concat(squares);
+ squares.forEach(cell => grid.appendChild(cell));
+ }
+ }
+}
+
+function gameOver() {
+ if (current.some(index => squares[currentPosition + index].classList.contains('taken'))) {
+ scoreDisplay.textContent = 'end';
+ clearInterval(timerId);
+ isPaused = true;
+ }
+}
\ No newline at end of file
diff --git a/style.css b/style.css
new file mode 100644
index 0000000..83313da
--- /dev/null
+++ b/style.css
@@ -0,0 +1,83 @@
+:root {
+ --primary: #2c3e50;
+ --secondary: #34495e;
+ --accent: #e74c3c;
+ --text: #ecf0f1;
+}
+
+* {
+ margin: 0;
+ padding: 0;
+ box-sizing: border-box;
+}
+
+body {
+ font-family: 'Arial', sans-serif;
+ background: var(--primary);
+ color: var(--text);
+ min-height: 100vh;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+}
+
+h1 {
+ text-align: center;
+ margin-bottom: 2rem;
+ font-size: 3rem;
+ color: var(--accent);
+}
+
+.game-container {
+ display: flex;
+ gap: 2rem;
+}
+
+.grid, .mini-grid {
+ display: grid;
+ background: var(--secondary);
+ border: 2px solid var(--accent);
+}
+
+.grid {
+ grid-template-rows: repeat(20, 20px);
+ grid-template-columns: repeat(10, 20px);
+}
+
+.mini-grid {
+ grid-template-rows: repeat(4, 20px);
+ grid-template-columns: repeat(4, 20px);
+ margin-top: 1rem;
+}
+
+.sidebar {
+ display: flex;
+ flex-direction: column;
+ gap: 2rem;
+}
+
+.score {
+ text-align: center;
+}
+
+.start-button {
+ padding: 0.5rem 1rem;
+ background: var(--accent);
+ color: var(--text);
+ border: none;
+ border-radius: 4px;
+ cursor: pointer;
+ font-size: 1rem;
+ transition: background 0.3s;
+}
+
+.start-button:hover {
+ background: #c0392b;
+}
+
+@media (max-width: 600px) {
+ .game-container {
+ flex-direction: column;
+ align-items: center;
+ }
+}
\ No newline at end of file