commit 1d99f7ee6948cd292c8d92a01f307cfdf9921e83
Author: root <root@hub.scroll.pub> Date: 2024-12-27 17:38:43 +0000 Subject: Initial commit diff --git a/body.html b/body.html new file mode 100644 index 0000000..6ad22cd --- /dev/null +++ b/body.html @@ -0,0 +1,20 @@ +<main class="game-container"> + <div class="game-ui"> + <div class="stats"> + <div class="health">HP: <span id="playerHealth">100</span></div> + <div class="score">Score: <span id="playerScore">0</span></div> + </div> + <div id="dialogue" class="dialogue"></div> + </div> + + <div id="gameWorld" class="game-world"> + <div id="player" class="character player"></div> + <div id="enemy" class="character enemy"></div> + <div id="npc" class="character npc"></div> + </div> + + <div class="controls"> + <button id="attackBtn" class="game-btn">Attack</button> + <button id="talkBtn" class="game-btn">Talk</button> + </div> +</main> diff --git a/index.scroll b/index.scroll new file mode 100644 index 0000000..f89a0c6 --- /dev/null +++ b/index.scroll @@ -0,0 +1,8 @@ +buildHtml +baseUrl https://pixelquest.scroll.pub +metaTags +editButton /edit.html +title PixelQuest - Browser RPG Adventure +style.css +body.html +script.js diff --git a/prompt.json b/prompt.json new file mode 100644 index 0000000..7f71dda --- /dev/null +++ b/prompt.json @@ -0,0 +1,20 @@ +{ + "id": "msg_014S1ZaSNaqkbEGpKCpX9aBM", + "type": "message", + "role": "assistant", + "model": "claude-3-5-sonnet-20241022", + "content": [ + { + "type": "text", + "text": "I'll help create this RPG game website. For the domain, I suggest:\n\n---domain---\npixelquest.scroll.pub\n\n---index.scroll---\nbuildHtml\nbaseUrl https://pixelquest.scroll.pub\nmetaTags\neditButton /edit.html\ntitle PixelQuest - Browser RPG Adventure\nstyle.css\nbody.html\nscript.js\n\n---body.html---\n<main class=\"game-container\">\n <div class=\"game-ui\">\n <div class=\"stats\">\n <div class=\"health\">HP: <span id=\"playerHealth\">100</span></div>\n <div class=\"score\">Score: <span id=\"playerScore\">0</span></div>\n </div>\n <div id=\"dialogue\" class=\"dialogue\"></div>\n </div>\n \n <div id=\"gameWorld\" class=\"game-world\">\n <div id=\"player\" class=\"character player\"></div>\n <div id=\"enemy\" class=\"character enemy\"></div>\n <div id=\"npc\" class=\"character npc\"></div>\n </div>\n\n <div class=\"controls\">\n <button id=\"attackBtn\" class=\"game-btn\">Attack</button>\n <button id=\"talkBtn\" class=\"game-btn\">Talk</button>\n </div>\n</main>\n\n---style.css---\n:root {\n --primary-color: #2a2356;\n --accent-color: #7b61ff;\n --text-color: #ffffff;\n --bg-color: #1a1625;\n}\n\n* {\n margin: 0;\n padding: 0;\n box-sizing: border-box;\n}\n\nbody {\n background: var(--bg-color);\n color: var(--text-color);\n font-family: 'Segoe UI', system-ui, sans-serif;\n min-height: 100vh;\n display: flex;\n justify-content: center;\n align-items: center;\n}\n\n.game-container {\n position: relative;\n width: 800px;\n height: 600px;\n max-width: 95vw;\n max-height: 90vh;\n background: var(--primary-color);\n border-radius: 12px;\n box-shadow: 0 0 40px rgba(123, 97, 255, 0.2);\n overflow: hidden;\n}\n\n.game-world {\n width: 100%;\n height: 80%;\n position: relative;\n background: linear-gradient(45deg, #1a1625 25%, transparent 25%),\n linear-gradient(-45deg, #1a1625 25%, transparent 25%),\n linear-gradient(45deg, transparent 75%, #1a1625 75%),\n linear-gradient(-45deg, transparent 75%, #1a1625 75%);\n background-size: 20px 20px;\n background-position: 0 0, 0 10px, 10px -10px, -10px 0px;\n}\n\n.character {\n position: absolute;\n width: 32px;\n height: 32px;\n transition: all 0.2s ease;\n}\n\n.player {\n background: var(--accent-color);\n border-radius: 50%;\n box-shadow: 0 0 20px rgba(123, 97, 255, 0.4);\n}\n\n.enemy {\n background: #ff6161;\n clip-path: polygon(50% 0%, 100% 50%, 50% 100%, 0% 50%);\n}\n\n.npc {\n background: #61ff8d;\n clip-path: polygon(50% 0%, 100% 100%, 0% 100%);\n}\n\n.game-ui {\n padding: 1rem;\n display: flex;\n justify-content: space-between;\n}\n\n.stats {\n display: flex;\n gap: 1rem;\n font-size: 1.2rem;\n font-weight: bold;\n}\n\n.dialogue {\n position: absolute;\n bottom: 80px;\n left: 50%;\n transform: translateX(-50%);\n background: rgba(42, 35, 86, 0.9);\n padding: 1rem;\n border-radius: 8px;\n display: none;\n}\n\n.controls {\n position: absolute;\n bottom: 1rem;\n left: 50%;\n transform: translateX(-50%);\n display: flex;\n gap: 1rem;\n}\n\n.game-btn {\n padding: 0.8rem 1.5rem;\n background: var(--accent-color);\n border: none;\n border-radius: 6px;\n color: var(--text-color);\n font-weight: bold;\n cursor: pointer;\n transition: transform 0.2s ease;\n}\n\n.game-btn:hover {\n transform: translateY(-2px);\n}\n\n@media (max-width: 600px) {\n .game-container {\n height: 100vh;\n max-height: none;\n border-radius: 0;\n }\n \n .controls {\n bottom: 2rem;\n }\n}\n\n---script.js---\nclass Character {\n constructor(element, x, y) {\n this.element = element;\n this.x = x;\n this.y = y;\n this.health = 100;\n this.updatePosition();\n }\n\n updatePosition() {\n this.element.style.left = `${this.x}px`;\n this.element.style.top = `${this.y}px`;\n }\n\n moveBy(dx, dy) {\n const worldBounds = document.getElementById('gameWorld').getBoundingClientRect();\n this.x = Math.max(0, Math.min(this.x + dx, worldBounds.width - 32));\n this.y = Math.max(0, Math.min(this.y + dy, worldBounds.height - 32));\n this.updatePosition();\n }\n}\n\nclass Player extends Character {\n constructor(element) {\n super(element, 100, 100);\n this.score = 0;\n this.setupControls();\n }\n\n setupControls() {\n document.addEventListener('keydown', (e) => {\n const speed = 5;\n switch(e.key) {\n case 'ArrowUp': this.moveBy(0, -speed); break;\n case 'ArrowDown': this.moveBy(0, speed); break;\n case 'ArrowLeft': this.moveBy(-speed, 0); break;\n case 'ArrowRight': this.moveBy(speed, 0); break;\n }\n });\n }\n}\n\nclass Enemy extends Character {\n constructor(element) {\n super(element, 300, 100);\n this.patrolPoints = [[300, 100], [500, 100], [500, 300], [300, 300]];\n this.currentPoint = 0;\n this.startPatrol();\n }\n\n startPatrol() {\n setInterval(() => {\n const target = this.patrolPoints[this.currentPoint];\n const dx = target[0] - this.x;\n const dy = target[1] - this.y;\n const distance = Math.sqrt(dx * dx + dy * dy);\n \n if (distance < 2) {\n this.currentPoint = (this.currentPoint + 1) % this.patrolPoints.length;\n } else {\n this.moveBy(dx/distance * 2, dy/distance * 2);\n }\n }, 50);\n }\n}\n\nclass NPC extends Character {\n constructor(element) {\n super(element, 200, 200);\n this.setupInteraction();\n this.startRandomMovement();\n }\n\n setupInteraction() {\n this.element.addEventListener('click', () => {\n const dialogue = document.getElementById('dialogue');\n dialogue.textContent = \"Hello traveler! Welcome to PixelQuest!\";\n dialogue.style.display = 'block';\n setTimeout(() => {\n dialogue.style.display = 'none';\n }, 3000);\n });\n }\n\n startRandomMovement() {\n setInterval(() => {\n const dx = (Math.random() - 0.5) * 4;\n const dy = (Math.random() - 0.5) * 4;\n this.moveBy(dx, dy);\n }, 1000);\n }\n}\n\n// Initialize game\ndocument.addEventListener('DOMContentLoaded', () => {\n const player = new Player(document.getElementById('player'));\n const enemy = new Enemy(document.getElementById('enemy'));\n const npc = new NPC(document.getElementById('npc'));\n\n // Setup attack button\n document.getElementById('attackBtn').addEventListener('click', () => {\n const distance = Math.hypot(enemy.x - player.x, enemy.y - player.y);\n if (distance < 50) {\n enemy.health -= 20;\n player.score += 10;\n document.getElementById('playerScore').textContent = player.score;\n if (enemy.health <= 30) {\n enemy.moveBy((enemy.x - player.x) * 2, (enemy.y - player.y) * 2);\n }\n }\n });\n});\n\n---end---\n\nThis implementation creates a simple but engaging RPG game with:\n- Smooth character movements and animations\n- Enemy AI with patrol patterns and escape mechanics\n- Interactive NPC with dialogue\n- Player controls via keyboard and buttons\n- Responsive design that works on mobile devices\n- Modern visual effects using CSS\n- Clean, modular code structure\n\nThe game features a dark fantasy theme with glowing effects and geometric character designs. The code is organized into classes for easy expansion and maintenance." + } + ], + "stop_reason": "end_turn", + "stop_sequence": null, + "usage": { + "input_tokens": 526, + "cache_creation_input_tokens": 0, + "cache_read_input_tokens": 0, + "output_tokens": 2471 + } +} \ No newline at end of file diff --git a/readme.scroll b/readme.scroll new file mode 100644 index 0000000..0555a94 --- /dev/null +++ b/readme.scroll @@ -0,0 +1,2 @@ +# pixelquest.scroll.pub +Website generated by Claude from prompt: Create a browser based HTML RPG game: Generate in-line JavaScript code for a simple RPG game AI. The AI governs NPCs and enemies in a browser-based game. The AI should include: Features: Enemy AI Behavior: Basic Attack Logic: Enemies detect the player within a specific range and attack when in proximity. Patrol Mode: Enemies follow a predefined path when not engaged. Escape Mechanic: Enemies flee when their health drops below a threshold. NPC Behavior: Interaction Logic: NPCs respond to player actions, such as initiating dialogues when clicked. Movement Patterns: NPCs roam randomly within a defined area. Player Commands: Allow the player to control interactions (e.g., attack, talk) via simple button clicks or keypresses. HTML Integration: Render characters and environments using <div> elements styled with CSS. Update positions dynamically with JavaScript. Scalability: Code should be modular for adding more characters, behaviors, or levels. Output Example: Provide a minimal working example with: An enemy that patrols and attacks the player on proximity. An NPC that displays a message when clicked. Basic player movement with arrow keys. \ No newline at end of file diff --git a/script.js b/script.js new file mode 100644 index 0000000..6dd9faf --- /dev/null +++ b/script.js @@ -0,0 +1,112 @@ +class Character { + constructor(element, x, y) { + this.element = element; + this.x = x; + this.y = y; + this.health = 100; + this.updatePosition(); + } + + updatePosition() { + this.element.style.left = `${this.x}px`; + this.element.style.top = `${this.y}px`; + } + + moveBy(dx, dy) { + const worldBounds = document.getElementById('gameWorld').getBoundingClientRect(); + this.x = Math.max(0, Math.min(this.x + dx, worldBounds.width - 32)); + this.y = Math.max(0, Math.min(this.y + dy, worldBounds.height - 32)); + this.updatePosition(); + } +} + +class Player extends Character { + constructor(element) { + super(element, 100, 100); + this.score = 0; + this.setupControls(); + } + + setupControls() { + document.addEventListener('keydown', (e) => { + const speed = 5; + switch(e.key) { + case 'ArrowUp': this.moveBy(0, -speed); break; + case 'ArrowDown': this.moveBy(0, speed); break; + case 'ArrowLeft': this.moveBy(-speed, 0); break; + case 'ArrowRight': this.moveBy(speed, 0); break; + } + }); + } +} + +class Enemy extends Character { + constructor(element) { + super(element, 300, 100); + this.patrolPoints = [[300, 100], [500, 100], [500, 300], [300, 300]]; + this.currentPoint = 0; + this.startPatrol(); + } + + startPatrol() { + setInterval(() => { + const target = this.patrolPoints[this.currentPoint]; + const dx = target[0] - this.x; + const dy = target[1] - this.y; + const distance = Math.sqrt(dx * dx + dy * dy); + + if (distance < 2) { + this.currentPoint = (this.currentPoint + 1) % this.patrolPoints.length; + } else { + this.moveBy(dx/distance * 2, dy/distance * 2); + } + }, 50); + } +} + +class NPC extends Character { + constructor(element) { + super(element, 200, 200); + this.setupInteraction(); + this.startRandomMovement(); + } + + setupInteraction() { + this.element.addEventListener('click', () => { + const dialogue = document.getElementById('dialogue'); + dialogue.textContent = "Hello traveler! Welcome to PixelQuest!"; + dialogue.style.display = 'block'; + setTimeout(() => { + dialogue.style.display = 'none'; + }, 3000); + }); + } + + startRandomMovement() { + setInterval(() => { + const dx = (Math.random() - 0.5) * 4; + const dy = (Math.random() - 0.5) * 4; + this.moveBy(dx, dy); + }, 1000); + } +} + +// Initialize game +document.addEventListener('DOMContentLoaded', () => { + const player = new Player(document.getElementById('player')); + const enemy = new Enemy(document.getElementById('enemy')); + const npc = new NPC(document.getElementById('npc')); + + // Setup attack button + document.getElementById('attackBtn').addEventListener('click', () => { + const distance = Math.hypot(enemy.x - player.x, enemy.y - player.y); + if (distance < 50) { + enemy.health -= 20; + player.score += 10; + document.getElementById('playerScore').textContent = player.score; + if (enemy.health <= 30) { + enemy.moveBy((enemy.x - player.x) * 2, (enemy.y - player.y) * 2); + } + } + }); +}); diff --git a/style.css b/style.css new file mode 100644 index 0000000..44d0bbb --- /dev/null +++ b/style.css @@ -0,0 +1,129 @@ +:root { + --primary-color: #2a2356; + --accent-color: #7b61ff; + --text-color: #ffffff; + --bg-color: #1a1625; +} + +* { + margin: 0; + padding: 0; + box-sizing: border-box; +} + +body { + background: var(--bg-color); + color: var(--text-color); + font-family: 'Segoe UI', system-ui, sans-serif; + min-height: 100vh; + display: flex; + justify-content: center; + align-items: center; +} + +.game-container { + position: relative; + width: 800px; + height: 600px; + max-width: 95vw; + max-height: 90vh; + background: var(--primary-color); + border-radius: 12px; + box-shadow: 0 0 40px rgba(123, 97, 255, 0.2); + overflow: hidden; +} + +.game-world { + width: 100%; + height: 80%; + position: relative; + background: linear-gradient(45deg, #1a1625 25%, transparent 25%), + linear-gradient(-45deg, #1a1625 25%, transparent 25%), + linear-gradient(45deg, transparent 75%, #1a1625 75%), + linear-gradient(-45deg, transparent 75%, #1a1625 75%); + background-size: 20px 20px; + background-position: 0 0, 0 10px, 10px -10px, -10px 0px; +} + +.character { + position: absolute; + width: 32px; + height: 32px; + transition: all 0.2s ease; +} + +.player { + background: var(--accent-color); + border-radius: 50%; + box-shadow: 0 0 20px rgba(123, 97, 255, 0.4); +} + +.enemy { + background: #ff6161; + clip-path: polygon(50% 0%, 100% 50%, 50% 100%, 0% 50%); +} + +.npc { + background: #61ff8d; + clip-path: polygon(50% 0%, 100% 100%, 0% 100%); +} + +.game-ui { + padding: 1rem; + display: flex; + justify-content: space-between; +} + +.stats { + display: flex; + gap: 1rem; + font-size: 1.2rem; + font-weight: bold; +} + +.dialogue { + position: absolute; + bottom: 80px; + left: 50%; + transform: translateX(-50%); + background: rgba(42, 35, 86, 0.9); + padding: 1rem; + border-radius: 8px; + display: none; +} + +.controls { + position: absolute; + bottom: 1rem; + left: 50%; + transform: translateX(-50%); + display: flex; + gap: 1rem; +} + +.game-btn { + padding: 0.8rem 1.5rem; + background: var(--accent-color); + border: none; + border-radius: 6px; + color: var(--text-color); + font-weight: bold; + cursor: pointer; + transition: transform 0.2s ease; +} + +.game-btn:hover { + transform: translateY(-2px); +} + +@media (max-width: 600px) { + .game-container { + height: 100vh; + max-height: none; + border-radius: 0; + } + + .controls { + bottom: 2rem; + } +}