ノート

重力フラックス:物理ベースの飛行回避ゲーム

フリーのプロンプト百科事典 Wikiprompt より

loshu2000

2026年5月17日

重力フラックス:物理ベースの飛行回避ゲーム 物理ベースのゲームプレイ、手続き型ベジェ障害物、Web Audio合成、禅のようなパステル調の美学を備えた単一ファイルHTMLゲームを生成するための詳細なプロンプト。

プロンプト内容保存

🌐
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Gravity Flux</title> <style> body { margin: 0; overflow: hidden; background: #1a1a2e; font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; } canvas { display: block; cursor: none; } #ui { position: fixed; top: 20px; left: 20px; color: #e0e0e0; font-size: 14px; letter-spacing: 2px; text-transform: uppercase; opacity: 0.8; pointer-events: none; z-index: 10; } #ui h1 { font-size: 18px; margin: 0 0 10px 0; font-weight: 300; color: #c0c0c0; } #ui p { margin: 5px 0; font-size: 12px; color: #a0a0a0; } #score { font-size: 24px; font-weight: 700; color: #ffffff; text-shadow: 0 0 20px rgba(255,255,255,0.3); } #gameOver { position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%); text-align: center; color: #e0e0e0; display: none; z-index: 20; background: rgba(26,26,46,0.9); padding: 40px 60px; border-radius: 10px; border: 1px solid rgba(255,255,255,0.1); backdrop-filter: blur(10px); } #gameOver h2 { font-size: 36px; margin: 0 0 20px 0; font-weight: 300; letter-spacing: 4px; } #gameOver button { background: transparent; border: 1px solid #e0e0e0; color: #e0e0e0; padding: 12px 30px; font-size: 14px; letter-spacing: 2px; cursor: pointer; transition: all 0.3s; text-transform: uppercase; } #gameOver button:hover { background: #e0e0e0; color: #1a1a2e; } #controls { position: fixed; bottom: 20px; left: 50%; transform: translateX(-50%); color: #a0a0a0; font-size: 12px; letter-spacing: 1px; text-align: center; opacity: 0.6; pointer-events: none; z-index: 10; } </style> </head> <body> <div id="ui"> <h1>Gravity Flux</h1> <p>Score: <span id="score">0</span></p> <p>Altitude: <span id="altitude">0</span></p> </div> <div id="gameOver"> <h2>Flux Collapse</h2> <p style="margin-bottom: 20px; color: #a0a0a0;">The sphere has been crushed</p> <button onclick="restartGame()">Re-enter Flux</button> </div> <div id="controls"> MOUSE MOVE - Navigate &nbsp;|&nbsp; CLICK - Boost &nbsp;|&nbsp; SPACE - Pause </div> <canvas id="gameCanvas"></canvas> <script> // ============================================ // GRAVITY FLUX - Physics-based flight evasion // ============================================ const canvas = document.getElementById('gameCanvas'); const ctx = canvas.getContext('2d'); const scoreEl = document.getElementById('score'); const altitudeEl = document.getElementById('altitude'); const gameOverEl = document.getElementById('gameOver'); // Canvas sizing function resizeCanvas() { canvas.width = window.innerWidth; canvas.height = window.innerHeight; } resizeCanvas(); window.addEventListener('resize', resizeCanvas); // ============================================ // AUDIO SYSTEM - Web Audio API // ============================================ let audioCtx = null; let masterGain = null; let pulseOsc = null; let pulseGain = null; let ambientGain = null; function initAudio() { if (audioCtx) return; audioCtx = new (window.AudioContext || window.webkitAudioContext)(); masterGain = audioCtx.createGain(); masterGain.gain.value = 0.3; masterGain.connect(audioCtx.destination); // Ambient drone ambientGain = audioCtx.createGain(); ambientGain.gain.value = 0.15; ambientGain.connect(masterGain); const osc1 = audioCtx.createOscillator(); osc1.type = 'sine'; osc1.frequency.value = 55; const osc2 = audioCtx.createOscillator(); osc2.type = 'sine'; osc2.frequency.value = 55.5; const osc3 = audioCtx.createOscillator(); osc3.type = 'sine'; osc3.frequency.value = 110; const g1 = audioCtx.createGain(); g1.gain.value = 0.5; const g2 = audioCtx.createGain(); g2.gain.value = 0.3; const g3 = audioCtx.createGain(); g3.gain.value = 0.2; osc1.connect(g1); osc2.connect(g2); osc3.connect(g3); g1.connect(ambientGain); g2.connect(ambientGain); g3.connect(ambientGain); osc1.start(); osc2.start(); osc3.start(); // Pulse oscillator pulseOsc = audioCtx.createOscillator(); pulseOsc.type = 'sine'; pulseOsc.frequency.value = 220; pulseGain = audioCtx.createGain(); pulseGain.gain.value = 0; pulseOsc.connect(pulseGain); pulseGain.connect(masterGain); pulseOsc.start(); } function playPulse(freq = 220, duration = 0.3, volume = 0.2) { if (!audioCtx) return; const osc = audioCtx.createOscillator(); osc.type = 'sine'; osc.frequency.setValueAtTime(freq, audioCtx.currentTime); osc.frequency.exponentialRampToValueAtTime(freq * 0.5, audioCtx.currentTime + duration); const gain = audioCtx.createGain(); gain.gain.setValueAtTime(volume, audioCtx.currentTime); gain.gain.exponentialRampToValueAtTime(0.001, audioCtx.currentTime + duration); osc.connect(gain); gain.connect(masterGain); osc.start(); osc.stop(audioCtx.currentTime + duration); } function playGateSweep() { if (!audioCtx) return; const osc = audioCtx.createOscillator(); osc.type = 'sine'; osc.frequency.setValueAtTime(400, audioCtx.currentTime); osc.frequency.exponentialRampToValueAtTime(1200, audioCtx.currentTime + 0.4); const gain = audioCtx.createGain(); gain.gain.setValueAtTime(0.3, audioCtx.currentTime); gain.gain.exponentialRampToValueAtTime(0.001, audioCtx.currentTime + 0.4); osc.connect(gain); gain.connect(masterGain); osc.start(); osc.stop(audioCtx.currentTime + 0.4); } // ============================================ // GAME STATE // ============================================ let gameRunning = true; let paused = false; let score = 0; let gameOver = false; let lastTime = 0; let time = 0; // Player sphere const player = { x: 0, y: 0, vx: 0, vy: 0, radius: 18, targetRadius: 18, baseRadius: 18, inflation: 0, targetX: 0, targetY: 0, boost: false, boostCooldown: 0 }; // Camera / world scroll let worldY = 0; let worldSpeed = 80; // pixels per second // Obstacles let obstacles = []; let nextObstacleY = 0; const OBSTACLE_SPACING = 300; // ============================================ // PROCEDURAL OBSTACLE GENERATION // ============================================ class Obstacle { constructor(y) { this.y = y; this.gateSize = 120 + Math.random() * 80; this.centerX = canvas.width / 2 + (Math.random() - 0.5) * 200; this.phase = Math.random() * Math.PI * 2; this.speed = 0.5 + Math.random() * 1.5; this.amplitude = 20 + Math.random() * 30; this.thickness = 15 + Math.random() * 10; this.passed = false; this.points = []; this.generatePoints(); } generatePoints() { this.points = []; const segments = 8; for (let i = 0; i <= segments; i++) { const t = i / segments; const x = this.centerX + (t - 0.5) * this.gateSize * 2; const y = this.y + Math.sin(t * Math.PI * 2 + this.phase) * this.amplitude; this.points.push({x, y}); } } update(dt) { this.phase += this.speed * dt; this.gateSize += Math.sin(this.phase * 0.5) * 20 * dt; this.gateSize = Math.max(60, Math.min(250, this.gateSize)); this.generatePoints(); } draw() { // Draw the gate as two bezier curves (top and bottom) const topPoints = this.points.map(p => ({x: p.x, y: p.y - this.gateSize / 2})); const bottomPoints = this.points.map(p => ({x: p.x, y: p.y + this.gateSize / 2})); ctx.strokeStyle = '#c0c0c0'; ctx.lineWidth = this.thickness; ctx.shadowColor = '#c0c0c0'; ctx.shadowBlur = 20; ctx.lineCap = 'round'; ctx.lineJoin = 'round'; // Draw top curve ctx.beginPath(); ctx.moveTo(topPoints[0].x, topPoints[0].y); for (let i = 1; i < topPoints.length; i++) { const prev = topPoints[i-1]; const curr = topPoints[i]; const midX = (prev.x + curr.x) / 2; const midY = (prev.y + curr.y) / 2; ctx.quadraticCurveTo(prev.x, prev.y, midX, midY); } ctx.stroke(); // Draw bottom curve ctx.beginPath(); ctx.moveTo(bottomPoints[0].x, bottomPoints[0].y); for (let i = 1; i < bottomPoints.length; i++) { const prev = bottomPoints[i-1]; const curr = bottomPoints[i]; const midX = (prev.x + curr.x) / 2; const midY = (prev.y + curr.y) / 2; ctx.quadraticCurveTo(prev.x, prev.y, midX, midY); } ctx.stroke(); // Draw connecting lines at edges ctx.beginPath(); ctx.moveTo(topPoints[0].x, topPoints[0].y); ctx.lineTo(bottomPoints[0].x, bottomPoints[0].y); ctx.moveTo(topPoints[topPoints.length-1].x, topPoints[topPoints.length-1].y); ctx.lineTo(bottomPoints[bottomPoints.length-1].x, bottomPoints[bottomPoints.length-1].y); ctx.stroke(); ctx.shadowBlur = 0; } checkCollision(px, py, pr) { // Check collision with top and bottom curves for (let i = 0; i < this.points.length - 1; i++) { const p1 = this.points[i]; const p2 = this.points[i+1]; // Top curve const topY1 = p1.y - this.gateSize / 2; const topY2 = p2.y - this.gateSize / 2; if (this.lineCircleCollision(p1.x, topY1, p2.x, topY2, px, py, pr)) return true; // Bottom curve const botY1 = p1.y + this.gateSize / 2; const botY2 = p2.y + this.gateSize / 2; if (this.lineCircleCollision(p1.x, botY1, p2.x, botY2, px, py, pr)) return true; } // Check side walls const leftX = this.points[0].x; const rightX = this.points[this.points.length-1].x; if (px - pr < leftX && px + pr > leftX) { const topY = this.points[0].y - this.gateSize / 2; const botY = this.points[0].y + this.gateSize / 2; if (py > topY && py < botY) return true; } if (px - pr < rightX && px + pr > rightX) { const topY = this.points[this.points.length-1].y - this.gateSize / 2; const botY = this.points[this.points.length-1].y + this.gateSize / 2; if (py > topY && py < botY) return true; } return false; } lineCircleCollision(x1, y1, x2, y2, cx, cy, r) { const dx = x2 - x1; const dy = y2 - y1; const fx = x1 - cx; const fy = y1 - cy; const a = dx * dx + dy * dy; const b = 2 * (fx * dx + fy * dy); const c = fx * fx + fy * fy - r * r; let discriminant = b * b - 4 * a * c; if (discriminant < 0) return false; discriminant = Math.sqrt(discriminant); const t1 = (-b - discriminant) / (2 * a); const t2 = (-b + discriminant) / (2 * a); if (t1 >= 0 && t1 <= 1) return true; if (t2 >= 0 && t2 <= 1) return true; return false; } } // ============================================ // INITIALIZATION // ============================================ function init() { player.x = canvas.width / 2; player.y = canvas.height * 0.7; player.targetX = player.x; player.targetY = player.y; player.radius = player.baseRadius; player.inflation = 0; player.boost = false; player.boostCooldown = 0; worldY = 0; worldSpeed = 80; score = 0; gameOver = false; gameOverEl.style.display = 'none'; obstacles = []; nextObstacleY = -200; // Generate initial obstacles for (let i = 0; i < 5; i++) { const obs = new Obstacle(nextObstacleY); obstacles.push(obs); nextObstacleY -= OBSTACLE_SPACING; } // Reset audio if (audioCtx) { audioCtx.resume(); } } // ============================================ // GAME LOOP // ============================================ function update(dt) { if (paused || gameOver) return; time += dt; worldSpeed = 80 + score * 0.5; // Player physics const mouseX = player.targetX; const mouseY = player.targetY; // Spring physics for smooth movement const springForce = 8; const damping = 0.85; player.vx += (mouseX - player.x) * springForce * dt; player.vy += (mouseY - player.y) * springForce * dt; player.vx *= damping; player.vy *= damping; // Boost if (player.boost && player.boostCooldown <= 0) { player.vy -= 300 * dt; player.boostCooldown = 0.5; playPulse(440, 0.2, 0.1); } player.boostCooldown -= dt; player.x += player.vx * dt; player.y += player.vy * dt; // Keep in bounds player.x = Math.max(player.radius, Math.min(canvas.width - player.radius, player.x)); player.y = Math.max(player.radius, Math.min(canvas.height - player.radius, player.y)); // Inflation/deflation based on altitude const altitude = canvas.height - player.y; const targetInflation = Math.max(0, (altitude - 100) / 500); player.inflation += (targetInflation - player.inflation) * dt * 2; player.radius = player.baseRadius + player.inflation * 10; // World scroll worldY += worldSpeed * dt; // Update obstacles for (let i = obstacles.length - 1; i >= 0; i--) { const obs = obstacles[i]; obs.y += worldSpeed * dt; obs.update(dt); // Check collision if (obs.checkCollision(player.x, player.y, player.radius)) { endGame(); return; } // Check if passed if (!obs.passed && obs.y > player.y + player.radius) { obs.passed = true; score++; scoreEl.textContent = score; playGateSweep(); } // Remove if off screen if (obs.y > canvas.height + 100) { obstacles.splice(i, 1); } } // Generate new obstacles if (obstacles.length < 5) { const lastY = obstacles.length > 0 ? Math.min(...obstacles.map(o => o.y)) : 0; const newObs = new Obstacle(lastY - OBSTACLE_SPACING); obstacles.push(newObs); } // Update altitude display altitudeEl.textContent = Math.max(0, Math.floor(altitude)); // Ambient pulse if (audioCtx && Math.random() < dt * 0.5) { playPulse(110 + Math.random() * 110, 0.5, 0.05); } } function draw() { // Clear with gradient background const gradient = ctx.createLinearGradient(0, 0, 0, canvas.height); gradient.addColorStop(0, '#1a1a2e'); gradient.addColorStop(0.5, '#16213e'); gradient.addColorStop(1, '#0f3460'); ctx.fillStyle = gradient; ctx.fillRect(0, 0, canvas.width, canvas.height); // Draw subtle grid lines ctx.strokeStyle = 'rgba(255,255,255,0.03)'; ctx.lineWidth = 1; for (let y = 0; y < canvas.height; y += 50) { ctx.beginPath(); ctx.moveTo(0, y); ctx.lineTo(canvas.width, y); ctx.stroke(); } for (let x = 0; x < canvas.width; x += 50) { ctx.beginPath(); ctx.moveTo(x, 0); ctx.lineTo(x, canvas.height); ctx.stroke(); } // Draw obstacles for (const obs of obstacles) { obs.draw(); } // Draw player sphere ctx.save(); ctx.shadowColor = '#e0e0e0'; ctx.shadowBlur = 30; // Outer glow const glowGradient = ctx.createRadialGradient( player.x, player.y, 0, player.x, player.y, player.radius * 2 ); glowGradient.addColorStop(0, 'rgba(255,255,255,0.3)'); glowGradient.addColorStop(1, 'rgba(255,255,255,0)'); ctx.fillStyle = glowGradient; ctx.beginPath(); ctx.arc(player.x, player.y, player.radius * 2, 0, Math.PI * 2); ctx.fill(); // Main sphere const sphereGradient = ctx.createRadialGradient( player.x - player.radius * 0.3, player.y - player.radius * 0.3, 0, player.x, player.y, player.radius ); sphereGradient.addColorStop(0, '#ffffff'); sphereGradient.addColorStop(0.7, '#e0e0e0'); sphereGradient.addColorStop(1, '#a0a0a0'); ctx.fillStyle = sphereGradient; ctx.beginPath(); ctx.arc(player.x, player.y, player.radius, 0, Math.PI * 2); ctx.fill(); // Inner detail ctx.shadowBlur = 0; ctx.strokeStyle = 'rgba(255,255,255,0.3)'; ctx.lineWidth = 1; ctx.beginPath(); ctx.arc(player.x, player.y, player.radius * 0.6, 0, Math.PI * 2); ctx.stroke(); ctx.restore(); // Draw boost indicator if (player.boostCooldown > 0) { ctx.fillStyle = 'rgba(255,255,255,0.2)'; ctx.beginPath(); ctx.arc(player.x, player.y, player.radius + 10, 0, Math.PI * 2); ctx.fill(); } } function endGame() { gameOver = true; gameOverEl.style.display = 'block'; playPulse(80, 1, 0.3); } function restartGame() { init(); } // ============================================ // MAIN LOOP // ============================================ let lastFrameTime = performance.now(); function gameLoop(timestamp) { const dt = Math.min((timestamp - lastFrameTime) / 1000, 0.05); lastFrameTime = timestamp; update(dt); draw(); requestAnimationFrame(gameLoop); } // ============================================ // EVENT LISTENERS // ============================================ canvas.addEventListener('mousemove', (e) => { player.targetX = e.clientX; player.targetY = e.clientY; }); canvas.addEventListener('click', () => { initAudio(); player.boost = true; setTimeout(() => player.boost = false, 100); }); canvas.addEventListener('contextmenu', (e) => { e.preventDefault(); player.boost = true; setTimeout(() => player.boost = false, 100); }); window.addEventListener('keydown', (e) => { if (e.code === 'Space') { e.preventDefault(); paused = !paused; } }); // Initialize init(); requestAnimationFrame(gameLoop); // Start audio on first interaction document.addEventListener('click', initAudio, { once: true }); </script> </body> </html>

ログインして完全なプロンプトを表示

次で続行:

ログインすると、次に同意したことになります: 利用規約 と プライバシーポリシー

使い方

このプロンプトは coding 向けに設計されています。上の内容をコピーして、お好みの AI ツールに貼り付けてください。

最良の結果を得るには、プレースホルダー(角括弧や大文字で示された部分)を具体的な要件に置き換えてください。

参考資料

カテゴリ:coding| prompts.chat| game-development| physics-engine

ノート